《深入理解Android 卷1》读书笔记 (一)—— Android Init之zygote restart
本文的大体流程还是按照书本上来,分三段。
(二)zygote restart
由于本文内容较长,重新组织了下文章结构,将原文一分为三。
(二)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部分),
对原文内容有所补充。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。