殭屍程序的產生原因和避免方法

2021-06-28 10:06:16 字數 4494 閱讀 5410



殭屍程序的產生:

當乙個程序建立了乙個子程序時,他們的執行時非同步的。即父程序無法預知子程序會在什麼時候結束,那麼如果父程序很繁忙來不及wait 子程序時,那麼當子程序結束時,會不會丟失子程序的結束時的狀態資訊呢?處於這種考慮unix提供了一種機制可以保證只要父程序想知道子程序結束時的資訊,它就可以得到。

這種機制是:在每個程序退出的時候,核心釋放該程序所有的資源,包括開啟的檔案,占用的記憶體。但是仍然保留了一些資訊(如程序號pid 退出狀態 執行時間等)。這些保留的資訊直到程序通過呼叫wait/waitpid時才會釋放。這樣就導致了乙個問題,如果沒有呼叫wait/waitpid的話,那麼保留的資訊就不會釋放。比如程序號就會被一直占用了。但系統所能使用的程序號的有限的,如果產生大量的殭屍程序,將導致系統沒有可用的程序號而導致系統不能建立程序。所以我們應該避免殭屍程序

這裡有乙個需要注意的地方。如果子程序先結束而父程序後結束,即子程序結束後,父程序還在繼續執行但是並未呼叫wait/waitpid那子程序就會成為殭屍程序。

但如果子程序後結束,即父程序先結束了,但沒有呼叫wait/waitpid來等待子程序的結束,此時子程序還在執行,父程序已經結束。那麼並不會產生殭屍程序。應為每個程序結束時,系統都會掃瞄當前系統中執行的所有程序,看看有沒有哪個程序時剛剛結束的這個程序的子程序,如果有,就有init來接管它,成為它的父程序。

同樣的在產生殭屍程序的那種情況下,即子程序結束了但父程序還在繼續執行(並未呼叫wait/waitpid)這段期間,假如父程序異常終止了,那麼該子程序就會自動被init接管。那麼它就不再是殭屍程序了。應為intit會發現並釋放它所占有的資源。(當然如果程序表越大,init發現它接管殭屍程序這個過程就會變得越慢,所以在init為發現他們之前,殭屍程序依舊消耗著系統的資源)

我們先來討論 父程序先結束的情況:

比如這段**。我們讓子程序迴圈列印5次語句 父程序迴圈列印3次語句。並在父程序中呼叫wait()等待子程序的結束//

[cpp]view plain

copy

print?

#include

#include

#include

#include

#include

int main()  

for(;count>0;count--)  

if(pid)  

wait((int *)0);  

if(pid)  

printf("father programdone.\n");  

else

printf("child programdnoe\n");  

exit(0);  

}  

#include#include#include#include#includeint main()

for(;count>0;count--)

if(pid)

wait((int *)0);

if(pid)

printf("father programdone.\n");

else

printf("child programdnoe\n");

exit(0);

}

我們讓程式在後台執行,並用ps命令檢視程序狀態。

我們從輸出中看到

第一行顯示了我們執行的程序pid是27324

ps 的輸出中我們看到了他有乙個2735的子程序,

父程序迴圈三次後並不會結束,而是等待子程序結束後再結束。

這裡並未產生殭屍程序

如果我們不等帶子程序的結束

if(pid)

wait((int *)0)注釋掉

將產生如下輸出

從第一行我們看到我們執行的程式pid為2804

ps輸出中的pid為2805 是建立的子程序。我們是在父程序結束後(未呼叫wait,所以父程序先結束)再用ps命令檢視的。所以2805的父程序變成了1 (init 的pid),因為2804已經結束了,所以2805這個子程序被 init接管,同樣這裡並未產生殭屍程序

現在我們來分析子程序後結束的情況:

我們  給出下面這個程式

[cpp]view plain

copy

print?

#include

#include

#include

#include

int main()  

for(;count>0;count--)  

if(pid)  

printf("father programdone.\n");  

else

printf("child prigramdone\n");  

exit(exit_success);  

}  

#include#include#include#includeint main()

for(;count>0;count--)

if(pid)

printf("father programdone.\n");

else

printf("child prigramdone\n");

exit(exit_success);

}

這裡的**改動很小,我們只是改變了父程序和子程序的 列印次數

並且在父程序中我們不呼叫wait/waitpid來釋放子程序的一些資訊

在子程序結束,但父程序還未結束時我們檢視程序資訊

第一行我們看到 我們執行的程式pid 是2874,它的子程序我們可以從ps輸出中看到為2875

我們注意到pid為2875的程序這時候成了殭屍程序。如果主線程執行的時間足夠長,那麼該殭屍程序就會一直存在著並占用著系統的一些資源。

我們已盡知道了殭屍程序的產生原因,那麼如何避免殭屍程序呢

如果父程序並不是很繁忙我們就可以通過直接呼叫wait/waitpid來等待子程序的結束。當然這會導致父程序被掛起。比如第一種情況中(父程序迴圈了三次,子程序迴圈了五次,子程序先結束,父程序呼叫wait等待子程序)父程序迴圈結束後並不會結束,而是被掛起等待子程序的結束。

但是如果父程序很忙。我們不希望父程序一直被掛起直到子程序的結束

那麼我們可以使用訊號函式sigaction為sigchld設定wait處理函式。這樣子程序結束後,父程序就會收到子程序結束的訊號。並呼叫wait**子程序的資源

這裡給出乙個例程

我們在子程序結束前 用 ps 檢視了一次結束後也檢視了一次。

從輸出我們看到,pid為2949的子程序正常結束了,並未產生殭屍程序。說明子程序結束後,父程序收到了它結束的訊息,並呼叫了wait**了子程序的資源。從而避免了殭屍程序的產生。

殭屍程序的產生原因

在linux系統中,殭屍程序是已經執行完畢,但是沒有被父程序 的子程序。判斷殭屍程序的乙個方法是使用ps命令檢視程序狀態。如果程序狀態是z,說明這是乙個殭屍程序。在多程序的程式中,父程序會啟動若干個子程序來處理任務。當子程序退出後,除了在程序表中占用的乙個程序表項,子程序所使用的資源 檔案描述符 記...

mysql殭屍程序 殭屍程序產生原因和解決方法

在linux系統中,當用ps命令觀察程序的執行狀態時,經常看到某些程序的狀態列為defunct,這就是所謂的 殭屍 程序。殭屍 程序是乙個早已死亡的程序,但在程序表 processs table 中仍佔了乙個位置 slot 由於程序表的容量是有限的,所以,defunct程序不僅占用系統的記憶體資源,...

殭屍程序產生原因和解決方法

在linux系統中,當用ps命令觀察程序的執行狀態時,經常看到某些程序的狀態列為defunct,這就是所謂的 殭屍 程序。殭屍 程序是乙個早已死亡的程序,但在程序表 processs table 中仍佔了乙個位置 slot 由於程序表的容量是有限的,所以,defunct程序不僅占用系統的記憶體資源,...