殭屍程序
乙個程序使用fork建立子程序,如果子程序退出,而父程序並沒有呼叫wait()或waitpid()獲取子程序的狀態資訊,那麼子程序的程序描述符仍然儲存在系統中,這種程序稱之為殭屍程序。
什麼是殭屍程序
首先核心會釋放終止程序(呼叫了exit系統呼叫)所使用的所有儲存區,關閉所有開啟的檔案等,但核心為每乙個終止子程序儲存了一定量的資訊。這些資訊至少包括程序id號,程序的終止狀態,以及該程序使用的cpu時間,所以當終止子程序的父程序呼叫wait或waitpid時就可以得到這些資訊。
任何乙個子程序(init除外)在exit後並非馬上消失,而是留下乙個稱為殭屍程序的資料節後,等待父程序處理。這是每乙個子程序都必須經歷的階段,另外子程序退出的時候會向其父程序傳送乙個sigchld訊號。
殭屍程序的目的
設定僵死狀態的目的是維護子程序的資訊,以便父程序在以後的某個時候獲取。這些資訊至少包括程序id,程序的終止狀態,以及該程序使用的cpu時間,所以當終止子程序的父程序呼叫wait或waitpid時就可以得到這些資訊。如果乙個父程序終止,而該程序有子程序處於殭屍狀態,那麼它的所有殭屍子程序的父程序id將被重置為1(init程序)。繼承這些子程序的init程序將清理他們(也就是說init程序將wait他們,從而去除他們的殭屍狀態)。
殭屍程序如何產生
如果乙個程序在其終止的時候,自己就**所有分配給它的資源,系統就不會產生所謂的殭屍程序了,那麼我們所說乙個程序終止之後,還會保留哪些資訊?為什麼要保留這些資訊呢?
乙個程序終止的方法有很多,程序終止後有些資訊對於父程序和核心還是很有用的,例如程序的id號,程序的退出狀態,程序執行的cpu時間等。因此程序在終止時,**多有核心分配給他們的記憶體,關閉他開啟的所有檔案等等,但是還會保留以上極少的資訊,以供父程序使用。父程序可以使用wait或waitpid等系統呼叫來為子程序收屍,做一些收尾工作。
因此,乙個殭屍程序產生的過程是:父程序呼叫fork建立子程序後,子程序執行直至其終止,它立即從記憶體中移除,但程序描述符仍然保留在記憶體中(程序描述符占有極少的記憶體空間)。子程序的狀態程式設計exit_zombie,並且向父程序傳送sigchld訊號,父程序此時應該呼叫wait()系統呼叫來獲取子程序的退出狀態以及其他的資訊。在wait呼叫之後,殭屍程序就完全從記憶體中移除。因此乙個殭屍存在於其終止到其父程序呼叫wait等函式這個時間的間隙,一般很快就消失了,但如果程式設計不合理,父程序從不呼叫wait等系統呼叫來收集殭屍程序,那麼這些程序會一直存在於記憶體中。
在linux下,我們可以使用ps等命令檢視系統中殭屍程序,殭屍程序的狀態標記為『z』
殭屍程序的問題及危害
unix提供了一種機制可以保證只要父程序想知道子程序結束時的狀態資訊,就可以得到。這種機制就是:在每個程序退出的時候,核心釋放該程序的所有資源,包括開啟的檔案,占用的記憶體等。但是仍然為其保留一定的資訊(包括程序號,退出窗台,執行時間等)。直到父程序呼叫wait/waitpid來取時才釋放。但這樣就導致了問題,如果父程序不呼叫wait/waitpid的話,那麼保留的那段資訊就不會釋放,其程序號就會一直被占用,但是系統所能使用的程序號是有限的,如果大量的產生殭屍程序,將因為可能沒有可用的程序號而導致系統不能產生新的程序,這就是殭屍程序的危害,應當避免。
如何避免殭屍程序
1.通過signal(sigchld,sig_ign)通知核心對子程序的結束不關心,由核心**,如果不想讓父程序掛起,可以在父程序中加一條語句,signal(sigchld,sig_ign);表示父程序忽略sigchld訊號,該訊號是子程序退出的時候向父程序傳送的。
2.父程序呼叫wait/waitpid等函式等待子程序結束,如果尚無子程序退出,wait會導致父程序阻塞。waitpid可以通過傳遞wnohang使父程序不阻塞立即返回。
3.如果父程序很忙可以用signal註冊新號處理函式,在訊號處理函式呼叫wait/waitpid等待子程序退出。
4.通過兩次呼叫fork。父程序首先呼叫fork建立乙個子程序然後waitpid等待子程序退出,子程序再fork乙個孫程序後退出,這樣子程序退出後會被父程序等待**,而對於孫程序其父程序已經退出所以孫程序成為乙個孤兒程序,孤兒程序由init程序接管,孫程序結束後,init會等待**。
殭屍程序測試
1 #include
2 #include
3 #include
4 #include
56 int main()
719else
if(pid ==0)
2023}24
else
2529}30
return0;
31}
呼叫ps -ef | grep 「zombiel」可以檢視當前的殭屍程序
呼叫ps -ef | grep defunct | grep -v grep | wc -l可以統計殭屍程序的數目。
殭屍程序的解決辦法
1.通過訊號機制
子程序退出時向父程序傳送sigchld訊號,父程序處理sigchld訊號。在訊號處理函式中呼叫wait進行處理殭屍程序。測試如下:
2.fork兩次
原理是將子程序成為孤兒程序,從而其父程序變為init程序,通過init程序可以處理殭屍程序
孤兒程序乙個父程序退出,而他的乙個或多個子程序還在執行,那麼那些子程序將成功孤兒程序。孤兒程序將被init程序所收養,並由init程序對他們完成狀態收集工作。
孤兒程序沒有什麼危害
殭屍程序和孤兒程序
殭屍程序 乙個子程序在其父程序還沒有呼叫wait 或waitpid 的情況下退出。這個子程序就是殭屍程序。孤兒程序 乙個父程序退出,而它的乙個或多個子程序還在執行,那麼那些子程序將成為孤兒程序。孤兒程序將被init程序 程序號為1 所收養,並由init程序對它們完成狀態收集工作。殭屍程序將會導致資源...
殭屍程序和孤兒程序
什麼是殭屍程序?乙個子程序在其父程序沒有呼叫wait 或waitpid 的情況下退出。這個子程序就是殭屍程序。如果其父程序還存在而一直不呼叫wait,則該殭屍程序將無法 等到父程序結束後,會被init 驗證 include include includeint main 3秒後查詢其程序資訊 通過上...
殭屍程序和孤兒程序
殭屍程序和孤兒程序 在unix系統程式設計中,常常會碰到兩個概念 僵死程序和孤兒程序 僵死程序 在unix程序模型中,程序是按照父程序產生子程序,子程序產生子子程序這樣的方式建立出完成各項相互協作功能的程序的。當乙個程序完成它的工作終止之後,它的父程序需要呼叫wait 或者waitpid 系統呼叫取...