《深入理解Android 卷1》读书笔记 (一)—— Android Init之zygote restart

来源:互联网 发布:淘宝购物生成器 编辑:程序博客网 时间:2024/06/05 16:13

本文的大体流程还是按照书本上来,分三段。

(一)从Main开始到service start.

(二)zygote restart

(三)属性服务 (property_service)


由于本文内容较长,重新组织了下文章结构,将原文一分为三。

(二)zygote restart

     为什么会提到这个zygote restart呢? 因为看到了信号处理函数的注册,在servicemanager的那个

"service"  section里面有句:onrestart restart zygote ,对此有点好奇。读《深入理解Android 卷1》,

看到对init.c中main函数里面剩下的部分进行了介绍,就是与zygote restart有关,所以在此记录下。

     看那个onrestart,猜想应该跟重启有关。

queue_builtin_action(signal_init_action, "signal_init");
static int signal_init_action(int nargs, char **args){    signal_init();    return 0;}
void signal_init(void){    int s[2];    struct sigaction act;    memset(&act, 0, sizeof(act));    act.sa_handler = sigchld_handler;    act.sa_flags = SA_NOCLDSTOP;    sigaction(SIGCHLD, &act, 0);    /* create a signalling mechanism for the sigchld handler */    if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {        signal_fd = s[0];        signal_recv_fd = s[1];        fcntl(s[0], F_SETFD, FD_CLOEXEC);        fcntl(s[0], F_SETFL, O_NONBLOCK);        fcntl(s[1], F_SETFD, FD_CLOEXEC);        fcntl(s[1], F_SETFL, O_NONBLOCK);    }    handle_signal();}

static void sigchld_handler(int s){    write(signal_fd, &s, 1);}
void handle_signal(void){    char tmp[32];    /* we got a SIGCHLD - reap and restart as needed */    read(signal_recv_fd, tmp, sizeof(tmp));    while (!wait_for_one_process(0))        ;}

zygote死后,其父进程init会收到SIGCHLD信号,并调用上面

的信号处理函数sigchld_handler进行处理。

 if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {        signal_fd = s[0];        signal_recv_fd = s[1];
    

     signal_fd是在signal_init中通过socketpair创建的两个socket中的一个,当往signal_fd中写

数据的时候,对应的那个pair socket  (signal_recv_fd)会收到,这样就会导致init从poll函数返回。

init.c中main函数里面的poll相关代码如下:


nr = poll(ufds, fd_count, timeout);        if (nr <= 0)            continue;        for (i = 0; i < fd_count; i++) {            if (ufds[i].revents == POLLIN) {                if (ufds[i].fd == get_property_set_fd())                    handle_property_set_fd();                else if (ufds[i].fd == get_keychord_fd())                    handle_keychord();                else if (ufds[i].fd == get_signal_fd())                    handle_signal();            }        }

handle_signal中调用的wait_for_one_process函数里面相关代码为(设置状态标志):

svc = service_find_by_pid(pid);    if (!svc) {        ERROR("untracked pid %d exited\n", pid);        return 0;    }    NOTICE("process '%s', pid %d exited\n", svc->name, pid);    if (!(svc->flags & SVC_ONESHOT) || (svc->flags & SVC_RESTART)) {        kill(-pid, SIGKILL);        NOTICE("process '%s' killing any children in process group\n", svc->name);    }    /* remove any sockets we may have created */    for (si = svc->sockets; si; si = si->next) {        char tmp[128];        snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);        unlink(tmp);    }    svc->pid = 0;    svc->flags &= (~SVC_RUNNING);

svc->flags &= (~SVC_RESTART);svc->flags |= SVC_RESTARTING;

重点还是这svc->flags &= (~SVC_RESTART);  和 svc->flags |= SVC_RESTARTING;  及 

svc->flags &= (~SVC_RUNNING); 几句。 顺便说下,之后调用的service里面command所

对应的函数,实际上是没执行任何函数的,因为那个command list为NULL,其初始化是

通过calloc进行的。

/* Execute all onrestart commands for this service. */    list_for_each(node, &svc->onrestart.commands) {        cmd = node_to_item(node, struct command, clist);        cmd->func(cmd->nargs, cmd->args);    }

在设置了zygote service的restarting 标志后,我们来看看其用途。在init.c中的main函数中,

for循环里面不是有句 restart_processes();么?

 for(;;) {        int nr, i, timeout = -1;        execute_one_command();        restart_processes();         ...         ...}
static void restart_processes(){    process_needs_restart = 0;    service_for_each_flags(SVC_RESTARTING,                           restart_service_if_needed);}
void service_for_each_flags(unsigned matchflags,                            void (*func)(struct service *svc)){    struct listnode *node;    struct service *svc;    list_for_each(node, &service_list) {        svc = node_to_item(node, struct service, slist);        if (svc->flags & matchflags) {            func(svc);        }    }}
static void restart_service_if_needed(struct service *svc){    time_t next_start_time = svc->time_started + 5;    if (next_start_time <= gettime()) {        svc->flags &= (~SVC_RESTARTING);        service_start(svc, NULL);        return;    }    if ((next_start_time < process_needs_restart) ||        (process_needs_restart == 0)) {        process_needs_restart = next_start_time;    }}

于是设置了restarting标志的zygote service 就通过service_start重启了。


BTW,文中第二部分参考了原书较多,是因为开始自己对restart 认识不清,不知

在什么情况下进程会重启。当然,随着后面自己结合已有经验和知识(signal部分),

对原文内容有所补充。


0 0
原创粉丝点击