在看項目的代碼,對父進程fork的子進程的各種死法,父進程會受到子進程什麼樣的信號產生了疑慮。
通過細看apue,可以整理出一下流程:
對於子進程(abort, ctrl+c, a/0, 被kill, *invalid_addr 等等)各種死法,子進程會收到對應的信號(如 SIGABRT, SIGKILL,SIGFPE ..等等信號),這些信號是按照 [硬件/軟件] -> 內核 -> 進程 順序發送給子進程的。
這只是子進程接收信號的表述,實際上子進程本身也可能是導致發送信號的原因,比如子進程運行結束,會導致內核向父進程發送 SIGCHLD 信號。
因此不管子進程是正常死的(return 0)還是異常死的(kill),也不管異常死的方式。只要子進程運行結束了,內核都會負責向父進程報喪(發 SIGCHLD 信號)。而如果父進程不用wait或者waitpid接收報喪,那麼子進程將會變成殭屍進程(沒人收屍)。
如果父進程在子進程之前運行終止,那麼內核會在一個進程終止時,逐個檢查所有活動進程,以判斷它是否是正要終止的進
程的子進程,如果是(此時子進程成爲孤兒進程),則該進程的父進程 I D就更改爲1 ( i n i t進程的I D ),由init進程收養。以確保系統每個子進程都有一個父進程。因爲init進程會調用wait取得子進程的消亡狀態,因此孤兒進程不會變成殭屍進程。
有了上面的理解,下面的代碼就好看懂了:
sig_hander(int signo)
{
int save_errno = errno;
//switch(signo)
//case SIGCHLD, SIGINT, SIGTERM
//do something
errno = save_errno;
}
父進程:
signal(SIGCHLD, sig_hander); //處理子進程終止產生的信號,此時sig_hander 的參數是 SIGCHLD
signal(SIGINT, sig_hander); //處理中斷信號 ctrl + c,此時sig_hander 的參數是 SIGINT
signal(SIGTERM, sig_hander); //處理終止信號,此時sig_hander 的參數是 SIGTERM
//注意不能捕獲,SIGKILL 和 SIGSTOP 這兩個信號。