殭屍進程可以被“殺死”嗎?

殭屍不可能被殺死,因爲它已經死了,不存在再死一次的問題。死的對立面是活,死者已死。只有活的進程纔可能被殺死。

什麼是殭屍

首先要明確一點,殭屍進程的含義是:子進程已經死了,但是父進程還沒有wait它的一箇中間狀態,這個時候子進程是一個殭屍。正常情況下子死,父wait,清理掉子進程的task_struct,釋放子進程的PID:

編譯上述程序,運行,我們看到2個a.out進程:

殺死子進程4578,看到父進程的打印:

之後,4578會消失,因爲父進程執行到了wait,也知道了子進程是被信號2殺掉的。

但是如果子進程死了,父進程不執行到wait,比如把上圖中的"#if 0"改爲"#if 1",殺死子進程後,子進程就會是一個殭屍:

我們重新運行,當我們用kill -2殺掉子進程4628後,我們發現4628成爲一個殭屍,狀態變爲Z+,名字上也加了一個棺材[],成爲[a.out]:

殭屍不可能被殺死

我們看到上面4628是個殭屍很不爽,所以我們想把它幹掉,據說Linux有個信號9,神擋殺神,佛擋殺佛,我們現在來用kill -9幹掉4628:

從上圖可以看出,我們把4628用kill -9捅了好多刀,但是最後看4628這個殭屍,還是沒有消失。

因爲殭屍已經是死了,它不可能再次被殺死,你給它捅一萬刀,它也是個死人,不可能再次死!

殭屍不可能被殺死,因爲它已經死了!只等父進程來wait清理屍體了。

這個時候我們能夠把殭屍消失掉的方法,就是殺死殭屍進程的父進程4627。

一個殭屍可以被殺死的假象

下面的這個程序證明“殭屍可以被殺死”

我們在主線程裏面,pthread_create()創建線程後,pthread_exit()退出,這個時候我們會發現,在ps命令裏面,a.out顯示爲一個殭屍:

這個時候我們來殺死4730這個殭屍:

kill -9 4730

我們會驚奇地發現,4730真地會從ps命令裏面消失!

我們把時間軸拉回調用"kill -9 4730"之前。剛纔我們“看起來”能殺死殭屍的本質原因是,當主線程4730調用pthread_exit()退出後,主線程4730的狀態確實是殭屍了,但是該進程裏面的4731線程,卻沒有死:

4731是活着的,證明整個進程並沒有掛。所以4730的退出,只是讓整個進程半死。而由於ps這些命令的誤會,4730湊巧又是整個進程的PID,它顯示地好像整個4370成了殭屍一樣。

那麼,根據POSIX標準關於信號(signal)的定義,當我們執行kill -9 4730(4730是4730和4731的TGID,也是整個進程用戶態視角的PID)的時候,是要殺死整個4730進程的,所以這個時候4731被我們殺死,整個進程就都死了,這個時候,執行到父進程的wait邏輯,導致殭屍消失。

所以,在本例中,kill -9 4730看起來是"殺死了殭屍”,實際是殺死了4730整個進程(裏面的每個線程),導致整個進程死。在次之前,整個進程實際還是活的。

 

 

 

 

 

 

 

 

 

 

 

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