Linux 殭屍程序

2021-06-05 02:50:51 字數 3718 閱讀 3095

怎樣產生殭屍程序的:

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

在linux程序的狀態中,殭屍程序是非常特殊的一種,它已經放棄了幾乎所有記憶體空間,沒有任何可執行**,也不能被排程,僅僅在程序列表中保留乙個位置,記載該程序的退出狀態等資訊供其他程序收集,除此之外,殭屍程序不再占有任何記憶體空間。它需要它的父程序來為它收屍,如果他的父程序沒安裝 sigchld訊號處理函式呼叫wait或waitpid()等待子程序結束,又沒有顯式忽略該訊號,那麼它就一直保持殭屍狀態,如果這時父程序結束了,那麼init程序自動會接手這個子程序,為它收屍,它還是能被清除的。但是如果如果父程序是乙個迴圈,不會結束,那麼子程序就會一直保持殭屍狀態,這就是為什麼系統中有時會有很多的殭屍程序。

怎麼檢視殭屍程序:

利用命令ps,可以看到有標記為z的程序就是殭屍程序。

怎樣來清除殭屍程序:

1.改寫父程序,在子程序死後要為它收屍。具體做法是接管sigchld訊號。子程序死後,會傳送sigchld訊號給父程序,父程序收到此訊號後,執行waitpid()函式為子程序收屍。這是基於這樣的原理:就算父程序沒有呼叫wait,核心也會向它傳送sigchld訊息,儘管對的預設處理是忽略,如果想響應這個訊息,可以設定乙個處理函式。

2.把父程序殺掉。父程序死後,殭屍程序成為"孤兒程序",過繼給1號程序init,init始終會負責清理殭屍程序.它產生的所有殭屍程序也跟著消失。

===================================

在fork ()/execve()過程中,假設子程序結束時父程序仍存在,而父程序fork()之前既沒安裝sigchld訊號處理函式呼叫waitpid()等待子程序結束,又沒有顯式忽略該訊號,則子程序成為殭屍程序,無法正常結束,此時即使是root身份kill -9也不能殺死殭屍程序。補救辦法是殺死殭屍程序的父程序(殭屍程序的父程序必然存在),殭屍程序成為"孤兒程序",過繼給1號程序init,init始終會負責清理殭屍程序。  

****************************************===

在linux中可以用

ps auwx  

發現殭屍程序

a all w/ tty, including other users 所有視窗和終端,包括其他使用者的程序

u user-oriented 面向使用者(使用者友好)

-w,w wide output 寬格式輸出

x processes w/o controlling ttys  

在殭屍程序後面 會標註

ps axf  

看程序樹,以樹形方式現實程序列表

ps axm  

會把執行緒列出來,在linux下程序和執行緒是統一的,是輕量級程序的兩種方式。

ps axu  

顯示程序的詳細狀態

****************************************===

killall

kill -15

kill -9

一般都不能殺掉 defunct程序

用了kill -15,kill -9以後 之後反而會多出更多的殭屍程序

kill -kill pid

fuser -k pid  

可以考慮殺死他的parent process,

kill -9 他的parent process

****************************************===

乙個已經終止,但是其父程序尚未對其進行善後處理(獲取終止子程序的有關資訊、釋放它仍占用的資源)的程序被稱為僵死程序(zombie process)。

避免zombie的方法:

1)在svr4中,如果呼叫signal或sigset將sigchld的配置設定為忽略,則不會產生僵死子程序。另外,使用svr4版的sigaction,則可設定sa_nocldwait標誌以避免子程序僵死。

linux中也可使用這個,在乙個程式的開始呼叫這個函式

signal(sigchld,sig_ign);  

2)呼叫fork兩次。程式8 - 5 實現了這一點。

3)用waitpid等待子程序返回.  

****************************************===

zombie程序是僵死程序。防止它的辦法,一是用wait,waitpid之類的函式獲得

程序的終止狀態,以釋放資源。另乙個是fork兩次  

****************************************===

