首頁 > 軟體

linux如何檢視殭屍程序

2023-03-23 22:07:26

linux檢視殭屍程序

1、檢視系統是否有殭屍程序

使用Top命令查詢,當zombie前的數量不為0時,即系統記憶體在相應數量的殭屍程序。


 

2、定位殭屍程序

使用命令ps -A -ostat,ppid,pid,cmd |grep -e '^[Zz]'定位殭屍程序以及該殭屍程序的父程序。

3、殺死殭屍程序

使用Kill -HUP 殭屍程序ID來殺死殭屍程序,往往此種情況無法殺死殭屍程序,此時就需要殺死殭屍程序的父程序。

kill -HUP 殭屍程序父ID

然後使用上面第二步的語句查詢該殭屍程序是否被殺死。

4、引數解讀

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

-A  引數列出所有程序

-o  自定義輸出欄位 stat(狀態)、ppid(程序父id)、pid(程序id)、cmd(命令)

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

linux殭屍程序及殭屍程序的處理

殭屍程序

(1)程序中的指令已經執行完成,但是程序PCB結構還沒有回收。

即子程序先於父程序退出後,子程序的PCB需要其父程序釋放,但是父程序並沒有釋放子程序的PCB,這樣的子程序就稱為殭屍程序。

(2)父程序未結束,子程序結束,但父程序沒有處理子程序的退出狀態(當子程序先於父程序結束,父程序沒有獲取子程序的退出碼,子程序的PCB會保留一段時間等待父程序在PCB中獲取退出碼,,且該程序不可執行,此時子程序變成殭屍程序)。

直到父程序獲取到子程序的退出狀態,子程序的PCB才會被移除。

我們的程式在退出的時候:return 0,exit(0),這個0就是退出碼(狀態資訊),它儲存在當前程序的PCB中,會有一個整型值來儲存退出碼。

當我們子程序結束以後,會把退出碼寫到PCB中,然後希望父程序可以獲得到這個退出碼,然後父程序就可以看到子程序是正常執行結束還是出錯退出。正常的話我們return 0,失敗的話我們return -1。

模擬殭屍程序:

僵死程序產生了,會有什麼影響?

  • 如果只有一兩個僵死程序,沒有什麼影響。
  • 如果有很多個僵死程序,持續不斷的產生,就有影響了,因為子程序的PCB如果沒有被釋放,程序的PID就被一直佔著,在核心空間中,PCB本身是結構體,會佔用記憶體空間,對系統軟硬體資源損耗,因此我們要避免僵死程序的產生,父程序有義務去處理!

何處理殭屍程序

父程序呼叫wait()方法獲取子程序的退出碼,從而使得OS刪除子程序的PCB;

父程序先結束(該子程序就失去了父程序,系統會將這種沒有子程序的父程序當做孤兒程序OS會給該孤兒程序重新尋找一個父程序Init程序,其PID == 1,通常會收養那些沒有父程序的子程序,就會直接獲取其退出碼從而消除該程序的僵死狀態 [ 其內部其實也是呼叫了wait()方法] )

如下圖所示,修改之前的程式碼,讓父程序先於子程序結束

執行結果如下:

我們可以看到失去父程序的子程序的PPID變為1,也就是Init程序

父程序處理子程序退出狀態(退出碼)的方法

pid_t wait(int *result)//獲取呼叫此方法的程序的子程序的退出碼
  • 如果沒有子程序,則呼叫失敗;
  • 如果有子程序並且已經結束,則返回子程序的PID,退出碼在result帶回。
  • 如果子程序沒有結束,那麼wait就會阻塞等待子程序結束。

我們來看一下wait的參考手冊:

我們需要傳入一個整形變數的地址,它會將退出碼寫到該地址中,返回值就是他獲取到退出碼的那個子程序的PID。

執行結果如下:這樣就相當於父子程序是序列執行的,因此我們不會很簡單粗暴地呼叫wait(),失去了多程序執行的意義,常會使用一些巧妙的方法,比如配合訊號使用,這個在後面的部落格中將會提到。

出現這種現象的原因是:父程序需要獲取子程序的退出碼,就需要等待子程序先結束,既然子程序沒有結束,就無法獲取子程序的退出碼,wait()方法就相當於阻塞了父程序的執行。

如果有多個子程序,一次wait呼叫只能處理一個子程序(最先結束的哪一個)。

如下程式碼也用wait處理了殭屍程序,但我們需要解決另外一個問題:

注意:此時我們exit(0)的退出碼是0

此時val的值為0

但是當我們將退出碼改為3時,執行結果發生了變化,我們可以看到val = 768

這是為什麼呢?

其實768對應的二進位制數為0011 0000 0000,(11就是那個3)

——左移了8位元,因為退出碼一般來說是128以內的值,但是一個整型有4位元組,1個位元組本來就夠儲存退出碼了,其他3個位元組有別的作用了,所以在這裡就發現被移位了,儲存在該儲存的位上。我們這怎麼處理?

操作位是不大方便的,但是系統給我們提供了一些方法

  • 第一個宏是用來判斷程式是否是正常exit退出
  • 如果是正常退出,就通過第二個宏得出退出碼,這個宏就知道我們的退出碼是在4個位元組中的哪個位元組存放的,精準取值,此時拿到的就是我們設定的3了,不是768了。

當程式還沒有執行到exit就被殺死,獲取到異常終止的訊號,我們就用下面這個宏來判斷

使用宏後,我們修改程式碼如下:

之後就可以看到正常的執行結果了

wait呼叫的最佳時機:子程序退出的那一時刻,父程序呼叫wait;

這裡引入一個概念,在下一期Linux專欄將會講到訊號

若在父程序一開始就呼叫,那麼就會出現序列執行的效果;

若在父程序快要結束的時候呼叫,那麼父程序已經退出,處理殭屍程序就沒有意義了。

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com