Android系統init進程啟動及init.rc全解析


轉:https://blog.csdn.net/zhonglunshun/article/details/78615980

服務啟動機制
system/core/init/init.c文件main函數中parse_config_file(init.rc)讀取並解析init.rc文件內容。將service信息放置到system/core/init/init_parser.cpp的service_list中
system/core/init/init.c文件main函數繼續執行restart_servie_if_needed(…) -> service_start(…) -> Execve(…)建立service進程;
為了讓大伙看得更明白,上個圖先《總體啟動框架圖》:


init.rc 簡介
目前Linux有很多通訊機制可以在用戶空間和內核空間之間交互,例如設備驅動文件(位於/dev目錄中)、內存文件(/proc、/sys目錄等)。了解Linux的同學都應該知道Linux的重要特征之一就是一切都是以文件的形式存在的,例如,一個設備通常與一個或多個設備文件對應。這些與內核空間交互的文件都在用戶空間,所以在Linux內核裝載完,需要首先建立這些文件所在的目錄。而完成這些工作的程序就是本文要介紹的init。Init是一個命令行程序。其主要工作之一就是建立這些與內核空間交互的文件所在的目錄。當Linux內核加載完后,要做的第一件事就是調用init程序,也就是說,init是用戶空間執行的第一個程序。

盡管init完成的工作不算很多,不過代碼還是非常復雜的。Init程序並不是由一個源代碼文件組成的,而是由一組源代碼文件的目標文件鏈接而成的。這些文件位於如下的目錄。

需要明白的是,這些init.rc只是語法文件,並不是程序,真正的入口則是上面提到的system/core/init/init.c
因為init.c文件比較大,在文章的第二部分我會簡要的通過main函數分析init啟動流程;

init.rc有兩個,分別位於:
./system/core/rootdir/init.rc
./bootable/recovery/etc/init.rc
從目錄上大致可以猜測,這兩個init.rc使用場景不一樣,一個是刷機用到的,也就是進入recorvery模式,一個是正常啟動用到的;我們這里重點分析的是上面那個,也是init.c關聯的那個;

init.rc語法結構解析
要了解init.rc是怎么解析的,我們需要先看看說明文檔,說明文檔在,當然也可以看下熱心網友的中文對照版本;
init.rc位於/bootable/recovery/etc/init.rc

Android初始化語言包含了四種類型的聲明:
Actions(行為)、Commands(命令)、Services(服務)和Options(選項)

