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

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

(一)从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部分),

对原文内容有所补充。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。