当前位置: 代码迷 >> Android >> Android-init历程(1)
  详细解决方案

Android-init历程(1)

热度:12   发布时间:2016-04-28 03:24:56.0
Android-init进程(1)

init进程是android启动的第一个进程 进程pid为1.其主要做了如下几件事:

*解析配置文件

*根据配置文件执行操作early_init init early_boot boot

*设置属性服务

init主要内容

本节主要内容讲解如何解析init.rc文件和运行zygote.

1.解析init.rc配置文件

/**init.c*/

main函数中,执行如下函数:

init_parse_config_file("/init.rc");
/**init_parse.c*/
int init_parse_config_file(const char *fn){    char *data;    data = read_file(fn, 0);    if (!data) return -1;    parse_config(fn, data);    DUMP();    return 0;}static void parse_config(const char *fn, char *s);

parse_config函数主要找到一个SECTION的节点开始解析if (kw_is(kw, SECTION)) {        state.parse_line(&state, 0, 0);        parse_new_section(&state, kw, nargs, args);} 

 kw_is函数执行了keywords文件 并找处指定标示 k_##symbol

/**keywords.h*/ 

1>定义枚举.枚举值为k_class k_mkdir等
2>定义结构体数组keyword_info,把KEYOWRD宏改变成结构体,通过宏定义找出symbol与func解析init.rc文件
如关键字section的symbol为chdir 则找到如int do_chdir(int nargs, char **args)的声明查看对应定义
>>>关键字有:OPTION,COMMAND,SECTION
/**init.rc*/
on init #表示on的SECTION名称为init 基本步骤为early-init init early-boot boot 
        #从一个section开始 到下一个section开始标签前结束

export ANDROID_ROOT /system  #表示export为一个COMMAND

*如下图




2.分析zygote

/**init.rc配置文件*/ 

在该文件中 zygote被定义为需要执行4个操作并且拥有一个socket为660的服务,他是init的一个子进程.

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

---------------Service定义信息------------------
-维护所有生成Service的一个双向链表listnode
-service的name zygote的name为init.svc.zygote
-className 默认"default"
-属性flag pid uid gid io优先级 参数(个数)
-time_started time_crashed nr_crashed 上次启动死亡时 总死亡次数
-socketinfo(socket环境变量信息)  svcenvinfo(进程所需环境变量信息)  
-struct action onrestart; 保存OPTION后面的COMMAND信息
------------------------------------------------

---------------onrestart定义信息------------------
struct action {        /* node in list of all actions */    struct listnode alist;        /* node in the queue of pending actions */    struct listnode qlist;        /* node in list of actions for a trigger */    struct listnode tlist;    unsigned hash;    const char *name;        struct listnode commands;    struct command *current;//保存restart里面的COMMOND动作};

------------------------------------------------


/**init_parse.c*/
#主要执行parse_service 和parse_line_service
//创建service结构体主要框架,并添加到service_list双向链表中
//socketinfo是一个单向链表 zygote只有一个660 的TCP scoket
//onrestart通过commond指向一个commonds链表 zygote如上在init.rc中可以看出有4个commond

static void *parse_service(struct parse_state *state, int nargs, char **args){	struct service *svc;	svc = calloc(1, sizeof(*svc) + sizeof(char*) * nargs);    if (!svc) {        parse_error(state, "out of memory\n");        return 0;    }    svc->name = args[1];    svc->classname = "default";    memcpy(svc->args, args + 2, sizeof(char*) * nargs);    svc->args[nargs] = 0;    svc->nargs = nargs;    svc->onrestart.name = "onrestart";    list_init(&svc->onrestart.commands);	    list_add_tail(&service_list, &svc->slist);    return svc;}

static void parse_line_service(struct parse_state *state, int nargs, char **args){	struct service *svc = state->context;        nargs--;        args++;        kw = lookup_keyword(args[0]);		//创建Commond结构体        cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);        cmd->func = kw_func(kw);        cmd->nargs = nargs;        memcpy(cmd->args, args, sizeof(char*) * nargs);		//添加到双向列表中        list_add_tail(&svc->onrestart.commands, &cmd->clist);}

**********init 启动zygote**********
1)init.c::main>
// 将boot的commond加入到执行队列中   因为zygote 包含在boot动作中
action_for_each_trigger("boot", action_add_queue_tail);
//执行队列中的commond 并统一执行所有section的commond
queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
2)Bultins.c::do_class_start>
//因为class_start是一个COMMOND所以他会被执行 在这里zygote是一个 "default"的className
//所以执行service_start_if_not_disabled函数

//如果service的flag被明确规定为disable 那么执行该service必须单独再执行
service_for_each_class(args[1],service_start_if_not_disabled);
3)Bultins.c::service_start_if_not_disabled>
if (!(svc->flags & SVC_DISABLED)) {
        service_start(svc, NULL);//之前设置没有创建flags 表示该service还未启用 执行service_start
    }
4)init.c::service_start>
>>判断文件进程/system/bin/process文件是否存在  一般service有自己的进程  
rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
>>启动init子进程
pid = fork();
>>添加进程环境变量信息 
>>添加socket环境变量信息并创建socket
>>设置uid  gid并启动/system/bin/app_process文件的main函数

>>设置service的启动时间 pid等等


**********init 重启zygote**********
>>绑定操作 响应事件
1)init.c::main>>
queue_builtin_action(signal_init_action, "signal_init");
2)init.c::signal_init_action>>
signal_init();
3)signal_handler::signal_init>>
struct sigaction act;//绑定2个方法 sigchld_handler handle_signal 其结构体还包括了一个sa_flags标示
>>zygote死后父进程init调用sigchld_handler
1)signal_handler::sigchld_handler>>
    write(signal_fd, &s, 1);//往signal_fd中写数据  signal_fd是socketpair中两条socket中的一条
2)init.c::main>>
nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;
        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents == POLLIN) {
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
3)signal_handler::handle_signal>>
read(signal_recv_fd, tmp, sizeof(tmp));
    while (!wait_for_one_process(0)) ;
4)signal_handler::wait_for_one_process>>
//杀掉zygote的所有子进程
//清除我们将要重建的scoket
//将所有onrestart的commond(zygote中有4个)添加到svc中的action结构体列表中
//改变svc状态为restarting
5)init.c::main>>
//poll后进入下一轮循环 又执行main
execute_one_command();//执行所有COMMOND

        restart_processes();//改变flag标识


  相关解决方案