1. 程式人生 > >Linux的殭屍程序產生原因及解決方法

Linux的殭屍程序產生原因及解決方法

來源:http://www.blogdaren.com/post-882.html

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等函式等待子程序結束,這會導致父程序掛起。

    執行wait()或waitpid()系統呼叫,則子程序在終止後會立即把它在程序表中的資料返回給父程序,此時系統會立即刪除該進入點。在這種情形下就不會產生defunct程序。

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

    (3) 如果父程序不關心子程序什麼時候結束,那麼可以用signal(SIGCLD, SIG_IGN)或signal(SIGCHLD, SIG_IGN)通知核心,自己對子程序的結束不感興趣,那麼子程序結束後,核心會回收,並不再給父程序傳送訊號

    (4)fork兩次,父程序fork一個子程序,然後繼續工作,子程序fork一個孫程序後退出,那麼孫程序被init接管,孫程序結束後,init會回收。不過子程序的回收還要自己做。