孤兒程序:乙個父程序退出,而它的乙個或多個子程序還在執行,那麼那些子程序將成為孤兒程序。孤兒程序將被init程序(程序號為1)所收養,並由init程序對它們完成狀態收集工作。
殭屍程序:乙個程序使用fork建立子程序,如果子程序退出,而父程序並沒有呼叫wait或waitpid獲取子程序的狀態資訊,那麼子程序的程序描述符仍然儲存在系統中。這種程序稱之為僵死程序。
unix提供了一種機制可以保證只要父程序想知道子程序結束時的狀態資訊,這種機制就是: 在每個程序退出的時候,核心釋放該程序所有的資源,包括開啟的檔案,占用的記憶體等。 但是仍然為其保留一定的資訊(包括程序號the process id,退出狀態the termination status of the process,執行時間the amount of cpu time taken by the process等),直到父程序通過wait / waitpid來取時才釋放。
但這樣就導致了問題,如果程序不呼叫wait / waitpid的話, 那麼保留的那段資訊就不會釋放,其程序號就會一直被占用,但是系統所能使用的程序號是有限的,如果大量的產生僵死程序,將因為沒有可用的程序號而導致系統不能產生新的程序.。此即為殭屍程序的危害,應當避免。
孤兒程序是沒有父程序的程序,孤兒程序這個重任就落到了init程序身上,init程序就好像是乙個民政局,專門負責處理孤兒程序的善後工作。每當出現乙個孤兒程序的時候,核心就把孤 兒程序的父程序設定為init,而init程序會迴圈地wait()它的已經退出的子程序。這樣,當乙個孤兒程序淒涼地結束了其生命週期的時候,init程序就會代表黨和**出面處理它的一切善後工作。因此孤兒程序並不會有什麼危害。
任何乙個子程序(init除外)在exit()之後,並非馬上就消失掉,而是留下乙個稱為殭屍程序(zombie)的資料結構,等待父程序處理。這是每個子程序在結束時都要經過的階段。如果子程序在exit()之後,父程序沒有來得及處理,這時用ps命令就能看到子程序的狀態是「z」。如果父程序能及時 處理,可能用ps命令就來不及看到子程序的殭屍狀態,但這並不等於子程序不經過殭屍狀態。 如果父程序在子程序結束之前退出,則子程序將由init接管。init將會以父程序的身份對殭屍狀態的子程序進行處理。
例如有個程序,它定期的產 生乙個子程序,這個子程序需要做的事情很少,做完它該做的事情之後就退出了,因此這個子程序的生命週期很短,但是,父程序只管生成新的子程序,至於子程序退出之後的事情,則一概不聞不問,這樣系統執行上一段時間之後,系統中就會存在很多的僵死程序,倘若用ps命令檢視的話,就會看到很多狀態為z的程序。 嚴格地來說,僵死程序並不是問題的根源,罪魁禍首是產生出大量僵死程序的那個父程序。
因此,當我們尋求如何消滅系統中大量的僵死程序時,答案就是把產生大量僵死程序的那個元凶槍斃掉(也就是通過kill傳送sigterm或者sigkill訊號啦)。槍斃了元凶程序之後,它產生的僵死程序就變成了孤兒進 程,這些孤兒程序會被init程序接管,init程序會wait()這些孤兒程序,釋放它們占用的系統程序表中的資源,這樣,這些已經僵死的孤兒程序 就能瞑目而去了。
三、樣例測試
1、孤兒程序測試程式:
#include #include測試結果:#include
#include
intmain()
//子程序
if (pid == 0
)
//父程序
else
return0;
}
2、殭屍程序測試程式
#include #include測試結果:#include
#include
intmain()
else
if (pid == 0
)
printf(
"i am father process.i will sleep two seconds\n");
//等待子程序先退出
sleep(2
);
//輸出程序資訊
system("
ps -o pid,ppid,state,tty,command");
printf(
"father process is exiting.\n");
return0;
}
3、殭屍程序測試2
父程序迴圈建立子程序,子程序退出,造成多個殭屍程序,程式如下所示:
#include #include測試結果:#include
#include
intmain()
else
if (pid == 0
)
else
}return0;
}
1、通過訊號機制
子程序退出時向父程序傳送sigchild訊號,父程序處理sigchild訊號。在訊號處理函式中呼叫wait進行處理殭屍程序。測試程式如下所示:
#include #include測試結果:#include
#include
#include
static
void sig_child(int
signo);
intmain()
else
if (pid == 0
)
printf(
"i am father process.i will sleep two seconds\n");
//等待子程序先退出
sleep(2
);
//輸出程序資訊
system("
ps -o pid,ppid,state,tty,command");
printf(
"father process is exiting.\n");
return0;
}static
void sig_child(int
signo)
2、fork兩次
原理是:將子程序成為孤兒程序,從而其的父程序變為init程序,通過init程序可以處理殭屍程序。測試程式如下所示
#include #include測試結果:#include
#include
intmain()
//第乙個子程序
else
if (pid == 0
)
//第乙個子程序退出
else
if (pid >0
)
//第二個子程序
//睡眠3s保證第乙個子程序退出,這樣第二個子程序的父親就是init程序裡
sleep(3
); printf(
"i am the second child process.pid: %d\tppid:%d\n
",getpid(),getppid());
exit(0);
}//父程序處理第乙個子程序退出
if (waitpid(pid, null, 0) !=pid)
exit(0);
return0;
}
Linux 殭屍程序與孤兒程序
之前的部落格有講過儲存程序資訊的乙個重要的資料結構,task struct結構體,其中,state表示程序可能出現的狀態。如下 static const char const task state array 我們對個別狀態進行解釋如下 s sleeping 淺度睡眠,也是不可中斷睡眠。d disk...
Linux 殭屍程序與孤兒程序
產生原因 子程序先於父程序退出,他要保留退出原因在pcb中,因此退出後不會自動釋放所有資源,子程序退出後作業系統會通知父程序,子程序退出了,去獲取一下原因,然後完全釋放子程序資源,假如父程序不管子程序的退出狀態,那麼這個子程序將進入僵死狀態,成為殭屍程序 實現殭屍程序 該程式為20秒的殭屍程序,在第...
Linux 殭屍程序與孤兒程序
殭屍程序 產生原因 子程序先於父程序退出,他要保留退出原因在pcb中,因此退出後不會自動釋放所有資源,子程序退出後作業系統會通知父程序,子程序退出了,去獲取一下原因,然後完全釋放子程序資源,假如父程序不管子程序的退出狀態,那麼這個子程序將進入僵死狀態,成為殭屍程序 實現殭屍程序 該程式為20秒的殭屍...