您的位置:首页 > 移动开发 > Android开发

Android init进程分析——学习笔记

2015-08-20 11:13 459 查看
  Android init进程是Linux系统中用户空间的第一个进程,在Android里也是如此。在Android中init进程主要负责两大块内容,分别是:

创建几个关键进程,如zygote。

提供property service服务管理Android各种属性。

一、init分析

首先是init.c文件入口函数是其main函数

[–>init.c]

[code]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]

[code]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]

[code]......
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]

[code]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]

[code]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]

[code]static int init_property_area(void)
{
//初始化共享内存
}


[–>system_properties.c]

[code]int _system_properties_init(void)
{
//客服端获取共享内存
}


[–>property_service.c]

[code]void start_property_service(void)
{
//启动属性服务器
}

void handle_property_set_fd()
{
//处理socket消息
}

int property_set(const char *name, const char *value)
{
//设置属性
}


[–>properties.c]

[code]//客户端发送属性请求
int property_set(const char *key, const char *value)
{
    return __system_property_set(key, value);
}


本文只是很粗很泛的介绍了一下init.c进程,其中遗漏了大量东西,以及可能有许多错误的地方,希望以后能有机会来改进。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: