Linux 殭屍程序與孤兒程序

2021-09-01 06:00:10 字數 3180 閱讀 2510

殭屍程序:

乙個程序使用 fork 建立子程序,如果子程序退出而父程序並沒有呼叫 wait() 或者 waitpid() 獲取子程序資訊,

那麼子程序的描述符仍然儲存在系統中。這種程序就被稱為殭屍程序 -------- 即 z 程序

危害及解決辦法:
乙個程序會定期的產生一些子程序,這些子程序由於處理的事情很少並且處理完後會退出,即生命周期短。但是這些子程序退出之後,

它們的狀態資訊還會保留在系統中,它們的父程序只管生成新的子程序,並沒有去呼叫 wait() 或者 waitpid() 去獲取子程序的狀態資訊,

系統執行一段時間之後就會有大量的僵死程序,用 ps 命令來檢視的話就會看到許多狀態為 z 的程序。

危害:占用資源不放,正常程序可能無法進行建立

解決辦法:
我們要解決的話就只能找到那個產生大量僵死程序的父程序,只有殺死掉那個父程序 (通過 kill 傳送 sigterm 或 sigkill) 

殺死掉那個父程序之後,那些僵死程序就成了孤兒程序,孤兒程序會被 init 程序接管,init 會 wait 掉這些孤兒程序並且釋放它們在系統中

占用的資源這些僵死的孤兒程序就會死去。

繼續殭屍程序:

1. 產生原因:

在unix 系統中,乙個程序結束了,但是他的父程序沒有等待(呼叫wait / waitpid)它,那麼他將變成乙個殭屍程序。

通過ps命令檢視其帶有defunct的標誌。殭屍程序是乙個早已死亡的程序,但在程序表 (processs table)中仍佔了乙個位置(slot)。

但是如果該程序的父程序已經先結束了,那麼該程序就不會變成殭屍程序。因為每個程序結束的時候,

系統都會掃瞄當前系統中所執行的所有程序,看看有沒有哪個 程序是剛剛結束的這個程序的子程序,如果是的話,就由init程序來接管他,

成為他的父程序,從而保證每個程序都會有乙個父程序。而init程序會自動 wait其子程序,因此被init接管的所有程序都不會變成殭屍程序。

2. 原理分析:
每個unix程序在程序表裡都有乙個進入點(entry),核心程序執 行該程序時使用到的一切資訊都儲存在進入點。

當用 ps 命令察看系統中的程序資訊時,看到的就是程序表中的相關資料。當以fork()系統呼叫建立乙個新的程序後,

核心程序就會在程序表中給這個新程序分配乙個 進入點,然後將相關資訊儲存在該進入點所對應的程序表內。

這些資訊中有一項是其父程序的識別碼。

子程序的結束和父程序的執行是乙個非同步過程,即父程序永遠無法**子程序到底什麼時候結束。那麼會不會因為父程序太忙來不及

wait 子程序,或者說不知道子程序什麼時候結束,而丟失子程序結束時的狀態資訊呢?不會。因為unix提供了一種機制可以保證,

只要父程序想知道子程序結束時的 狀態資訊,就可以得到。這種機制就是:當子程序走完了自己的生命週期後,它會執行exit()

系統呼叫,核心釋放該程序所有的資源,包括開啟的檔案,占用 的記憶體等。但是仍然為其保留一定的資訊(包括程序號the process id,

退出碼exit code,退出狀態the terminationstatus of the process,執行時間the amount of cpu time taken by the process等),

這些資料會一直保留到系統將它傳遞給它的父程序為止,直到父程序通過wait / waitpid來取時才釋放。

3.解決方法:
(1) 父程序通過wait和waitpid等函式等待子程序結束,這會導致父程序掛起。

在這種情形下就不會產生defunct程序。

(2) 如果父程序很忙,那麼可以用signal函式為sigchld安裝handler。在子程序結束後,父程序會收到該訊號,可以在handler中

呼叫wait**。

(3) 如果父程序不關心子程序什麼時候結束,那麼可以用signal(sigcld, sig_ign)或signal(sigchld, sig_ign)通知核心,

自己對子程序的結束不感興趣,那麼子程序結束後,核心會**,並不再給父程序傳送訊號

(4)fork兩次,父程序fork乙個子程序,然後繼續工作,子程序fork乙個孫程序後退出,那麼孫程序被init接管,孫程序結束後,

init會**。不過子程序的**還要自己做。

孤兒程序概念:
如果父程序退出而它的乙個或多個子程序還在執行,那麼這些子程序就被稱為孤兒程序孤兒程序最終將被 init 程序 (程序號為 1 的 

init程序) 所收養並由 init 程序完成對它們的狀態收集工作。

孤兒程序說明:
孤兒程序是沒有危害的,孤兒程序是沒有父程序的子程序,當孤兒程序沒有父程序時,核心就會init設定為孤兒程序的父程序,

init程序就會呼叫wait去釋放那些已經退出的子程序,當孤兒程序完成其宣告週期之後,init會釋放掉其狀態資訊。

每乙個程序(init除外)在執行exit之後,不會馬上消失會留下乙個稱為殭屍程序的資料結構來等父程序處理。父程序沒有及時

處理的話,用ps命令來檢視就會發現其狀態為「z」。父程序及時處理的話,雖然ps之後狀態資訊不是「z」但並不等於子程序不經過

殭屍狀態。

殭屍程序測試程式:
#include #include #include #include int main()

else if(id > 0)

else

//printf("hello world\n");

return 0;

}

測試結果:

孤兒程序測試程式:

#include #include #include #include int main()

else if(id == 0)

else

//printf("hello world\n");

return 0;

}

孤兒程序測試結果:

Linux 殭屍程序與孤兒程序

之前的部落格有講過儲存程序資訊的乙個重要的資料結構,task struct結構體,其中,state表示程序可能出現的狀態。如下 static const char const task state array 我們對個別狀態進行解釋如下 s sleeping 淺度睡眠,也是不可中斷睡眠。d disk...

Linux 殭屍程序與孤兒程序

產生原因 子程序先於父程序退出,他要保留退出原因在pcb中,因此退出後不會自動釋放所有資源,子程序退出後作業系統會通知父程序,子程序退出了,去獲取一下原因,然後完全釋放子程序資源,假如父程序不管子程序的退出狀態,那麼這個子程序將進入僵死狀態,成為殭屍程序 實現殭屍程序 該程式為20秒的殭屍程序,在第...

Linux 殭屍程序與孤兒程序

殭屍程序 產生原因 子程序先於父程序退出,他要保留退出原因在pcb中,因此退出後不會自動釋放所有資源,子程序退出後作業系統會通知父程序,子程序退出了,去獲取一下原因,然後完全釋放子程序資源,假如父程序不管子程序的退出狀態,那麼這個子程序將進入僵死狀態,成為殭屍程序 實現殭屍程序 該程式為20秒的殭屍...