僵尸進(jìn)程是指它的父進(jìn)程已經(jīng)退出(父進(jìn)程沒(méi)有等待(調(diào)用wait/waitpid)它),而該進(jìn)程dead之后沒(méi)有進(jìn)程接受,就成為僵尸進(jìn)程,也就是(zombie)進(jìn)程。
一個(gè)進(jìn)程在調(diào)用了exit命令之后結(jié)束了自己的生命時(shí)候,你以為是真的被徹底銷毀了嗎?其實(shí)不然,它只是變成了我們稱之為“僵尸進(jìn)程”狀態(tài)。在用戶態(tài)程序調(diào)用系統(tǒng)調(diào)用exit時(shí),也僅僅限于將一個(gè)正常的進(jìn)程變成了一個(gè)僵尸進(jìn)程,并沒(méi)有完全的銷毀。看下圖所示:
在linux中,進(jìn)程的狀態(tài)有5種,其中僵尸進(jìn)程狀態(tài)是一種比較奇葩的存在方式,它放棄了幾乎所有的內(nèi)存地址空間,也沒(méi)有任何的可執(zhí)行的代碼,也不可能被調(diào)度器再次調(diào)度,它僅僅是在進(jìn)程列表中保留一個(gè)位置,在這個(gè)位置中記載了該進(jìn)程的狀態(tài)。而它也只是靜靜的等待著其他進(jìn)程(父進(jìn)程后者init進(jìn)程)為他收尸。
假如它的父進(jìn)程沒(méi)有安裝SIGCHLD信號(hào)處理函數(shù)來(lái)處理子進(jìn)程(也即使wait或者waitpid等待兒子結(jié)束),又沒(méi)有顯示忽略該信號(hào),那子進(jìn)程就會(huì)一直保持僵尸狀態(tài)。只有在父進(jìn)程結(jié)束之后,才由init進(jìn)程接管子進(jìn)程,為他收尸(好凄慘啊),這個(gè)時(shí)候才能說(shuō)子進(jìn)程才真正的消失在Linux內(nèi)核中。
又假如父進(jìn)程是個(gè)無(wú)限循環(huán)的進(jìn)程,那么子進(jìn)程就會(huì)一直保持僵尸狀態(tài)。這就能解釋為什么系統(tǒng)運(yùn)行久了,會(huì)出現(xiàn)大量的僵尸狀態(tài)的進(jìn)程。出現(xiàn)僵尸狀態(tài)進(jìn)程的數(shù)量少,是沒(méi)有任何問(wèn)題的,一旦出現(xiàn)巨量情況,就會(huì)導(dǎo)致PID用完,而給新的進(jìn)程分配PID,當(dāng)然也就會(huì)創(chuàng)建新進(jìn)程失敗。
為什么要有僵尸狀態(tài)呢?
主要是因?yàn)楦高M(jìn)程可能要取得子進(jìn)程的退出狀態(tài)等信息。僵尸狀態(tài)是每一個(gè)進(jìn)程必須要經(jīng)過(guò)的過(guò)程(除init進(jìn)程之外)。
那怎么避免呢?
當(dāng)前能給出四種方案,分別是:
- 父進(jìn)程通過(guò)wait或waitpid函數(shù)等待子進(jìn)程結(jié)束,這樣有個(gè)問(wèn)題,就是會(huì)導(dǎo)致父進(jìn)程掛起。
- 如果父進(jìn)程很忙,可以采用異步的方式,注冊(cè)SIGCHLD信號(hào)處理函數(shù),在處理函數(shù)中wait回收子進(jìn)程。
- 如果父進(jìn)程對(duì)子進(jìn)程生死不感興趣,也可以通過(guò)signal(SIGCHLD,SIG_IGN)告知內(nèi)核,忽視掉該信號(hào)。當(dāng)然子進(jìn)程結(jié)束后,內(nèi)核會(huì)幫助回收。
- 還可以用一些技巧,比如fork兩次。子進(jìn)程退出,孫進(jìn)程就由init進(jìn)程接管回收了。這個(gè)方法的代碼網(wǎng)絡(luò)上多如牛毛。自信百度查看。
?
如何查看僵尸進(jìn)程呢?
在Linux中,可以使用ps命令,ps 命令就是最根本相應(yīng)情況下也是相當(dāng)強(qiáng)大地進(jìn)程查看命令.運(yùn)用該命令可以確定有哪些進(jìn)程正在運(yùn)行和運(yùn)行地狀態(tài)、 進(jìn)程 是否結(jié)束、進(jìn)程有沒(méi)有僵死、哪些進(jìn)程占用了過(guò)多地資源等等.總之大部分信息均為可以通過(guò)執(zhí)行該命令得到地.
標(biāo)記“Z”的進(jìn)程就是僵尸進(jìn)程了。
ps -ef
可以用ps的-l選項(xiàng),得到更詳細(xì)的進(jìn)程信息.
F(Flag):一系列數(shù)字的和,表示進(jìn)程的當(dāng)前狀態(tài)。這些數(shù)字的含義為:
00:若單獨(dú)顯示,表示此進(jìn)程已被終止。 01:進(jìn)程是核心進(jìn)程的一部分,常駐于系統(tǒng)主存。如:sched、 vhand 、bdflush 等。 02:Parent is tracing process. 04:Tracing parent’s signal has stopped the process; the parent is waiting ( ptrace(S)). 10:進(jìn)程在優(yōu)先級(jí)低于或等于25時(shí),進(jìn)入休眠狀態(tài),而且不能用信號(hào)喚醒,例如在等待一個(gè)inode被創(chuàng)建時(shí) 20:進(jìn)程被裝入主存(primary memory) 40:進(jìn)程被鎖在主存,在事務(wù)完成前不能被置換
S(state of the process )
O:進(jìn)程正在處理器運(yùn)行 S:休眠狀態(tài)(sleeping) R:等待運(yùn)行(runable) I:空閑狀態(tài)(idle) Z:僵尸狀態(tài)(zombie) T:跟蹤狀態(tài)(Traced) B:進(jìn)程正在等待更多的內(nèi)存頁(yè) C:cpu利用率的估算值(cpu usage)
另外使用top命令查看時(shí)有一欄為S,如果狀態(tài)為Z說(shuō)明它就是僵尸進(jìn)程。






