码迷,mamicode.com
首页 > 移动开发 > 详细

Android-init进程(1)

时间:2014-12-11 12:24:10      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:android   style   blog   http   io   ar   color   sp   for   

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

*解析配置文件

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

*设置属性服务

bubuko.com,布布扣

本节主要内容讲解如何解析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

*如下图

bubuko.com,布布扣



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标识


Android-init进程(1)

标签:android   style   blog   http   io   ar   color   sp   for   

原文地址:http://blog.csdn.net/qq285016127/article/details/41649591

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!