作業系統

當前位置 /首頁/計算機/作業系統/列表

Linux系統中查殺殭屍程序方法介紹

在UNIX 系統中,一個程序結束了,但是他的父程序沒有等待(呼叫wait / waitpid)他, 那麼他將變成一個殭屍程序. 在fork()/execve()過程中,假設子程序結束時父程序仍存在,而父程序fork()之前既沒安裝SIGCHLD訊號處理函式呼叫 waitpid()等待子程序結束,又沒有顯式忽略該訊號,則子程序成為殭屍程序。

Linux系統中查殺殭屍程序方法介紹

一個程序在呼叫exit命令結束自己的生命的時候,其實它並沒有真正的被銷燬, 而是留下一個稱為殭屍程序(Zombie)的資料結構(系統呼叫exit,它的作用是 使程序退出,但也僅僅限於將一個正常的程序變成一個殭屍程序,並不能將其完全銷燬)

程序的危害

由於子程序的結束和父程序的執行是一個非同步過程,即父程序永遠無法預測子程序 到底什麼時候結束. 那麼會不會因為父程序太忙來不及wait子程序,或者說不知道 子程序什麼時候結束,而丟失子程序結束時的狀態資訊呢? 不會。因為UNⅨ提供了一種機制可以保證只要父程序想知道子程序結束時的狀態資訊, 就可以得到。這種機制就是: 在每個程序退出的時候,核心釋放該程序所有的資源,包括開啟的檔案,佔用的.記憶體等。但是仍然為其保留一定的資訊(包括程序號the process ID,退出狀態the termination status of the process,執行時間the amount of CPU time taken by the process等)。直到父程序通過wait / waitpid來取時才釋放. 但這樣就導致了問題,如果程序不呼叫wait / waitpid的話,那麼保留的那段資訊就不會釋放,其程序號就會一直被佔用,但是系統所能使用的程序號是有限的,如果大量的產生僵死程序,將因為沒有可用的程序號而導致系統不能產生新的程序. 此即為殭屍程序的危害,應當避免。

1、如何檢視殭屍程序?

如何檢視linux系統上的殭屍程序,如何統計有多少殭屍程序?

#ps -ef | grep defunct

或者查詢狀態為Z的程序,Z就是代表zombie process,殭屍程序的意思。

另外使用top命令檢視時有一欄為S,如果狀態為Z說明它就是殭屍程序。

Tasks: 95 total, 1 running, 94 sleeping, 0 stopped, 0 zombie

top命令中也統計了殭屍程序。或者使用下面的命令:

ps -ef | grep defunct | grep -v grep | wc -l

2、如何殺死殭屍程序?

一般殭屍程序很難直接kill掉,不過您可以kill殭屍爸爸。父程序死後,殭屍程序成為”孤兒程序”,過繼給1號程序init,init始終會負責清理殭屍程序.它產生的所有殭屍程序也跟著消失。

ps -e -o ppid,stat | grep Z | cut –d” ” -f2 | xargs kill -9

kill -HUP `ps -A -ostat,ppid | grep -e ’^[Zz]‘ | awk ’{print $2}’`

當然您可以自己編寫更好的shell指令碼,歡迎與大家分享。

另外子程序死後,會發送SIGCHLD訊號給父程序,父程序收到此訊號後,執行waitpid()函式為子程序收屍。就是基於這樣的原理:就算父程序沒有呼叫wait,核心也會向它傳送SIGCHLD訊息,而此時,儘管對它的預設處理是忽略,如果想響應這個訊息,可以設定一個處理函式。

3、如何避免殭屍程序?

處理SIGCHLD訊號並不是必須的。但對於某些程序,特別是伺服器程序往往在請求到來時生成子程序處理請求。如果父程序不等待子程序結 束,子程序將成為殭屍程序(zombie)從而佔用系統資源。如果父程序等待子程序結束,將增加父程序的負擔,影響伺服器程序的併發效能。在Linux下 可以簡單地將 SIGCHLD訊號的操作設為SIG_IGN。

signal(SIGCHLD,SIG_IGN);

這樣,核心在子程序結束時不會產生殭屍程序。這一點與BSD4不同,BSD4下必須顯式等待子程序結束才能釋放殭屍程序;或者用兩次fork(),而且使緊跟的子程序直接退出,是的孫子程序成為孤兒程序,從而init程序將負責清除這個孤兒程序。