導航:首頁 > 解決方法 > 網路編程解決僵屍進程四種方法

網路編程解決僵屍進程四種方法

發布時間:2022-12-08 06:08:16

『壹』 ubuntu Linux怎麼解決僵屍進程

Linux 允許進程查詢內核以獲得其父進程的 PID,或者其任何子進程的執行狀態。例如,進程可以創建一個子進程來執行特定的任務,然後調用諸如 wait() 這樣的一些庫函數檢查子進程是否終止。如果子進程已經終止,那麼,它的終止代號將告訴父進程這個任務是否已成功地完成。

為了遵循這些設計原則,不允許 Linux 內核在進程一終止後就丟棄包含在進程描述符欄位中的數據。只有父進程發出了與被終止的進程相關的 wait() 類系統調用之後,才允許這樣做。這就是引入僵死狀態的原因:盡管從技術上來說進程已死,但必須保存它的描述符,直到父進程得到通知。

如果一個進程已經終止,但是它的父進程尚未調用 wait() 或 waitpid() 對它進行清理,這時的進程狀態稱為僵死狀態,處於僵死狀態的進程稱為僵屍進程(zombie process)。任何進程在剛終止時都是僵屍進程,正常情況下,僵屍進程都立刻被父進程清理了。

僵屍進程是如何產生的

在UNIX 系統中,一個進程結束了,但是他的父進程沒有等待(調用wait / waitpid)他,那麼他將變成一個僵屍進程。通過ps命令查看其帶有defunct的標志。僵屍進程是一個早已死亡的進程,但在進程表 (processs table)中仍佔了一個位置(slot)。

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

為了觀察到僵屍進程,我們自己寫一個不正常的程序,父進程 fork 出子進程,子進程終止,而父進程既不終止也不調用 wait 清理子進程:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

intmain(void)

{

inti = 100;

pid_t pid=fork();

if(pid < 0)

{

perror("fork failed.");

exit(1);

}

if(pid > 0)

{

printf("This is the parent process. My PID is %d. ", getpid());

for(; i > 0; i--)

{

sleep(1);

}

}

elseif(pid == 0)

{

printf("This is the child process. My PID is: %d. My PPID is: %d. ", getpid(), getppid());

}

return0;

}

把上面的代碼保存到文件 zomprocdemo.c 文件中,並執行下面的命令編譯:

?

1

$ gcc zomprocdemo.c -o zomprocdemo

然後運行編譯出來的 zomprocdemo 程序:

?

1

$ ./zomprocdemo

上圖紅框中的大寫字母 "Z" 說明 PID 為 112712 的進程此時處於僵死的狀態。

讓我們接著往下看!在結束 sleep 後父進程退出。當父進程退出後,子進程會變成孤兒進程,此時它會被一個管理進程收養。在不同的系統中,這個管理進程不太一樣,早期一般是 init 進程,Ubuntu 上是 upstart,還有近來的 Systemd。但是它們都完成相同的任務,就是 wiat() 這些孤兒進程,並最終釋放它們佔用的系統進程表中的資源。這樣,這些已經僵死的孤兒進程就徹底的被清除了。

僵屍進程的危害

在進程退出的時候,內核釋放該進程所有的資源,包括打開的文件,佔用的內存等。但是仍然為其保留一定的信息(包括進程號 PID,退出狀態 the termination status of the process,運行時間 the amount of CPU time taken by the process 等)。直到父進程通過 wait / waitpid 來取時才釋放。

如果進程不調用 wait / waitpid 的話, 那麼保留的那段信息就不會釋放,其進程號就會一直被佔用,但是系統所能使用的進程號是有限的,如果大量的產生僵死進程,將因為沒有可用的進程號而導致系統不能產生新的進程。

如何處理僵屍進程

僵屍進程的產生是因為父進程沒有 wait() 子進程。所以如果我們自己寫程序的話一定要在父進程中通過 wait() 來避免僵屍進程的產生。

當系統中出現了僵屍進程時,我們是無法通過 kill 命令把它清除掉的。但是我們可以殺死它的父進程,讓它變成孤兒進程,並進一步被系統中管理孤兒進程的進程收養並清理。

下面的 demo 中,父進程通過 wait() 等待子進程結束:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

intmain(void)

{

pid_t pid;

pid = fork();

if(pid < 0)

{

perror("fork failed");

exit(1);

}

if(pid == 0) {

inti;

for(i = 3; i > 0; i--)

{

printf("This is the child ");

sleep(1);

}

// exit with code 3 for test.

exit(3);

}

else

{

intstat_val;

wait(&stat_val);

if(WIFEXITED(stat_val))

{

printf("Child exited with code %d ", WEXITSTATUS(stat_val));

}

}

return0;

}

demo 中父進程不僅等待子進程結束,還通過 WEXITSTATUS 宏取到了子進程的 exit code。

『貳』 【zombie】如何查看並殺死僵屍進程

In UNIX System terminology, a process that has terminated,but whose parent has not yet waited for it is called a zombie.

在UNIX 系統中,一個進程結束了,但是他的父進程沒有等待(調用wait / waitpid), 那麼它將變成一個僵屍進程.  在fork()/execve()過程中,假設子進程結束時父進程仍存在,而父進程fork()之前既沒安裝SIGCHLD信號處理函數調用 waitpid()等待子進程結束,又沒有顯式忽略該信號,則子進程成為僵屍進程。

我們可以用top命令來查看伺服器當前是否有僵屍進程,在下圖中可以看到僵屍進程數的提示,如果數字大於0,那麼意味著伺服器當前存在有僵屍進程:

#ps -ef | grep defunct