所有這些都是以行為單位的,各種記號由空格來隔開。
C語言風格的反斜杠號可用於在記號間插入空格。
雙引號也可用於防止字符串被空格分割成多個記號。
行末的反斜杠用於折行,注釋行以井號(#)開頭(允許以空格開頭)。

需要注意的是,這個只是一個語法文件,就像一個xml文件一樣,沒有執行順序的,解析器通過讀這個文件獲取想要的數據,包括service,action等

Actions和Services聲明一個新的分組Section。所有的命令或選項都屬於最近聲明的分組。位於第一個分組之前的命令或選項將會被忽略。
Actions和Services有唯一的名字。如果有重名的情況,第二個申明的將會被作為錯誤忽略。

Actions
Actions(行為)是一系列命令的開始
Actions代表一些Action.Action代表一組命令(Commands),Actions都有一個trigger(觸發器),該觸發器決定了何時執行這個Action,即在什么情況下才能執行該Action中的定義命令.當一些條件滿足觸發器的條件時,該Action中定義的命令會被添加到要執行命令隊列的尾部(如果這組命令已經在隊列中,則不會再次添加).

隊列中的每一個action都被依次提取出,而這個action中的每個command(命令)在一個Action從隊列移除時,該Action定義的命令會依次被執行.

Action的格式如下:

on <trgger> [&& <trigger>]*
<command1>
<command2>
<command3>
...
1
2
3
4
5
on后面跟着一個觸發器,當trigger被觸發時,command1,command2,command3,會依次執行,直到下一個Action或下一個Service。

簡單來說,Actions就是Android在啟動時定義的一個啟動腳本,當條件滿足時,會執行該腳本,腳本里都是一些命令commands,不同的腳本用on來區分。

Triggers(觸發器)
trigger即我們上面所說的觸發器,本質上是一個字符串,能夠匹配某種包含該字符串的事件.
trigger又被細分為事件觸發器(event trigger)和屬性觸發器(property trigger).
Triggers(觸發器)是一個用於匹配特定事件類型的字符串,用於使Actions發生。

事件觸發器可由”trigger”命令或初始化過程中通過QueueEventTrigger()觸發,通常是一些事先定義的簡單字符串,例如:boot,late-init
屬性觸發器是當指定屬性的變量值變成指定值時觸發,其格式為property:=*

一個Action可以有多個屬性觸發器,但是最多有一個事件觸發器.下面我們看兩個例子:

on boot && property:a=b
1
該Action只有在boot事件發生時,並且屬性a和b相等的情況下才會被觸發.

on property:a=b && property:c=d
1
該Action會在以下三種情況被觸發:

在啟動時,如果屬性a的值等於b並且屬性c的值等於d
在屬性c的值已經是d的情況下,屬性a的值被更新為b
在屬性a的值已經是b的情況下,屬性c的值被更新為d
當前AIL中常用的有以下幾種事件觸發器:

類型 說明
-------------------------------------------------
boot init.rc被裝載后觸發
device-added-<path> 指定設備被添加時觸發
device-removed-<path> 指定設備被移除時觸發
service-exited-<name> 在特定服務(service)退出時觸發
early-init 初始化之前觸發
late-init 初始化之后觸發
init 初始化時觸發(在 /init.conf (啟動配置文件)被裝載之后)
1
2
3
4
5
6
7
8
9
Init的觸發是由init.c里的函數action_for_each_trigger來決定的(在main函數中被調用)。

Services
Services(服務)是一個程序,以 service開頭,由init進程啟動,一般運行於另外一個init的子進程,所以啟動service前需要判斷對應的可執行文件是否存在。init生成的子進程,定義在rc文件,其中每一個service,在啟動時會通過fork方式生成子進程。Services(服務)的形式如下:

service <name> <pathname> [ <argument> ]*
<option>
<option>
...
1
2
3
4
其中:

name:服務名
pathname:當前服務對應的程序位置
option:當前服務設置的選項
argument 可選參數
init.rc文件詳解
為了方便理解,我把整個init.rc解析一邊,便於大家了解整個流程;如果想要了解recovery下的init語法解析,參考這篇文章《recovery下的init.rc語法解析》
代碼量比較大,如果覺得看起來費勁,可以挑綠色部分看;

# Copyright (C) 2012 The Android Open Source Project
#
# IMPORTANT: Do not create world writable files or directories.
# This is a common source of Android security bugs.
#

"【import <filename>一個init配置文件,擴展當前配置。】"
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.${ro.zygote}.rc
import /init.trace.rc

"【觸發條件early-init,在early-init階段調用以下行】"
on early-init
# Set init and its forked children's oom_adj.
write /proc/1/oom_score_adj -1000
"【打開路徑為<path>的一個文件,並寫入一個或多個字符串】"
# Apply strict SELinux checking of PROT_EXEC on mmap/mprotect calls.
write /sys/fs/selinux/checkreqprot 0

# Set the security context for the init process.
# This should occur before anything else (e.g. ueventd) is started.
"【這段腳本的意思是init進程啟動之后就馬上調用函數setcon將自己的安全上下文設置為“u:r:init:s0”,即將init進程的domain指定為init。】"
setcon u:r:init:s0

# Set the security context of /adb_keys if present.
"【恢復指定文件到file_contexts配置中指定的安全上線文環境】"
restorecon /adb_keys

"【執行start ueventd的命令。ueventd是一個service后面有定義】 "
start ueventd

"【mkdir <path> [mode] [owner] [group] //創建一個目錄<path>,可以選擇性地指定mode、owner以及group。如果沒有指定,默認的權限為755,並屬於root用戶和root組。】"
# create mountpoints
mkdir /mnt 0775 root system

on init
"【設置系統時鍾的基准,比如0代表GMT,即以格林尼治時間為准】"
sysclktz 0

"【設置kernel日志等級】"
loglevel 6 ####
write /proc/bootprof "INIT: on init start" ####

"【symlink <target> <path> //創建一個指向<path>的軟連接<target>。】"
# Backward compatibility
symlink /system/etc /etc
symlink /sys/kernel/debug /d

# Right now vendor lives on the same filesystem as system,
# but someday that may change.
symlink /system/vendor /vendor

"【創建一個目錄<path>,可以選擇性地指定mode、owner以及group。】"
# Create cgroup mount point for cpu accounting
mkdir /acct
mount cgroup none /acct cpuacct
mkdir /acct/uid

"【mount <type> <device> <dir> [ <mountoption> ] //在目錄<dir>掛載指定的設備。<device> 可以是以 mtd@name 的形式指定一個mtd塊設備。<mountoption>包括 ro、rw、remount、noatime、 ...】"
# Create cgroup mount point for memory
mount tmpfs none /sys/fs/cgroup mode=0750,uid=0,gid=1000
mkdir /sys/fs/cgroup/memory 0750 root system
mount cgroup none /sys/fs/cgroup/memory memory
write /sys/fs/cgroup/memory/memory.move_charge_at_immigrate 1
"【chown <owner> <group> <path> //改變文件的所有者和組。】"

"【后面的一些行因為類似,就省略了】"
.....

# Healthd can trigger a full boot from charger mode by signaling this
# property when the power button is held.
on property:sys.boot_from_charger_mode=1
"【停止指定類別服務類下的所有已運行的服務】"
class_stop charger
"【觸發一個事件,將該action排在某個action之后(用於Action排隊)】"
trigger late-init

# Load properties from /system/ + /factory after fs mount.
on load_all_props_action
"【從/system,/vendor加載屬性。默認包含在init.rc】"
load_all_props

# Indicate to fw loaders that the relevant mounts are up.
on firmware_mounts_complete
"【刪除指定路徑下的文件】"
rm /dev/.booting

# Mount filesystems and start core system services.
on late-init
"【觸發一個事件。用於將一個action與另一個 action排列。】"
trigger early-fs
trigger fs
trigger post-fs
trigger post-fs-data

# Load properties from /system/ + /factory after fs mount. Place
# this in another action so that the load will be scheduled after the prior
# issued fs triggers have completed.
trigger load_all_props_action

# Remove a file to wake up anything waiting for firmware.
trigger firmware_mounts_complete

trigger early-boot
trigger boot


on post-fs
...
"【一些創造目錄,建立鏈接,更改權限的操作,這里省略】"

on post-fs-data
...
"【一些創造目錄,建立鏈接,更改權限的操作,這里省略】"

"【恢復指定文件到file_contexts配置中指定的安全上線文環境】"
restorecon /data/mediaserver

"【將系統屬性<name>的值設置為<value>,即以鍵值對的方式設置系統屬性】"
# Reload policy from /data/security if present.
setprop selinux.reload_policy 1

"【以遞歸的方式恢復指定目錄到file_contexts配置中指定的安全上下文中】"
# Set SELinux security contexts on upgrade or policy update.
restorecon_recursive /data

# If there is no fs-post-data action in the init.<device>.rc file, you
# must uncomment this line, otherwise encrypted filesystems
# won't work.
# Set indication (checked by vold) that we have finished this action
#setprop vold.post_fs_data_done 1

on boot
"【初始化網絡】"
# basic network init
ifup lo
"【設置主機名為localhost】"
hostname localhost
"【設置域名localdomain】"
domainname localdomain

"【設置資源限制】"
# set RLIMIT_NICE to allow priorities from 19 to -20
setrlimit 13 40 40

"【這里省略了一些chmod,chown,等操作,不多解釋】"
...


# Define default initial receive window size in segments.
setprop net.tcp.default_init_rwnd 60

"【重啟core服務】"
class_start core

on nonencrypted
class_start main
class_start late_start

on property:vold.decrypt=trigger_default_encryption
start defaultcrypto

on property:vold.decrypt=trigger_encryption
start surfaceflinger
start encrypt

on property:sys.init_log_level=*
loglevel ${sys.init_log_level}

on charger
class_start charger

on property:vold.decrypt=trigger_reset_main
class_reset main

on property:vold.decrypt=trigger_load_persist_props
load_persist_props

on property:vold.decrypt=trigger_post_fs_data
trigger post-fs-data

on property:vold.decrypt=trigger_restart_min_framework
class_start main

on property:vold.decrypt=trigger_restart_framework
class_start main
class_start late_start

on property:vold.decrypt=trigger_shutdown_framework
class_reset late_start
class_reset main

on property:sys.powerctl=*
powerctl ${sys.powerctl}

# system server cannot write to /proc/sys files,
# and chown/chmod does not work for /proc/sys/ entries.
# So proxy writes through init.
on property:sys.sysctl.extra_free_kbytes=*
write /proc/sys/vm/extra_free_kbytes ${sys.sysctl.extra_free_kbytes}

# "tcp_default_init_rwnd" Is too long!
on property:sys.sysctl.tcp_def_init_rwnd=*
write /proc/sys/net/ipv4/tcp_default_init_rwnd ${sys.sysctl.tcp_def_init_rwnd}

"【守護進程】"
## Daemon processes to be run by init.
##
service ueventd /sbin/ueventd
class core
critical
seclabel u:r:ueventd:s0

"【日志服務進程】"
service logd /system/bin/logd
class core
socket logd stream 0666 logd logd
socket logdr seqpacket 0666 logd logd
socket logdw dgram 0222 logd logd
seclabel u:r:logd:s0

"【Healthd是android4.4之后提出來的一種中介模型,該模型向下監聽來自底層的電池事件,向上傳遞電池數據信息給Framework層的BatteryService用以計算電池電量相關狀態信息】"
service healthd /sbin/healthd
class core
critical
seclabel u:r:healthd:s0

"【控制台進程】"
service console /system/bin/sh
"【為當前service設定一個類別.相同類別的服務將會同時啟動或者停止,默認類名是default】"
class core
"【服務需要一個控制台】"
console
"【服務不會自動啟動,必須通過服務名顯式啟動】"
disabled
"【在執行此服務之前切換用戶名,當前默認的是root.自Android M開始,即使它要求linux capabilities,也應該使用該選項.很明顯,為了獲得該功能,進程需要以root用戶運行】"
user shell
seclabel u:r:shell:s0

on property:ro.debuggable=1
start console

# adbd is controlled via property triggers in init.<platform>.usb.rc
service adbd /sbin/adbd --root_seclabel=u:r:su:s0
class core
"【創建一個unix域下的socket,其被命名/dev/socket/<name>. 並將其文件描述符fd返回給服務進程.其中,type必須為dgram,stream或者seqpacke,user和group默認是0.seclabel是該socket的SELLinux的安全上下文環境,默認是當前service的上下文環境,通過seclabel指定】"
socket adbd stream 660 system system
disabled
seclabel u:r:adbd:s0

# adbd on at boot in emulator
on property:ro.kernel.qemu=1
start adbd

"【內存管理服務,內存不夠釋放內存】"
service lmkd /system/bin/lmkd
class core
critical
socket lmkd seqpacket 0660 system system

"【ServiceManager是一個守護進程,它維護着系統服務和客戶端的binder通信。
在Android系統中用到最多的通信機制就是Binder,Binder主要由Client、Server、ServiceManager和Binder驅動程序組成。其中Client、Service和ServiceManager運行在用戶空間,而Binder驅動程序運行在內核空間。核心組件就是Binder驅動程序了,而ServiceManager提供輔助管理的功能,無論是Client還是Service進行通信前首先要和ServiceManager取得聯系。而ServiceManager是一個守護進程,負責管理Server並向Client提供查詢Server的功能。】"
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
"【servicemanager 服務啟動時會重啟zygote服務】"
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm

"【Vold是Volume Daemon的縮寫,它是Android平台中外部存儲系統的管控中心,是管理和控制Android平台外部存儲設備的后台進程】"
service vold /system/bin/vold
class core
socket vold stream 0660 root mount
ioprio be 2

"【Netd是Android系統中專門負責網絡管理和控制的后台daemon程序】"
service netd /system/bin/netd
class main
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
socket fwmarkd stream 0660 root inet

"【debuggerd是一個daemon進程,在系統啟動時隨着init進程啟動。主要負責將進程運行時的信息dump到文件或者控制台中】"
service debuggerd /system/bin/debuggerd
class main

service debuggerd64 /system/bin/debuggerd64
class main

"【Android RIL (Radio Interface Layer)提供了Telephony服務和Radio硬件之間的抽象層】"
# for using TK init.modem.rc rild-daemon setting
#service ril-daemon /system/bin/rild
# class main
# socket rild stream 660 root radio
# socket rild-debug stream 660 radio system
# user root
# group radio cache inet misc audio log

"【提供系統 范圍內的surface composer功能,它能夠將各種應用 程序的2D、3D surface進行組合。】"
service surfaceflinger /system/bin/surfaceflinger
class core
user system
group graphics drmrpc
onrestart restart zygote

"【DRM可以直接訪問DRM clients的硬件。DRM驅動用來處理DMA,內存管理,資源鎖以及安全硬件訪問。為了同時支持多個3D應用,3D圖形卡硬件必須作為一個共享資源,因此需要鎖來提供互斥訪問。DMA傳輸和AGP接口用來發送圖形操作的buffers到顯卡硬件,因此要防止客戶端越權訪問顯卡硬件。】"
#make sure drm server has rights to read and write sdcard ####
service drm /system/bin/drmserver
class main
user drm
# group drm system inet drmrpc ####
group drm system inet drmrpc sdcard_r ####

"【媒體服務,無需多說】"
service media /system/bin/mediaserver
class main
user root ####
# google default ####
# user media ####
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm media sdcard_r system net_bt_stack ####
# google default ####
# group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm ####

ioprio rt 4

"【設備加密相關服務】"
# One shot invocation to deal with encrypted volume.
service defaultcrypto /system/bin/vdc --wait cryptfs mountdefaultencrypted
disabled
"【當服務退出時,不重啟該服務】"
oneshot
# vold will set vold.decrypt to trigger_restart_framework (default
# encryption) or trigger_restart_min_framework (other encryption)

# One shot invocation to encrypt unencrypted volumes
service encrypt /system/bin/vdc --wait cryptfs enablecrypto inplace default
disabled
oneshot
# vold will set vold.decrypt to trigger_restart_framework (default
# encryption)

"【開機動畫服務】"
service bootanim /system/bin/bootanimation
class core
user graphics
# group graphics audio ####
group graphics media audio ####
disabled
oneshot

"【在Android系統中,PackageManagerService用於管理系統中的所有安裝包信息及應用程序的安裝卸載,但是應用程序的安裝與卸載並非PackageManagerService來完成,而是通過PackageManagerService來訪問installd服務來執行程序包的安裝與卸載的。】"
service installd /system/bin/installd
class main
socket installd stream 600 system system

service flash_recovery /system/bin/install-recovery.sh
class main
seclabel u:r:install_recovery:s0
oneshot

"【vpn相關的服務】"
service racoon /system/bin/racoon
class main
socket racoon stream 600 system system
# IKE uses UDP port 500. Racoon will setuid to vpn after binding the port.
group vpn net_admin inet
disabled
oneshot

"【android中有mtpd命令可以連接vpn】"
service mtpd /system/bin/mtpd
class main
socket mtpd stream 600 system system
user vpn
group vpn net_admin inet net_raw
disabled
oneshot

service keystore /system/bin/keystore /data/misc/keystore
class main
user keystore
group keystore drmrpc

"【可以用dumpstate 獲取設備的各種信息】"
service dumpstate /system/bin/dumpstate -s
class main
socket dumpstate stream 0660 shell log
disabled
oneshot

"【mdnsd 是多播 DNS 和 DNS 服務發現的守護程序。】"
service mdnsd /system/bin/mdnsd
class main
user mdnsr
group inet net_raw
socket mdnsd stream 0660 mdnsr inet
disabled
oneshot

"【觸發關機流程繼續往下走】"
service pre-recovery /system/bin/uncrypt
class main
disabled
"【當服務退出時,不重啟該服務】"
oneshot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
init.c全解析
接下來我們具體分析以下這個main函數的執行過程;可能比較長,大家耐心看一下:


int main( int argc, char **argv )
{
#創 建一些linux根文件系統中的目錄
mkdir( "/dev", 0755 );
mkdir( "/proc", 0755 );
mkdir( "/sys", 0755 );

mount( "tmpfs", "/dev", "tmpfs", 0, "mode=0755" );
mkdir( "/dev/pts", 0755 );
mkdir( "/dev/socket", 0755 );
mount( "devpts", "/dev/pts", "devpts", 0, NULL );
mount( "proc", "/proc", "proc", 0, NULL );
mount( "sysfs", "/sys", "sysfs", 0, NULL );
#init的 標准輸入,標准輸出,標准錯誤文件描述符定向到__null__,意味着沒有輸入和輸出,它的輸入和輸出全部寫入到Log中
open_devnull_stdio();
#初始化 log 寫入init進 信息
log_init();
#讀取並 且解析init.rc文件(這個文件在根目錄下)
parse_config_file( "/init.rc" );
#取得硬件 為打印我們的設備名fs100
get_hardware_name();
snprintf( tmp, sizeof(tmp), "/init.%s.rc", hardware );
#讀取並 且解析硬件相關的init腳本文件,
parse_config_file( tmp );
#觸發在init腳本文件中名字為early-init的action,並且執行其commands,其實是: on early-init
action_for_each_trigger( "early-init", action_add_queue_tail );
drain_action_queue();
#初始化動態設備管理,設備文件有變化時反應給內核,后面具體解釋
device_fd = device_init(); # 初 始 化 設 備 管 理 務
#加載啟動動畫,如果動畫打開失敗,則在屏幕上打印: A N D R O I D字樣。
if ( load_565rle_image( INIT_IMAGE_FILE ) )
{
fd = open( "/dev/tty0", O_WRONLY );
if ( fd >= 0 )
{
const char *msg;
msg = "\n"
"\n"
"\n"
879 "\n"
"\n"
"\n"
"\n" /* console is 40 cols x 30 lines */
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
/* " A N D R O I D ";開機動畫 */
write( fd, msg, strlen( msg ) );
close( fd );
}
}

#觸發 在init腳本文件中名字為init的action,並且執行其commands,其實是:on init
action_for_each_trigger( "init", action_add_queue_tail );
drain_action_queue();
#啟動系統屬性服務: system property service
property_set_fd = start_property_service();
#創建socket用來處理孤兒進程信號
if ( socketpair( AF_UNIX, SOCK_STREAM, 0, s ) == 0 )
{
signal_fd = s[0];
signal_recv_fd = s[1];
fcntl( s[0], F_SETFD, FD_CLOEXEC );
fcntl( s[0], F_SETFL, O_NONBLOCK );
fcntl( s[1], F_SETFD, FD_CLOEXEC );
fcntl( s[1], F_SETFL, O_NONBLOCK );
}
#觸發 在init腳本文件中名字為early-boot和boot的action,並且執行其commands,其實是:on early-boot和on boot
action_for_each_trigger( "early-boot", action_add_queue_tail );
action_for_each_trigger( "boot", action_add_queue_tail );
drain_action_queue();
#啟動所有屬性變化觸發命令,其實是: on property:ro.xx.xx=xx
queue_all_property_triggers();
drain_action_queue();
#進入 死循環()
for (;; )
{
#啟 動所有init腳本中聲明的service,
#如 :266 service servicemanager /system/bin/servicemanager
#user system
#critical
#onrestart restart zygote
#onrestart restart media
restart_processes();
#多路監聽設備管理,子進程運行狀態,屬性服務
nr = poll( ufds, fd_count, timeout );
if ( nr <= 0 )
continue;
if ( ufds[2].revents == POLLIN )
{
read( signal_recv_fd, tmp, sizeof(tmp) );
while ( !wait_for_one_process( 0 ) )
;
continue;
}

if ( ufds[0].revents == POLLIN )
handle_device_fd( device_fd );

if ( ufds[1].revents == POLLIN )
handle_property_set_fd( property_set_fd );
if ( ufds[3].revents == POLLIN )
handle_keychord( keychord_fd );
}

return(0);
}
---------------------
作者:瘋人院的院長大人
來源:CSDN
原文:https://blog.csdn.net/zhonglunshun/article/details/78615980
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM