init作为android启动的第一个用户进程,其主要有两个职责:
1. 解析.rc文件中的内容(如init.rc)
2. 启动、监听以及重启.rc文件中定义的Action和服务等。
Init的入口函数是Init.c (system\core\init) 中的main函数
下面的代码注释属于个人对代码的理解,省略号表示的是部分重复代码或次要代码,对上面两点的分析不造成影响。
int main(int argc, char **argv)
{
int fd_count = 0;
struct pollfd ufds[4];//ufds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符
char *tmpdev;
char* debuggable;
char tmp[32];
int property_set_fd_init = 0;
int signal_fd_init = 0;
int keychord_fd_init = 0;
bool is_charger = false;//表示是否在充电模式
//下面两个if语句分别表示ueventd和watchdogd的入口函数,至于为什么会进入这里,可在Android.mk文件的定义
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
if (!strcmp(basename(argv[0]), "watchdogd"))
return watchdogd_main(argc, argv);
......//这里省略的部分是文件系统的初始化
open_devnull_stdio();//重定向标准输入输出错误到/dev/_null_
klog_init();//系统日志的初始化
property_init();//属性区域的初始化
get_hardware_name(hardware, &revision);
process_kernel_cmdline();
union selinux_callback cb;
cb.func_log = log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
selinux_initialize();//selinux的初始化,一种安全机制,一般用.te文件进行约束
..........
INFO("property init\n");
property_load_boot_defaults();//之前初始化的属性区域没有任何东西,现在就是讲生成的/default.prop和/system/build.prop等文件信息加载到该区域中
INFO("reading config file\n");
init_parse_config_file("/init.rc");//1.解析init.rc文件的内容
action_for_each_trigger("early-init", action_add_queue_tail);//将early-init的action添加到启动链表的尾部
queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");//未在init.rc中配置的服务,添加到链表的尾部
.......
for(;;) {
int nr, i, timeout = -1;
execute_one_command();//2.执行一个命令,服务就是在执行命令的时候起来的
restart_processes();//重启标识了需要重启的服务
.......//init的监听服务的初始化工作
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();//处理属性服务请求
else if (ufds[i].fd == get_keychord_fd())
handle_keychord();
else if (ufds[i].fd == get_signal_fd())
handle_signal();//处理子进程退出请求
}
}
}
return 0;
}