#ps -ef | grep defunct | grep -v grep | wc -l

# ps -ef | grep defunct | grep -v grep | awk '{print "kill -18 " $3}'

一般僵屍進程很難直接kill掉,不過您可以kill僵屍爸爸。父進程死後,僵屍進程成為」孤兒進程」,過繼給1號進程init,init始終會負責清理僵屍進程.它產生的所有僵屍進程也跟著消失。

子進程死後,會發送SIGCHLD信號給父進程,父進程收到此信號後,執行waitpid()函數為子進程收屍。就是基於這樣的原理:就算父進程沒有調用wait,內核也會向它發送SIGCHLD消息,而此時,盡管對它的默認處理是忽略,如果想響應這個消息,可以設置一個處理函數。

我們用ps和grep命令尋找僵屍進程:

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

命令註解:

-A 參數列出所有進程

-o 自定義輸出欄位 我們設定顯示欄位為 stat(狀態), ppid(進程父id), pid(進程id),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

一條簡單的命令,直接查找僵死進程,然後將父進程殺死

#  ps -A -o stat,ppid,pid,cmd | grep -e '^[Zz]' | awk '{print $2}' | xargs kill -9

# ps -e -o ppid,stat | grep Z | cut -d」 」 -f2 | xargs kill -9

# kill -HUP  $(ps -A -ostat,ppid | grep -e 』^[Zz]『 | awk 』{print $2}』)

處理SIGCHLD信號並不是必須的,但對於某些進程,特別是伺服器進程往往在請求到來時生成子進程處理請求。

如果父進程不等待子進程結束,子進程將成為僵屍進程(zombie)從而佔用系統資源。如果父進程等待子進程結束,將增加父進程的負擔,影響伺服器進程的並發性能。

在Linux下 可以簡單地將 SIGCHLD信號的操作設為SIG_IGN。

這樣,內核在子進程結束時不會產生僵屍進程。這一點與BSD4不同,BSD4下必須顯式等待子進程結束才能釋放僵屍進程。

或者用兩次fork(),而且使緊跟的子進程直接退出,是的孫子進程成為孤兒進程,從而init進程將負責清除這個孤兒進程!

『叄』 ubuntu Linux怎麼解決僵屍進程

『肆』 linux怎麼處理僵屍進程

一般僵屍進程很難直接kill掉,不過您可以kill僵屍爸爸。父進程死後,僵屍進程成為」孤兒進程」,過繼給1號進程init,init始終會負責清理僵屍進程.它產生的所有僵屍進程也跟著消失。
ps -e -o ppid,stat | grep Z | cut -d」 」 -f2 | xargs kill -9

kill -HUP `ps -A -ostat,ppid | grep -e 』^[Zz]『 | awk 』{print $2}』`
當然您可以自己編寫更好的shell腳本,歡迎與大家分享。
我將nova-novncproxy stop後再start,僵屍進程即消失,問題解決。
另外子進程死後,會發送SIGCHLD信號給父進程,父進程收到此信號後,執行waitpid()函數為子進程收屍。就是基於這樣的原理:就算父進程沒有調用wait,內核也會向它發送SIGCHLD消息,而此時,盡管對它的默認處理是忽略,如果想響應這個消息,可以設置一個處理函數。

『伍』 ubuntu Linux怎麼解決僵屍進程

如何查看linux系統上的僵屍進程,如何統計有多少僵屍進程?

#ps -ef | grep defunct

或者查找狀態為Z的進程,Z就是代表zombie process,僵屍進程的意思。

另外使用top命令查看時有一欄為S,如果狀態為Z說明它就是僵屍進程。

Tasks: 95 total, 1 running, 94 sleeping, 0 stopped, 0 zombie

top命令中也統計了僵屍進程。或者使用下面的命令:

ps -ef | grep defunct | grep -v grep | wc -l

如何殺死僵屍進程呢?
一般僵屍進程很難直接kill掉,不過您可以kill僵屍爸爸。父進程死後,僵屍進程成為」孤兒進程」,過繼給1號進程init,init始終會負責清理僵屍進程.它產生的所有僵屍進程也跟著消失。

ps -e -o ppid,stat | grep Z | cut -d」 」 -f2 | xargs kill -9



kill -HUP `ps -A -ostat,ppid | grep -e 』^[Zz]『 | awk 』{print $2}』`

當然您可以自己編寫更好的shell腳本,

閱讀全文

與網路編程解決僵屍進程四種方法相關的資料

熱點內容
OT的評定方法有哪些 瀏覽:162
寶寶睡覺咳嗽打噴嚏有什麼方法 瀏覽:621
魅藍手機如何錄音許可權設置在哪裡設置方法 瀏覽:665
下拉式紗窗使用方法 瀏覽:642
簡單疊蛋糕的方法 瀏覽:496
午夜釣魚最佳方法 瀏覽:321
鍋爐水溫測量方法 瀏覽:927
零之終使用方法視頻 瀏覽:574
煲出一副好耳機的正確方法和步驟 瀏覽:735
手腳破皮有什麼土方法止疼 瀏覽:318
物理都有什麼探究方法 瀏覽:578
剛摘的柿子用什麼方法才能快速吃 瀏覽:995
斷電器與保護器連接方法 瀏覽:361
如何給下水道疏通方法 瀏覽:274
秒潮使用方法 瀏覽:582
室內減肥器材最佳方法 瀏覽:193
如何變不內向的方法 瀏覽:837
髖關節痛有哪些治療方法 瀏覽:636
常用的葯敏試驗方法有哪些 瀏覽:663
美術課堂組織方法研究前期調查表 瀏覽:512