目錄
一、什麼是殭屍行程
二、UNIX下進程的運作方式
三、殭屍行程的危害
四、殭屍進程的產生
五、如何避免僵尸进程
首頁 運維 linux運維 linux 殭屍行程是什麼

linux 殭屍行程是什麼

Apr 06, 2023 am 11:37 AM
linux 殭屍行程

linux殭屍進程是一個早已死亡的進程,但是在進程表中仍佔了一個位置;如果子進程死亡時父進程沒有wait(),通常用ps可以看到它被顯示為“ ”,這樣就產生了殭屍進程;如果大量產生殭屍進程,那麼將因為沒有可用的進程號而導致系統不能產生新的進程,所以要避免有殭屍進程。

linux 殭屍行程是什麼

本教學操作環境:linux5.9.8系統、Dell G3電腦。

linux下殭屍行程(Defunct行程)的產生與避免

一、什麼是殭屍行程

在UNIX 系統中,一個行程結束了,但是他的父行程沒有等待(呼叫wait / waitpid)他,那麼他將變成一個殭屍行程。當用ps指令觀察進程的執行狀態時,看到這些行程的狀態列為defunct。殭屍行程是一個早已死亡的過程,但在行程表(processs table)中仍佔了一個位置(slot)。

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

二、UNIX下進程的運作方式

每個Unix進程在進程表裡都有一個進入點(entry),核心進程執行該進程時使用到的一切資訊都儲存在進入點。當用 ps 指令察看系統中的進程資訊時,看到的就是進程表中的相關資料。當以fork()系統呼叫建立一個新的進程後,核心進程就會在進程表中給這個新進程分配一個進入點,然後將相關資訊儲存在該進入點所對應的進程表內。這些資訊中有一項是其父進程的識別碼。

子程序的結束和父進程的運行是一個非同步過程,即父進程永遠無法預測子進程到底什麼時候結束。那麼會不會因為父進程太忙來不及 wait 子進程,或是說不知道子進程什麼時候結束,而丟失子進程結束時的狀態資訊呢?

不會。因為UNIX提供了一個機制可以保證,只要父行程想知道子行程結束時的狀態訊息,就可以得到。這個機制就是:當子行程走完了自己的生命週期後,它會執行exit()系統調用,內核釋放該行程所有的資源,包括開啟的文件,佔用的記憶體等。但仍為其保留一定的資訊(包括進程號the process ID,退出碼exit code,退出狀態the terminationstatus of the process,運行時間the amount of CPU time taken by the process等),這些資料會保留到系統將它傳遞給它的父進程為止,直到父進程透過wait / waitpid來取時才釋放。

也就是說,當一個過程死亡時,它並不是完全的消失了。進程終止,它不再運行,但是還有一些殘留的資料等待父進程收回。當父行程 fork() 一個子程序後,它必須用 wait() (或 waitpid())等待子程序退出。正是這個 wait() 動作來讓子程序的殘留資料消失。

三、殭屍行程的危害

如果父行程不呼叫wait / waitpid的話,那麼保留的那段資訊就不會釋放,其行程號碼就會一直被佔用,但是系統的進程表容量是有限的,所能使用的進程號也是有限的,如果大量的產生殭屍進程,將因為沒有可用的進程號而導致系統不能產生新的進程。

所以,defunct進程不僅佔用系統的記憶體資源,影響系統的效能,而且如果其數目太多,還會導致系統癱瘓。而且,由於調度程式無法選取Defunct 進程,所以不能用kill指令刪除Defunct 進程,惟一的方法只有重啟系統。

四、殭屍進程的產生

如果子進程死亡時父進程沒有wait(),通常用ps 可以看到它被顯示為“”,這樣就產生了殭屍行程。它將永遠保持這樣直到父進程 wait()。

由此可見,defunct進程的出現時間是在子程序終止後,但是父進程尚未讀取這些資料之前。利用這一點我們可以用下面的程式建立一個defunct 進程:

#include <stdio.h> 
 
#include<sys/types.h> 
 
