淺議Unix進(jìn)程中defunct
我們?cè)赨nix系統(tǒng)管理中,當(dāng)用ps命令觀察Unix進(jìn)程的執(zhí)行狀態(tài)時(shí),經(jīng)常看到某些Unix進(jìn)程的狀態(tài)欄為defunct,這就是所謂的“僵尸”進(jìn)程。“僵尸”進(jìn)程是一個(gè)早已死亡的進(jìn)程,但在進(jìn)程表(processs table)中仍占了一個(gè)位置(slot)。由于Unix進(jìn)程表的容量是有限的,所以,defunct進(jìn)程不僅占用系統(tǒng)的內(nèi)存資源,影響系統(tǒng)的性能,而且如果其數(shù)目太多,還會(huì)導(dǎo)致系統(tǒng)癱瘓。
我們知道,每個(gè)Unix進(jìn)程在進(jìn)程表里都有一個(gè)進(jìn)入點(diǎn)(entry),核心程序執(zhí)行該Unix進(jìn)程時(shí)使用到的一切信息都存儲(chǔ)在進(jìn)入點(diǎn)。當(dāng)用ps命令察看系統(tǒng)中的進(jìn)程信息時(shí),看到的就是進(jìn)程表中的相關(guān)數(shù)據(jù)。
當(dāng)以fork()系統(tǒng)調(diào)用建立一個(gè)新的進(jìn)程后,核心進(jìn)程就會(huì)在進(jìn)程表中給這個(gè)新進(jìn)程分配一個(gè)進(jìn)入點(diǎn),然后將相關(guān)信息存儲(chǔ)在該進(jìn)入點(diǎn)所對(duì)應(yīng)的進(jìn)程表內(nèi)。這些信息中有一項(xiàng)是其父進(jìn)程的識(shí)別碼。
當(dāng)這個(gè)進(jìn)程走完了自己的生命周期后,它會(huì)執(zhí)行exit()系統(tǒng)調(diào)用,此時(shí)原來Unix進(jìn)程表中的數(shù)據(jù)會(huì)被該進(jìn)程的退出碼(exit code)、執(zhí)行時(shí)所用的CPU時(shí)間等數(shù)據(jù)所取代,這些數(shù)據(jù)會(huì)一直保留到系統(tǒng)將它傳遞給它的父進(jìn)程為止。由此可見,defunct進(jìn)程的出現(xiàn)時(shí)間是在子進(jìn)程終止后,但是父進(jìn)程尚未讀取這些數(shù)據(jù)之前。利用這一點(diǎn)我們可以用下面的程序建立一個(gè)defunct 進(jìn)程:
- CODE:#include
- #include
- main(){
- if(!fork()){
- printf(“child pid=%d\n”, getpid());
- exit(0)
- }
- sleep(20);
- printf(“parent pid=%d \n”, getpid());
- exit(0);
- }
當(dāng)上述程序以后臺(tái)的方式執(zhí)行時(shí),第8行強(qiáng)迫程序睡眠20秒,讓用戶有時(shí)間輸入ps -e指令,觀察進(jìn)程的狀態(tài)。當(dāng)父進(jìn)程執(zhí)行終止后,再用ps -e命令觀察時(shí),我們會(huì)發(fā)現(xiàn)defunct進(jìn)程也隨之消失。這是因?yàn)楦高M(jìn)程終止后,init 進(jìn)程會(huì)接管父進(jìn)程留下的這些“孤兒進(jìn)程”(orphan process),而這些“孤兒進(jìn)程”執(zhí)行完后,它在進(jìn)程表中的進(jìn)入點(diǎn)將被刪除。
如果一個(gè)程序設(shè)計(jì)上有缺陷,就可能導(dǎo)致某個(gè)Unix進(jìn)程的父進(jìn)程一直處于睡眠狀態(tài)或是陷入死循環(huán),那么當(dāng)該子進(jìn)程執(zhí)行結(jié)束后就變成了defunct進(jìn)程,這個(gè)defunct 進(jìn)程可能會(huì)一直留在系統(tǒng)中直到系統(tǒng)重新啟動(dòng)。
如果我們將上述程序略作修改,在第8行sleep()系統(tǒng)調(diào)用前執(zhí)行wait()或waitpid()系統(tǒng)調(diào)用,則子進(jìn)程在終止后會(huì)立即把它在Unix進(jìn)程表中的數(shù)據(jù)返回給父進(jìn)程,此時(shí)系統(tǒng)會(huì)立即刪除該進(jìn)入點(diǎn)。在這種情形下就不會(huì)產(chǎn)生defunct進(jìn)程。
由于調(diào)度程序無法選中Defunct 進(jìn)程,所以不能用kill命令刪除Defunct 進(jìn)程,惟一的方法只有重啟系統(tǒng)。
【編輯推薦】



















