什么是僵尸
首先要明確一點,僵尸進(jìn)程的含義是:子進(jìn)程已經(jīng)死了,但是父進(jìn)程還沒有wait它的一個中間狀態(tài),這個時候子進(jìn)程是一個僵尸。正常情況下子死,父wait,清理掉子進(jìn)程的task_struct,釋放子進(jìn)程的PID:
編譯上述程序,運行,我們看到2個a.out進(jìn)程:
殺死子進(jìn)程4578,看到父進(jìn)程的打?。?/p>
之后,4578會消失,因為父進(jìn)程執(zhí)行到了wait,也知道了子進(jìn)程是被信號2殺掉的。
但是如果子進(jìn)程死了,父進(jìn)程不執(zhí)行到wait,比如把上圖中的"#if 0"改為"#if 1",殺死子進(jìn)程后,子進(jìn)程就是一個僵尸:
我們重新運行,當(dāng)我們用kill -2殺掉子進(jìn)程4628后,我們發(fā)現(xiàn)4628成為一個僵尸,狀態(tài)變?yōu)閆+,名字上也加了一個棺材[],成為[a.out]:
僵尸不可能被殺死
我們看到上面4628是個僵尸很不爽,所以我們想把它干掉,據(jù)說Linux有個信號9,神擋殺神,佛擋殺佛,我們現(xiàn)在來用kill -9干掉4628:
從上圖可以看出,我們把4628用kill -9捅了好多刀,但是最后看4628這個僵尸,還是沒有消失。
因為僵尸已經(jīng)是死了,它不可能再次被殺死,你給它捅一萬刀,它也是個死人,不可能再次死!
僵尸不可能被殺死,因為它已經(jīng)死了!只等父進(jìn)程來wait清理尸體了。
一個僵尸可以被殺死的假象
下面的這個程序證明“僵尸可以被殺死”:
我們在主線程里面,pthread_create()創(chuàng)建線程后,pthread_exit()退出,這個時候我們會發(fā)現(xiàn),在ps命令里面,a.out顯示為一個僵尸:
這個時候我們來殺死4730這個僵尸:
kill -9 4730
我們會驚奇地發(fā)現(xiàn),4730真地會從ps命令里面消失!
我們把時間軸拉回調(diào)用"kill -9 4730"之前。剛才我們“看起來”能殺死僵尸的本質(zhì)原因是,當(dāng)主線程4730調(diào)用pthread_exit()退出后,主線程4730的狀態(tài)確實是僵尸了,但是該進(jìn)程里面的4731線程,卻沒有死:
看看4731:
4731是活著的,證明整個進(jìn)程并沒有掛。
那么,根據(jù)POSIX標(biāo)準(zhǔn)關(guān)于信號(signal)的定義,當(dāng)我們執(zhí)行kill -9 4730(4730是4730和4731的TGID,也是整個進(jìn)程用戶態(tài)視角的PID)的時候,是要殺死整個4730進(jìn)程的,所以這個時候4731被我們殺死,整個進(jìn)程就都死了,這個時候,執(zhí)行到父進(jìn)程的wait邏輯,導(dǎo)致僵尸消失。
所以,在本例中,kill -9 4730看起來是"殺死了僵尸”,實際是殺死了4731,導(dǎo)致整個進(jìn)程死
-
Linux
+關(guān)注
關(guān)注
87文章
11292瀏覽量
209323
原文標(biāo)題:宋寶華: Linux僵尸進(jìn)程可以被“殺死”嗎?
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論