main()  
{  
 
 if(!fork())  
    {  
 
        printf(“child pid=%d\n”, getpid());  
 
        exit(0);  
 
    }  
 
    sleep(20);  
 
    printf(“parent pid=%d \n”, getpid());  
 
    exit(0);  
 
}
登入後複製

当上述程序以后台的方式执行时,第17行强迫程序睡眠20秒,让用户有时间输入ps -e指令,观察进程的状态,我们看到进程表中出现了defunct进程。当父进程执行终止后,再用ps -e命令观察时,我们会发现defunct进程也随之消失。这是因为父进程终止后,init 进程会接管父进程留下的这些“孤儿进程”(orphan process),而这些“孤儿进程”执行完后,它在进程表中的进入点将被删除。如果一个程序设计上有缺陷,就可能导致某个进程的父进程一直处于睡眠状态或是陷入死循环,父进程没有wait子进程,也没有终止以使Init接管,该子进程执行结束后就变成了defunct进程,这个defunct 进程可能会一直留在系统中直到系统重新启动。

在看一个产生僵尸进程的例子。

子进程要执行的程序test_prog

//test.c 
#include <stdio.h> int main()  {  
 int i = 0;  
 for (i = 0 ; i < 10; i++)  
        {  
                printf ("child time %d\n", i+1);  
                sleep (1);  
        }  
 return 0;  }
登入後複製

父进程father的代码father.c

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
int main()  
{  
 int pid = fork ();  
 if (pid == 0)  
        {  
                system ("./test_prog");  
                _exit (0);  
        }else 
        {  
 int i = 0;  
 /* 
                                int status = 0; 
                while (!waitpid(pid, &status, WNOHANG)) 
                { 
                        printf ("father waiting%d\n", ++i); 
                        sleep (1); 
                }*/ 
 while (1)  
                {  
                        printf ("father waiting over%d\n", ++i);  
                        sleep (1);  
                }  
 return 0;  
        }  
 
}
登入後複製

执行./father,当子进程退出后,由于父进程没有对它的退出进行关注,会出现僵尸进程

20786 pts/0    00:00:00 father  
20787 pts/0    00:00:00 father <defunct>
登入後複製

总结:子进程成为 defunct 直到父进程 wait(),除非父进程忽略了 SIGCLD 。更进一步,父进程没有 wait() 就消亡(仍假设父进程没有忽略 SIGCLD )的子进程(活动的或者 defunct)成为 init 的子进程,init 着手处理它们。

五、如何避免僵尸进程

1、父进程通过wait和waitpid等函数等待子进程结束,这会导致父进程挂起。

在上个例子中,如果我们略作修改,在第8行sleep()系统调用前执行wait()或waitpid()系统调用,则子进程在终止后会立即把它在进程表中的数据返回给父进程,此时系统会立即删除该进入点。在这种情形下就不会产生defunct进程。

2. 如果父进程很忙,那么可以用signal函数为SIGCHLD安装handler。在子进程结束后,父进程会收到该信号,可以在handler中调用wait回收。

3. 如果父进程不关心子进程什么时候结束,那么可以用signal(SIGCLD, SIG_IGN)或signal(SIGCHLD, SIG_IGN)通知内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收,并不再给父进程发送信号

4. fork两次,父进程fork一个子进程,然后继续工作,子进程fork一个孙进程后退出,那么孙进程被init接管,孙进程结束后,init会回收。不过子进程的回收还要自己做。 下面就是Stevens给的采用两次folk避免僵尸进程的示例:

#include "apue.h" #include <sys/wait.h>  int main(void)  ...{  
     pid_t    pid;  
 
 if ((pid = fork()) < 0) ...{  
         err_sys("fork error");  
     } else if (pid == 0) ...{     /**//* first child */ 
 if ((pid = fork()) < 0)  
             err_sys("fork error");  
 else if (pid > 0)  
             exit(0);    /**//* parent from second fork == first child */ 
 /**//* 
          * We&#39;re the second child; our parent becomes init as soon 
          * as our real parent calls exit() in the statement above. 
          * Here&#39;s where we&#39;d continue executing, knowing that when 
          * we&#39;re done, init will reap our status. 
         */ 
         sleep(2);  
         printf("second child, parent pid = %d ", getppid());  
         exit(0);  
     }  
 
 if (waitpid(pid, NULL, 0) != pid)  /**//* wait for first child */ 
         err_sys("waitpid error");  
 
 /**//* 
      * We&#39;re the parent (the original process); we continue executing, 
      * knowing that we&#39;re not the parent of the second child. 
     */ 
     exit(0);  }
