91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Linux 僵尸進程產生原因及解決方法

發布時間:2020-09-25 22:35:51 來源:腳本之家 閱讀:298 作者:sparkdev 欄目:服務器

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

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

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

僵尸進程是如何產生的

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

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

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

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  int i = 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.\n", getpid());
    for(; i > 0; i--)
    {
      sleep(1);
    }
  }
  else if(pid == 0)
  {
    printf("This is the child process. My PID is: %d. My PPID is: %d.\n", getpid(), getppid());
  }
  return 0;
}

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

$ gcc zomprocdemo.c -o zomprocdemo

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

$ ./zomprocdemo

Linux 僵尸進程產生原因及解決方法

此時子進程已經退出,但是父進程沒有退出也沒有通過 wait() 調用處理子進程。我們使用 ps 命令查看進程的狀態:

Linux 僵尸進程產生原因及解決方法

上圖紅框中的大寫字母 "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() 等待子進程結束:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  pid_t pid;
  pid = fork();
  if (pid < 0)
  {
    perror("fork failed");
    exit(1);
  }
  if (pid == 0) {
    int i;
     for (i = 3; i > 0; i--)
     {
      printf("This is the child\n");
      sleep(1);
     }
     // exit with code 3 for test.
    exit(3);
  }
  else
  {
    int stat_val;
    wait(&stat_val);
     if (WIFEXITED(stat_val))
     {
       printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
     }      
  }
  return 0;
}

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

泸溪县| 玉门市| 金山区| 黄龙县| 靖边县| 同德县| 潢川县| 宜阳县| 溧阳市| 鄂托克旗| 尚志市| 新巴尔虎左旗| 荔浦县| 泗洪县| 福贡县| 德州市| 东城区| 和顺县| 屯昌县| 和平县| 峨眉山市| 融水| 河津市| 同江市| 大悟县| 惠来县| 文昌市| 荆门市| 扶沟县| 慈溪市| 五原县| 二手房| 安塞县| 湖南省| 化德县| 新营市| 隆尧县| 新巴尔虎右旗| 泰和县| 青铜峡市| 儋州市|