category :
工作學習
linux
2010.12.31
什麼是殭屍程序
殭屍程序是指它的父程序已經退出(父程序沒有等待(呼叫wait/waitpid)它),而該程序dead之後沒有程序接受,就成為殭屍程序,也就是(zombie)程序。
殭屍程序是怎麼樣產生
乙個程序在呼叫exit命令結束自己的生命的時候,其實它並沒有真正的被銷毀,而是留下乙個稱為殭屍程序(zombie)的資料結構(系統呼叫exit,它的作用是使程序退出,但也僅僅限於將乙個正常的程序變成乙個殭屍程序,並不能將其完全銷毀)。
在linux程序的狀態中,殭屍程序是非常特殊的一種,它已經放棄了幾乎所有記憶體空間,沒有任何可執行**,也不能被排程,僅僅在程序列表中保留乙個位置,記載該程序的退出狀態等資訊供其他程序收集,除此之外,殭屍程序不再占有任何記憶體空間。它需要它的父程序來為它收屍。
如果他的父程序沒安裝sigchld訊號處理函式呼叫wait或waitpid()等待子程序結束,又沒有顯式忽略該訊號,那麼它就一直保持殭屍狀態,如果這時父程序結束了,那麼init程序自動會接手這個子程序,為它收屍,它還是能被清除的。
但是如果父程序是乙個迴圈,不會結束,那麼子程序就會一直保持殭屍狀態,這就是為什麼系統中有時會有很多的殭屍程序。系統所能使用的程序號是有限的,如果大量的產生僵死程序,將因為沒有可用的程序號而導致系統不能產生新的程序.
殭屍程序的避免
1、父程序通過wait和waitpid等函式等待子程序結束,這會導致父程序掛起
2、如果父程序很忙,那麼可以用signal函式為sigchld安裝handler,因為子程序結束後,父程序會收到該訊號,可以在handler中呼叫wait**
3、如果父程序不關心子程序什麼時候結束,那麼可以用signal(sigchld, sig_ign) 通知核心,自己對子程序的結束不感興趣,那麼子程序結束後,核心會**,並不再給父程序傳送訊號
4、還有一些技巧,就是fork兩次,父程序fork乙個子程序,然後繼續工作,子程序fork乙個孫程序後退出,那麼孫程序被init接管,孫程序結束後,init會**。不過子程序的**還要自己做。
子程序結束後為什麼要進入殭屍狀態?
因為父程序可能要取得子程序的退出狀態等資訊。
殭屍狀態是每個子程序比經過的狀態嗎?
任何乙個子程序(init除外)在exit()之後,並非馬上就消失掉,而是留下乙個稱為殭屍程序(zombie)的資料結構(它占用一點記憶體資源,也就是程序表裡還有乙個記錄),等待父程序處理。這是每個子程序在結束時都要經過的階段。如果子程序在exit()之後,父程序沒有來得及處理,這時用ps命令就能看到子程序的狀態是「z」。
如果父程序能及時處理,可能用ps命令就來不及看到子程序的殭屍狀態,但這並不等於子程序不經過殭屍狀態。
如果父程序在子程序結束之前退出,則子程序將由init接管。init將會以父程序的身份對殭屍狀態的子程序進行處理。
如何檢視殭屍程序
在linux中,利用命令ps,可以看到有標記為z的程序就是殭屍程序。
ps -ef|grep defunc可以找出殭屍程序.
可以用ps的-l選項,得到更詳細的程序資訊. f(flag):一系列數字的和,表示程序的當前狀態。這些數字的含義為:
00:若單獨顯示,表示此程序已被終止。
01:程序是核心程序的一部分,常駐於系統主存。如:sched、 vhand 、bdflush 等。
02:parent is tracing process.
04:tracing parent』s signal has stopped the process; the parent is waiting ( ptrace(s)).
10:程序在優先順序低於或等於25時,進入休眠狀態,而且不能用訊號喚醒,例如在等待乙個inode被建立時
20:程序被裝入主存(primary memory)
40:程序被鎖在主存,在事務完成前不能被置換
s(state of the process )
o:程序正在處理器執行
s:休眠狀態(sleeping)
r:等待執行(runable)
i:空閒狀態(idle)
z:殭屍狀態(zombie)
t:跟蹤狀態(traced)
b:程序正在等待更多的記憶體頁
c:cpu利用率的估算值(cpu usage)
殭屍程序清除的方法
1.改寫父程序,在子程序死後要為它收屍。具體做法是接管sigchld訊號。子程序死後,會傳送sigchld訊號給父程序,父程序收到此訊號後,執行waitpid()函式為子程序收屍。這是基於這樣的原理:就算父程序沒有呼叫wait,核心也會向它傳送sigchld訊息,儘管對的預設處理是忽略,如果想響應這個訊息,可以設定乙個處理函式。
sigchld訊號:子程序結束時, 父程序會收到這個訊號。如果父程序沒有處理這個訊號,也沒有等待(wait)子程序,子程序雖然終止,但是還會在核心程序表中占有表項,這時的子程序稱為殭屍程序。這種情況我們應該避免(父程序或者忽略sigchild訊號,或者捕捉它,或者wait它派生的子程序,或者父程序先終止,這時子程序的終止自動由init程序來接管)。
2. kill -18 ppid (ppid是其父程序)
這個訊號是告訴父程序,該子程序已經死亡了,請收回分配給他的資源。
sigcont也是乙個有意思的訊號。如前所述,當程序停止的時候,這個訊號用來告訴程序恢復執行。該訊號的有趣的地方在於:它不能被忽略或阻塞,但可以**獲。預設行為是丟棄該訊號。
3.終止父程序
如果方法2不能終止,可採用終止其父程序的方法(如果其父程序不需要的話)父程序死後,殭屍程序成為」孤兒程序」,過繼給1號程序init,init始終會負責清理殭屍程序.它產生的所有殭屍程序也跟著消失。
先看其父程序又無其他子程序,如果有,可能需要先kill其他子程序,也就是兄弟程序。方法是:
kill –15 pid1 pid2 (pid1,pid2是殭屍程序的父程序的其它子程序)。
然後再kill父程序:kill –15 ppid
這樣殭屍程序就可能被完全殺掉了。
linux下殭屍程序的發現與處理
當子程序退出時,父程序沒有呼叫wait函式或者waitpid 函式等待子程序結束,又沒有顯式忽略sigchld訊號,那麼它將一直保持在殭屍狀態,如果這時父程序結束了,init程序會自動接收這個子程序,為它收屍,但如果父程序是乙個迴圈,不會結束,那麼子程序就會一直保持僵死狀態。程序狀態 ps a o ...
linux下殭屍程序的發現與處理
當子程序退出時,父程序沒有呼叫wait函式或者waitpid 函式等待子程序結束,又沒有顯式忽略sigchld訊號,那麼它將一直保持在殭屍狀態,如果這時父程序結束了,init程序會自動接收這個子程序,為它收屍,但如果父程序是乙個迴圈,不會結束,那麼子程序就會一直保持僵死狀態。程序狀態 ps a o ...
Linux的殭屍程序處理1
linux中有兩種異常的程序 1.孤兒程序 應用通過fork程序後,父程序被kill或者exit,該父程序的子程序被1號程序接管。linux核心啟動時候回啟動0號程序,啟動完畢後0號程序就處於空閒狀態,所有的程序的父程序都是有1號程序fork出來的。2.殭屍程序 fork操作出來的父子程序,子程序收...