繼續上一講,分析handle_signal
1.init進程–>分析init.rc–>獲得服務列表–>依次啓動服務子進程
在init啓動的進程中,除了一小部分外,其他大部分進程出現意外終止時,init進程要重新啓動他們。
子進程終止–>向父進程init傳遞SIGCHLD信號–>檢查進程選項是否設置爲oneshot–>放棄重啓或者重啓進程
2.代碼分析
上節講到,收到SIGCHLD信號後,調用與之相對應的處理函數
sigchld_handler–>signal_fd套接字寫1,signal_recv_fd套接字對應有1–>poll監聽到
–>handle_signal函數調用–>wait_for_one_process函數調用,如下圖:
wait_for_one_process函數在產生SIGCHLD信號的進程的服務列表中,檢查進程的設置選項,若選項非oneshot(SVC_ONE_SHOT)則添加重啓選項(SVC_RESTARTING)。否則不會被重啓。
static int wait_for_one_process(int block)
{
...
/*waitpid函數用來回收進程所佔用的資源,第一個參數爲-1,代表查看所有子進程是否發出SIGCHLD信號,返回值即是產生SIGCHLD信號的進程pid號*/
while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR );
svc = service_find_by_pid(pid);//取出進程號爲pid的服務項目
...
//如果是要重啓,先殺死pid的所有子進程
if (!(svc->flags & SVC_ONESHOT) || (svc->flags & SVC_RESTART)) {
kill(-pid, SIGKILL);
//傳送信號給指定的進程,pid爲負數將信號傳給進程組識別碼爲負數絕對值的所有進程
NOTICE("process '%s' killing any children in process group\n", svc->name);
}
/* remove any sockets we may have created,刪除進程持有的所有sockDescriptor */
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_running
/* oneshot processes go into the disabled state on exit,except when manually restarted. 不重啓的,設置爲SVC_DISABLED*/
if ((svc->flags & SVC_ONESHOT) && !(svc->flags & SVC_RESTART)) {
svc->flags |= SVC_DISABLED;
}
/* disabled and reset processes do not get restarted automatically */
if (svc->flags & (SVC_DISABLED | SVC_RESET) ) {
notify_service_state(svc->name, "stopped");
return 0;//不重啓的,退出
}
...
svc->flags &= (~SVC_RESTART);
//添加SVC_RESTARTING,此標記應用在for循環中的restart_processes()中,用來確定待重啓的進程
svc->flags |= SVC_RESTARTING;
/* Execute all onrestart commands for this service. 檢查待重啓的進程在init.rc文件中是否帶有onrestart選項,如果有,執行它們*/
list_for_each(node, &svc->onrestart.commands) {
cmd = node_to_item(node, struct command, clist);
cmd->func(cmd->nargs, cmd->args);
}
notify_service_state(svc->name, "restarting");//設置服務屬性
return 0;
}
//回到for循環中,執行restart_processes();
static void restart_processes()
{
process_needs_restart = 0;
service_for_each_flags(SVC_RESTARTING,restart_service_if_needed);
}
static void restart_service_if_needed(struct service *svc)
{
...
if (next_start_time <= gettime()) {
svc->flags &= (~SVC_RESTARTING); //清除flags中的restarting位
service_start(svc, NULL); //重啓此服務
return;
}
...
}