Android init进程是Linux系统中用户空间的第一个进程,在Android里也是如此。在Android中init进程主要负责两大块内容,分别是:
- 创建几个关键进程,如zygote。
- 提供property service服务管理Android各种属性。
一、init分析
首先是init.c文件入口函数是其main函数
[–>init.c]
int main(int argc, char **argv)
{
//一些准备工作,如
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
......
//初始化相关属性
property_init();
......
//获取系统信息
get_hardware_name(hardware, &revision);
......
//解析配置文件
init_parse_config_file("/init.rc");
......
//early-init,init阶段
action_for_each_trigger("early-init", action_add_queue_tail);
action_for_each_trigger("init", action_add_queue_tail);
......
//early-init,init阶段
for(;;) {
......
//执行相关命令,重启已死去的进程
execute_one_command();
restart_processes();
......
}
}
init.c可总结为一下几点:
- 初始化设备。如某些文件的创建与挂在,property_init()相关属性的初始化,设备信息的获取等工作。
- 分析配置文件init.rc。
- 执行一些动作,zygote就是在某个动作中完成创建的。
- 进入无线循环,等待一些事的发生。
二、init.rc配置文件解析
在init.c中调用了init_parse_config_file(“/init.rc”)函数来解析配置文件,函数代码如下
[–>init_parser.c]
int init_parse_config_file(const char *fn)
{
char *data;
data = read_file(fn, 0);
if (!data) return -1;
//主要是调用 parse_config进行解析
parse_config(fn, data);
DUMP();
return 0;
}
......
static void parse_config(const char *fn, char *s)
{
......
for (;;) {
switch (next_token(&state)) {
......
case T_NEWLINE:
state.line++;
if (nargs) {
int kw = lookup_keyword(args[0]);
if (kw_is(kw, SECTION)) {
state.parse_line(&state, 0, 0);
//解析配置文件中的section
parse_new_section(&state, kw, nargs, args);
} else {
state.parse_line(&state, nargs, args);
}
nargs = 0;
}
break;
......
}
}
一个section就是init.rc文件中的一个service如
[–>init.rc]
......
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
......
解析section 的入口函数为parse_new_section
[–>init_parser.c]
static void parse_new_section(struct parse_state *state, int kw,
int nargs, char **args)
{
......
switch(kw) {
case K_service:
state->context = parse_service(state, nargs, args);
if (state->context) {
state->parse_line = parse_line_service;
return;
}
break;
......
}
然后在调用parse_service和parse_line_service对init.rc进行解析,parse_service用来搭建一个struct service结构体框架,parse_line_service用来对框架进行填充。
三、启动zygote
[–>init.c]
void service_start(struct service *svc, const char *dynamic_args)
{
.....
pid = fork();//创建一个子进程来处理后面的事
if (pid == 0) {
.....
if (!dynamic_args) {
//通过execve命令/system/bin/app_process命令,但实质为调用app_main.c下的main函数
if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
.....
}
}
.....
}
}
四、属性服务
init.c里对主要是对属性服务进行了初始化,建立了一种服务器客服端的通信架构,在初始化属性服务的时候会建立一块共享内存,客户端则通过这块共享内存来读取属性,但设置属性则是通过客服端与服务器的socket通信,然后服务器端根据socket信息以及客户端的权限来设置相应的属性。相应的函数如下(具体过程就不再详解)
[–>property_service.c]
static int init_property_area(void)
{
//初始化共享内存
}
[–>system_properties.c]
int _system_properties_init(void)
{
//客服端获取共享内存
}
[–>property_service.c]
void start_property_service(void)
{
//启动属性服务器
}
void handle_property_set_fd()
{
//处理socket消息
}
int property_set(const char *name, const char *value)
{
//设置属性
}
[–>properties.c]
//客户端发送属性请求
int property_set(const char *key, const char *value)
{
return __system_property_set(key, value);
}
本文只是很粗很泛的介绍了一下init.c进程,其中遗漏了大量东西,以及可能有许多错误的地方,希望以后能有机会来改进。