登入後複製

相关推荐:《Linux视频教程

以上是linux 殭屍行程是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

vscode需要什麼電腦配置 vscode需要什麼電腦配置 Apr 15, 2025 pm 09:48 PM

VS Code 系統要求:操作系統:Windows 10 及以上、macOS 10.12 及以上、Linux 發行版處理器:最低 1.6 GHz,推薦 2.0 GHz 及以上內存:最低 512 MB,推薦 4 GB 及以上存儲空間:最低 250 MB,推薦 1 GB 及以上其他要求:穩定網絡連接,Xorg/Wayland(Linux)

Linux體系結構:揭示5個基本組件 Linux體系結構:揭示5個基本組件 Apr 20, 2025 am 12:04 AM

Linux系統的五個基本組件是:1.內核,2.系統庫,3.系統實用程序,4.圖形用戶界面,5.應用程序。內核管理硬件資源,系統庫提供預編譯函數,系統實用程序用於系統管理,GUI提供可視化交互,應用程序利用這些組件實現功能。

notepad怎麼運行java代碼 notepad怎麼運行java代碼 Apr 16, 2025 pm 07:39 PM

雖然 Notepad 無法直接運行 Java 代碼,但可以通過借助其他工具實現:使用命令行編譯器 (javac) 編譯代碼,生成字節碼文件 (filename.class)。使用 Java 解釋器 (java) 解釋字節碼,執行代碼並輸出結果。

vscode終端使用教程 vscode終端使用教程 Apr 15, 2025 pm 10:09 PM

vscode 內置終端是一個開發工具,允許在編輯器內運行命令和腳本,以簡化開發流程。如何使用 vscode 終端:通過快捷鍵 (Ctrl/Cmd ) 打開終端。輸入命令或運行腳本。使用熱鍵 (如 Ctrl L 清除終端)。更改工作目錄 (如 cd 命令)。高級功能包括調試模式、代碼片段自動補全和交互式命令歷史。

git怎麼查看倉庫地址 git怎麼查看倉庫地址 Apr 17, 2025 pm 01:54 PM

要查看 Git 倉庫地址,請執行以下步驟:1. 打開命令行並導航到倉庫目錄;2. 運行 "git remote -v" 命令;3. 查看輸出中的倉庫名稱及其相應的地址。

vscode 無法安裝擴展 vscode 無法安裝擴展 Apr 15, 2025 pm 07:18 PM

VS Code擴展安裝失敗的原因可能包括:網絡不穩定、權限不足、系統兼容性問題、VS Code版本過舊、殺毒軟件或防火牆干擾。通過檢查網絡連接、權限、日誌文件、更新VS Code、禁用安全軟件以及重啟VS Code或計算機,可以逐步排查和解決問題。

vscode在哪寫代碼 vscode在哪寫代碼 Apr 15, 2025 pm 09:54 PM

在 Visual Studio Code(VSCode)中編寫代碼簡單易行,只需安裝 VSCode、創建項目、選擇語言、創建文件、編寫代碼、保存並運行即可。 VSCode 的優點包括跨平台、免費開源、強大功能、擴展豐富,以及輕量快速。

vscode 可以用於 mac 嗎 vscode 可以用於 mac 嗎 Apr 15, 2025 pm 07:36 PM

VS Code 可以在 Mac 上使用。它具有強大的擴展功能、Git 集成、終端和調試器,同時還提供了豐富的設置選項。但是,對於特別大型項目或專業性較強的開發,VS Code 可能會有性能或功能限制。

See all articles