殺死Linux中的defunct進程(殭屍進程)的方法指南

來源:互聯網
上載者:User

一、什麼是defunct進程(殭屍進程)
在 Linux  系統中,一個進程結束了,但是他的父進程沒有等待(調用wait /  waitpid)他,那麼他將變成一個殭屍進程。當用ps命令觀察進程的執行狀態時,看到這些進程的狀態列為defunct。殭屍進程是一個早已死亡的進程,但在進程表(processs  table)中仍佔了一個位置(slot)。
但是如果該進程的父進程已經先結束了,那麼該進程就不會變成殭屍進程。因為每個進程結束的時候,系統都會掃描當前系統中所啟動並執行所有進程,看看有沒有哪個進程是剛剛結束的這個進程的子進程,如果是的話,就由Init進程來接管他,成為他的父進程,從而保證每個進程都會有一個父進程。而Init進程會自動wait其子進程,因此被Init接管的所有進程都不會變成殭屍進程。

二、 Linux下進程的運作方式
每個  Linux進程在進程表裡都有一個進入點(entry),核心進程執行該進程時使用到的一切資訊都儲存在進入點。當用 ps  命令察看系統中的進程資訊時,看到的就是進程表中的相關資料。當以fork()系統調用建立一個新的進程後,核心進程就會在進程表中給這個新進程分配一個進入點,然後將相關資訊儲存在該進入點所對應的進程表內。這些資訊中有一項是其父進程的識別碼。
子進程的結束和父進程的運行是一個非同步過程,即父進程永遠無法預測子進程到底什麼時候結束。那麼會不會因為父進程太忙來不及 wait 子進程,或者說不知道子進程什麼時候結束,而丟失子進程結束時的狀態資訊呢?
不會。因為 Linux提供了一種機制可以保證,只要父進程想知道子進程結束時的狀態資訊,就可以得到。這種機制就是:當子進程走完了自己的生命週期後,它會執行exit()系統調用,核心釋放該進程所有的資源,包括開啟的檔案,佔用的記憶體等。但是仍然為其保留一定的資訊(包括進程號the  process ID,退出碼exit code,退出狀態the terminationstatus of the  process,已耗用時間the amount of CPU time taken by the  process等),這些資料會一直保留到系統將它傳遞給它的父進程為止,直到父進程通過wait / waitpid來取時才釋放。
也就是說,當一個進程死亡時,它並不是完全的消失了。進程終止,它不再運行,但是還有一些殘留的資料等待父進程收回。當父進程  fork() 一個子進程後,它必須用 wait() (或者 waitpid())等待子進程退出。正是這個 wait()  動作來讓子進程的殘留資料消失。

三、殭屍進程的危害
如果父進程不調用wait / waitpid的話,那麼保留的那段資訊就不會釋放,其進程號就會一直被佔用,但是系統的進程表容量是有限的,所能使用的進程號也是有限的,如果大量的產生殭屍進程,將因為沒有可用的進程號而導致系統不能產生新的進程。
所以,defunct進程不僅佔用系統的記憶體資源,影響系統的效能,而且如果其數目太多,還會導致系統癱瘓。而且,由於發送器無法選中Defunct 進程,所以不能用kill命令刪除Defunct 進程,惟一的方法只有重啟系統。

四、如何殺死defunct進程
defunct進程是指出錯損壞的進程,父子進程之間不會再通訊。有時,它們會演變成“殭屍進程”,存留在你的系統中,直到系統重啟。可以嘗試 “kill -9” 命令來清除,但多數時候不管用。
為了殺死這些defunct進程,你有兩個選擇:
1.重啟你的電腦
2.繼續往下讀...
我們先看看系統中是否存在defunct進程:

代碼如下:

$ ps -A | grep defunct

假設得到的輸出如下所示:

代碼如下:
8328 ? 00:00:00 mono
8522 ? 00:00:01 mono
13132 ? 00:00:00 mono
25822 ? 00:00:00 ruby
28383 ? 00:00:00 ruby
18803 ? 00:00:00 ruby

這意味著存在6個defunct進程:3個mono進程,以及3個ruby進程。這些進程之所以存在,可能是因為應用程式寫得很爛或者使用者做了不常見的操作,在我這,一定是我寫的mono C#程式存在嚴重問題 :smile: 。
現在,我們來看看這些進程的ID及其父進程ID:

代碼如下:

$ ps -ef | grep defunct | more

以上命令的輸出如下:

代碼如下:
UID PID PPID ...
---------------------------------------------------------------
kenno 8328 6757 0 Mar22 ? 00:00:00 [mono]
kenno 8522 6757 0 Mar22 ? 00:00:01 [mono]
kenno 13132 6757 0 Mar23 ? 00:00:00 [mono]
kenno 25822 25808 0 Mar27 ? 00:00:00 [ruby]
kenno 28383 28366 0 Mar27 ? 00:00:00 [ruby]
kenno 18803 18320 0 Apr02 ? 00:00:00 [ruby]

UID:使用者ID
PID:進程ID
PPID:父進程ID
如果你使用命令  “kill -9 8328”  嘗試殺死ID為8328的進程,可能會沒效果。要想成功殺死該進程,需要對其父進程(ID為6757)執行kill命令($ kill -9  6757)。對所有這些進程的父進程ID應用kill命令,並驗證結果($ ps -A | grep defunct)。
如果前一個命令顯示無結果,那麼搞定!否則,可能你需要重啟一下系統。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.