Init进程概述
init是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init始终是用户级的第一个进程。
adb shell ps查看pid及ppid为1的进程信息:
作为天字第一号进程,init被赋予了很多极其重要的工作职责:
(1)解析系统property文件并初始化property信息。
(2)解析脚本init.rc。
(3)根据init.rc配置信息,触发Action及启动Service。
(4)提供系统property服务管理及完成对应的触发事件。
(5)维护系统级Service。
解析init.rc
文件内容
在Android的Init文件中,主要包含:
Action
Commands
Services
Options
在文件 system/core/init/keywords.h 例如如下的定义:
KEYWORD(on, SECTION, 0, 0)
KEYWORD(service, SECTION, 0, 0)
on <trigger>
<command>
<command>
<command> ...
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
Init动作
参考init.c中main函数的
action_for_each_trigger
queue_builtin_action
有三个关键列表
(1)static list_declare(service_list);
(2)static list_declare(action_list);
(3)static list_declare(action_queue);
service_list保存了结构体为service的链表。
Init动作执行4个阶段:
(1)early-init
wait_for_coldboot_done
keychord_init
console_init
(2)init
early-fs
fs
post-fs
post-fs-data
property_service_init
signal_init
check_startup
(3)early-boot
(4)boot
数据结构
system/core/init/init.h中,定义了action节点,service节点,command节点的结构:
代码逻辑
for(;;) {
execute_one_command();
restart_processes();
......
}
execute_one_command的关键逻辑:
(1)action_remove_queue_head函数获取action_queue链表中的第一个action节点,
(2)通过action节点调用get_next_command函数,获取它的下一个Command
(3)执行Command
关键点,通过函数上层的for循环,首先获取Action节点,其次循环获取并执行Action节点下的Command,Command循环完成后,再获取下一个Action节点。
restart_processes的关键逻辑:
(1)循环获取service_list中的Service节点,
(2)调用service_for_each_flags函数,通过Service节点中的flags、 time_started判断,是否启动该Service。
(3)调用service_start函数,fork子进程,创建Socket、执行启动Service等操作 。
解析&启动Service
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
onrestart restart surfaceflinger
属性服务
获取属性
通过adb shell getprop获取系统当前属性
启动属性服务
(1)Property服务启动入口:
action_queue中的Action:property_service_init,对应的函数指针: property_service_init_action
(2)初始化调用过程:
property_service_init_action-> start_property_service-> load_properties_from_file& create_socket& listen&set property_set_fd
(3)多路切换监听过程
for(;;) {
......
if (!property_set_fd_init && get_property_set_fd() > 0) {
ufds[fd_count].fd = get_property_set_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
property_set_fd_init = 1;
}
......
nr = poll(ufds, fd_count, timeout);
}
(4)Property服务响应
for(;;) {
......
nr = poll(ufds, fd_count, timeout);
if (nr <= 0) {
continue;
}
for (i = 0; i < fd_count; i++) {
if (ufds[i].revents == POLLIN) {
if (ufds[i].fd == get_property_set_fd()) {
handle_property_set_fd();
}
......
}
}
}
1.accept
2. getsockopt
3. recv
4. property_set
5. property_changed