本文的大体流程还是按照书本上来,分三段。
(二)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部分),
对原文内容有所补充。