殭屍程序的產生:
當乙個程序建立了乙個子程序時,他們的執行時非同步的。即父程序無法預知子程序會在什麼時候結束,那麼如果父程序很繁忙來不及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
?
#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
?
#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**了子程序的資源。從而避免了殭屍程序的產生。
殭屍程序是如何產生的?怎樣避免殭屍程序的產生
殭屍程序的產生 當乙個程序建立了乙個子程序時,他們的執行時非同步的。即父程序無法預知子程序會在什麼時候結束,那麼如果父程序很繁忙來不及wait 子程序時,那麼當子程序結束時,會不會丟失子程序的結束時的狀態資訊呢?處於這種考慮unix提供了一種機制可以保證只要父程序想知道子程序結束時的資訊,它就可以得...
Linux下如何避免殭屍程序的產生
比如程序採用exit 退出的時候,作業系統會進行一些列的處理工作,包括關閉開啟的檔案描述符 占用的記憶體等等,但是,作業系統也會為該程序保留少量的資訊,比如程序id號等資訊,因而占用了系統的資源。在一種極端的情況下,檔殭屍程序過多的時候,占用了大量的程序id,系統將無法產生新的程序,相當於系統的資源...
殭屍程序的產生原因和避免方法
殭屍程序的產生 當乙個程序建立了乙個子程序時,他們的執行時非同步的。即父程序無法預知子程序會在什麼時候結束,那麼如果父程序很繁忙來不及wait 子程序時,那麼當子程序結束時,會不會丟失子程序的結束時的狀態資訊呢?處於這種考慮unix提供了一種機制可以保證只要父程序想知道子程序結束時的資訊,它就可以得...