大話殭屍進程

前天跟一位“大神”級別的人物交流了一番,意識到什麼是真正的“高”手,廢話不多說,就其中的某一個問題且結合自己的經驗總結一番,希望能給到屏幕前的你一些啓示(以下是個人理解):

一體機進程有核間通信進程(DPAA)應用層業務,底軟側負責完成關於DPAA資源的初始化。實測過程中發現底軟關於DPAA管理沒處理好,導致一體機在測試反覆重啓的過程中出現殭屍進程,出現異常時會看到內核的打印調試信息。

爲什麼會產生殭屍進程呢?

底軟的DPAA等於是一體機DPAA的父進程,一體機DPAA進程退出時,底軟的DPAA需要用wait()或waitpid()系統調用取得子進程的終止狀態來回收資源,一體機的進程雖然已經退出了,但是在系統進程表中還爲它保留了一些退出狀態的信息,如果底軟DPAA進程一直不取得這些退出信息的話,這些進程表項就將一直被佔用,就會造成一體機的進程變成了殭屍進程。通過PS命令可以查看其帶有defunct的標誌,殭屍進程是一個早已死亡的進程,但在進程表中仍佔據一個位置。defunct進程是不能直接kill -9殺掉的,否則就不叫殭屍進程了。

但是如果該進程的父進程已經先結束了,那麼該進程就不會變成殭屍進程。因爲每個進程結束的時候,系統都會掃描當前系統中所運行的所有進程,看看有沒有哪個進程是剛剛結束的這個進程的子進程,如果是的話,就由init進程來接管他,成爲他的父進程,從而保證每個進程都會有一個父進程。而init進程會自動wait其子進程,因此被Init接管的所有進程都不會變成殭屍進程。

在Linux進程的狀態中,殭屍進程是非常特殊的一種,它已經放棄了幾乎所有的內存空間,沒有任何可執行代碼,也不能被調度,僅僅在進程列表中保留一個位置,記錄在進程的退出狀態等信息供其他進程收集,除此之外,殭屍進程不在佔有任何內存空間。它需要父進程來爲它收屍…如果父進程結束了,那麼init進程會自動接手這個子進程來爲它收屍,它還是能被清除的,但是如果父進程是一個循環不會結束,那麼子進程就會一直保持殭屍狀態,這就是爲什麼系統有時候會有很多的殭屍進程。

清除殭屍進程的方法:

把父進程殺掉,父進程死後,殭屍進程稱爲“孤兒進程”,過繼給1號進程init,init始終負責清理殭屍進程,它產生的所有殭屍進程跟着消失。一般都不能殺掉defunct進程,用了kill -15,kill -9以後反而會多出更多的殭屍進程。

以下是轉載,感謝原創作者,希望大家支持原創:

在UNIX系統中,一個進程結束了,但是其父進程沒有等待(調用wait/waitpid)它,那麼它將變成一個殭屍進程。通過PS命令可以查看其帶有defunct的標誌,殭屍進程是一個早已死亡的進程,但在進程表中仍佔據一個位置;

一個進程在調用exit命令結束自己的生命時候,其實它沒有真正的被銷燬,而是留下一個稱爲殭屍進程的數據結構(系統調用exit,它的作用是使進程退出,但也僅僅限於將一個正常的進程變成一個殭屍進程,並不能將其完全銷燬)。在Linux進程的狀態中,殭屍進程是非常特殊的一種,它已經放棄了幾乎所有的內存空間,沒有任何可執行代碼,也不能被調度,僅僅在進程列表中保留一個位置,記錄在進程的退出狀態等信息供其他進程收集,除此之外,殭屍進程不在佔有任何內存空間。

爲什麼windows不會有殭屍進程? 
創建進程的方式在Windows(CreateProcess)和Linux(Fork)下的差異還是有的,但是也不是完全不能統一,麻煩點的就是Windows沒有殭屍進程的概念導致進程ID不能真正區別出一個進程,比如說一個ID100的進程關閉了,然後一個新的進程啓動後ID爲100,並且父子進程之間的聯繫比Linux下要弱的多。 
進程之間相互獨立;要進行等待需要顯式寫代碼。

查看殭屍進程
top>> task (line)>> zombie..

清除殭屍進程
把父進程殺掉,父進程死後,殭屍進程稱爲“孤兒進程”,過繼給1號進程init,init始終負責清理殭屍進程,它產生的所有殭屍進程跟着消失;

kill
kill命令可以帶信號號碼選項,也可以不帶。如果沒有信號號碼,kill命令就會發出終止信號(15)

killall kill -15 kill -9 

一般都不能殺掉 defunct進程.. 用了kill -15,kill -9以後 之後反而會多出更多的殭屍進程

停止和重啓進程
有時候只想簡單的停止和重啓進程。如下: 

kill -HUP PID 

該命令讓Linux和緩的執行進程關閉,然後立即重啓。在配置應用程序的時候,這個命令很方便,在對配置文件修改後需要重啓進程時就可以執行此命令。

很多時候,會有人建議你,如果kill殺不掉一個進程,就用kill -9. 爲什麼? 
kill是Linux下常見的命令。其man手冊的功能定義如下:

kill – send a signal to a process

明朗了,其實kill就是給某個進程id發送了一個信號。默認發送的信號是SIGTERM,而kill -9發送的信號是SIGKILL,即exit。exit信號不會被系統阻塞,所以kill -9能順利殺掉進程。當然你也可以使用kill發送其他信號給進程。

Linux系統尋找和殺掉殭屍進程
Linux服務器上,多少會出現一些殭屍進程,下面介紹如何快速尋找和消滅這些殭屍進程的方法:

首先,可以使用top命令來查看服務器當前是否有殭屍進程,下圖中可以看到殭屍進程的提示,如果數字大於0,那麼意味着服務器當前存在殭屍進程:

下面,用ps 命令和 grep命令尋找殭屍進程:

ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'

命令註解: 
-A 參數列出所有進程 
-o 自定義輸出字段,我們設定顯示字段爲stat(狀態),ppid(父進程pid),pid(進程pid),cmd(命令行)這四個參數

因爲狀態爲 z 或者 Z的進程爲殭屍進程,所以我們使用grep 抓取stat 狀態爲zZ進程;

運行結果如下所示:

Z 12334 12339 /path/cmd

這時,我們可以使用kill -HUP 12339 來殺掉這個殭屍進程;

運行後,在此運行ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]' 來確認是否將殭屍進程殺死;

如果kill 子進程的無效,可以嘗試kill 其父進程來解決問題,例如上面父進程pid 爲12334,那麼我們就運行 kill -HUP 12334 來解決問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章