Android2.2_INIT进程

1.init主要工作流程:
>解析两个配置文件.1个是 init.rc 1个是 init.hardware.rc
>执行各种Action,分别是early-init init early-boot boot
>调用property_init初始化属性 调用property_set设置属性 调用start_property_service启动属性服务
>init无限循环处理来自socket事件 属性事件


*附属工作:
>创建文件夹 挂载设备
>重定向输入/日至
>创建Uevent与Linux交互的socket
>初始化keychord调试设备
>socketpair创建两个socket
>init循环中 监听以上创建好代码的事件


2.解析配置文件:
>init.rc配置主要内容:
*该文件由3个flags标示区别开,分别是OPTION COMMAND SECTION ,SECTION表示章节(从关键字开始到下个关键字开始),
COMMAND表示执行动作,#define KEYWORD(symbol, flags, nargs, func) K_##symbol  当KEYWORD 的flags为COMMAND时执行func函数

*该文件主要的section有on init,on boot分别对应4个执行动作中的两个.service zygote,service media分别对应两个service

>分析zygote service配置解析

*init.rc中的zygote信息(1个socket option 用于创建socket通讯和 3个onrestart option)

# 一个service的section,对应的section 名为zygote
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
	#socket onrestart是OPTION ,write restart是COMMAND
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media

*回到init.c的 main函数中,调用parse_config_file("/init.rc");最终调用到Parser.c的parse_new_section(),如下

//parse_service  parse_line_service 解析service
        state->context = parse_service(state, nargs, args);
        if (state->context) {
            state->parse_line = parse_line_service;
            return;
        }
*解析zygote无非做两件事:1.解析socket配置环境 2.解析onrestart配置环境,而zygote本身的信息由函数parse_service()解析,

而上面的两件事由parse_line_service()解析.解析前先查看zygote的结构体信息.

struct service {
    //双向链表, 用来保存解析配置文件后得到的service
    struct listnode slist;


    const char *name;	//service的名称
    const char *classname;	//service的class名字,默认"default"


    unsigned flags;
    pid_t pid;		
    time_t time_started;    /* time of last start */
    time_t time_crashed;    /* first crash within inspection window */
    int nr_crashed;         /* number of times crashed within window */
    
    uid_t uid;
    gid_t gid;	
    gid_t supp_gids[NR_SVC_SUPP_GIDS];
    size_t nr_supp_gids;

	//读写权限为666 的 http socket, socket 也是IPC 通讯
    struct socketinfo *sockets;
	//描述进程所需环境变量信息
    struct svcenvinfo *envvars;

	//存储onrestart 后面的 COMMAND 信息
    struct action onrestart;  /* Actions to execute on restart. */
    
    /* keycodes for triggering this service via /dev/keychord */
    int *keycodes;
    int nkeycodes;
    int keychord_id;

    int ioprio_class;
    int ioprio_pri;
    int nargs;
    char *args[1];
};
socket的结构体如下:

struct socketinfo {
    struct socketinfo *next;
    const char *name;
    const char *type;
    uid_t uid;
    gid_t gid;
    int perm;
};
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;
    //zygote 配置文件有3发onrestart  option 对应3 个COMMAND 的双向链表
    struct listnode commands;
    struct command *current;
};
*回到Parser.c查看如何解析service主要结构体,parse_service()主要代码如下:

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";//设置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);
	//把zygote 的service 加到 service_slist 全局链表中去.
    list_add_tail(&service_list, &svc->slist);
parse_line_service()主要代码如下:
//创建socket相关信息并添加到zygote service 结构体中
        si = calloc(1, sizeof(*si));
        if (!si) {
            parse_error(state, "out of memory\n");
            break;
        }
        si->name = args[1];
        si->type = args[2];
        si->perm = strtoul(args[3], 0, 8);
        if (nargs > 4)
            si->uid = decode_uid(args[4]);
        if (nargs > 5)
            si->gid = decode_uid(args[5]);
        si->next = svc->sockets;
        svc->sockets = si;
//解析onrestart 里面的配置信息并存储到service中去
        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);
至此,zygote解析如下图:



3.创建zygote服务

*解析完配置文件后 执行init.rc 中 on boot的所有 COMMAND;

action_for_each_trigger("boot", action_add_queue_tail);
	
	//#class_start是一个COMMAND 对应一个do_class_start函数
    //执行所有on boot  section 节里面的COMMAND .
    drain_action_queue();

int do_class_start(int nargs, char **args)
{
    //判断classname 第一次为default,执行service_start_if_not_disabled();
    service_for_each_class(args[1], service_start_if_not_disabled);
    return 0;
}
*触发 do_class_start,实际上调用到 service_start(), 代码如下:

该方法执行了如下步骤:

1)判断zygote所在进程文件system/bin/app_process是否存在.
2)fork一条子进程
3)添加环境变量socket变量信息

4)execve () 执行/system/bin/app_process  这样就进入到app_process的main中
5)修改服务信息


4.重启zygote服务

*当zygote服务进程销毁后,会调用sigchld_handler()往socket中写入数据,该socket由socketpair创建,

此时另一条socket就能poll到数据,而执行wait_for_one_process处理事件,主要代码如下:

//找到zygote 所在的service
svc = service_find_by_pid(pid);
if (!(svc->flags & SVC_ONESHOT)) {
		//杀掉所有子进程
        kill(-pid, SIGKILL);
        NOTICE("process '%s' killing any children in process group\n", svc->name);
    }


    //清理socket信息
    for (si = svc->sockets; si; si = si->next) {
        char tmp[128];
        snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
        unlink(tmp);
    }
//设置标示为SVC_RESTARTING
    svc->flags |= SVC_RESTARTING;


    //执行onrestart  的内容
    list_for_each(node, &svc->onrestart.commands) {
        cmd = node_to_item(node, struct command, clist);
        cmd->func(cmd->nargs, cmd->args);
    }
	//设置init.svc.zygote 值得为restarting
    notify_service_state(svc->name, "restarting");
最后,进入下一轮循环 重新启动SVC_RESTARTING的服务
//执行循环的动作
drain_action_queue();
//重启死去的进程
 restart_processes();

5.属性服务

*执行属性服务的过程总的有2个,property_init()和start_property_service()

*property_init()主要做了以下几件事

1)创建共享内存

2)创建共享内存到本地进程的映射

*start_property_service()主要做了如下2件事

1)加载持久化数据到property内存中

2)创建socket的IPC通讯以便客户端传输数据

*服务端如何获取数据,在init.c的main函数中,handle_property_set_fd函数等待客户端请求以便处理请求。它主要执行了如下几件事

1)接收TCP连接

2)接收请求数据

3)"控制"消息处理

4)调用property_set 设置属性,其中ro.* properties 为只读属性,net.change 特殊处理 持久化属性持久到特定的文件中等...

*而对于客户端 只需要发送socket请求即可对属性进行存储。


你可能感兴趣的:(Android2.2_INIT进程)