defunct程序只是在process table裡還有乙個記錄,其他的資源沒有占用,除非你的系統的process個數的限制已經快超過了,zombie程序不會有更多的壞處。

可能唯一的方法就是reboot系統可以消除zombie程序。

****************************************===

任何程式都有殭屍狀態,它占用一點記憶體資源(也就是程序表裡還有乙個記錄),僅僅是表象而已不必害怕。如果程式有問題有機會遇見,解決大批量殭屍簡單有效的辦法是重起。kill是無任何效果的

fork與zombie/defunct"

在unix 下的一些程序的運作方式。當乙個程序死亡時,它並不是完全的消失了。程序終止,它不再執行,但是還有一些殘留的小東西等待父程序收回。這些殘留的東西包括子程序的返回值和其他的一些東西。當父程序 fork() 乙個子程序後,它必須用 wait() 或者 waitpid() 等待子程序退出。正是這個 wait() 動作來讓子程序的殘留物消失。

自然的,在上述規則之外有個例外:父程序可以忽略 sigcld 軟中斷而不必要 wait()。可以這樣做到(在支援它的系統上,比如linux):

main()

{signal(sigcld, sig_ign);..

fork();

fork();

fork();

}現在,子程序死亡時父程序沒有 wait(),通常用 ps 可以看到它被顯示為「」。它將永遠保持這樣 直到 父程序 wait(),或者按以下方法處理。

這 裡是你必須知道的另乙個規則:當父程序在它wait()子程序之前死亡了(假定它沒有忽略 sigcld),子程序將把 init(pid 1)程序作為它的父程序。如果子程序工作得很好並能夠控制,這並不是問題。但如果子程序已經是 defunct,我們就有了一點小麻煩。看,原先的父程序不可能再 wait(),因為它已經消亡了。這樣,init 怎麼知道 wait() 這些 zombie 程序。

答案:不可預料的。在一些系統上,init週期性的破壞掉它所有的defunct程序。在另外一些系統中,它乾脆拒絕成為任何defunct程序的父程序,而是馬上毀滅它們。如果你使用上述系統的一種,可以寫乙個簡單的迴圈,用屬於init的defunct程序填滿程序表。這大概不會令你的系統管理員很高興吧?

你的任務:確定你的父程序不要忽略 sigcld,也不要 wait() 它 fork() 的所有程序。不過,你也未必 要總是這樣做(比如,你要起乙個 daemon 或是別的什麼東西),但是你必須小心程式設計,如果你是乙個 fork() 的新手。另外,也不要在心理上有任何束縛。

總結:子程序成為 defunct 直到父程序 wait(),除非父程序忽略了 sigcld 。

更進一步,父程序沒有 wait() 就消亡(仍假設父程序沒有忽略 sigcld )的子程序(活動的或者 defunct)成為 init 的子程序,init 用重手法處理它們。

引自:

linux殭屍程序

僵死程序 在unix程序模型中,程序是按照父程序產生子程序,子程序產生子子程序這樣的方式建立出完成各項相互協作功能的程序的。當乙個程序完成它的工作終止之後,它的父程序需要呼叫wait 或者waitpid 系統呼叫取得子程序的終止狀態。如果父程序沒有這麼做的話,子程序雖然已經退出了,但是在系統程序表中...

linux殭屍程序

殭屍程序是指子程序退出時,父程序並未對其發出的sigchild訊號進行適當處理,導致子程序停留在殭屍狀態等待其父程序為其收屍,這個狀態下的子程序就是殭屍程序。include include include int main int argc,char argv return 0 從上面的執行結果可以...

linux 殭屍程序

關於zombie程序 這些程序已經死亡,但沒有釋放系統資源,包括記憶體和一些一些系統表等,如果這樣的程序很多,會引發系統問題。用ps el看出的程序狀態如果是z,就是殭屍程序。ps ef grep defunc可以找出殭屍程序.有些zombie程序時用kill 9也不能殺死,而且消耗了很多系統資源不...