關於 unix SIGCHLD 信號的一些思考

在看項目的代碼,對父進程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 這兩個信號。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章