閱讀509 返回首頁    go 微軟 go Office


避免僵屍進程的三種方法

在unix係統中,如果一個子進程終止了,而父進程又沒有對子進程進行wait/waitpid,那麼子進程就會成為一個僵屍進程。

用命令ps -ef | grep zombie可以查看係統中是否出現僵屍進程。

僵屍進程是無法用kill 殺死,因為進程已經不存在了,但卻在進程表裏麵占據一個項。如果當係統中出現過多的僵屍進程,

那麼係統將無法再開啟另外的進程,因為進程表已經滿了。這個時候就隻有重新啟動,但reboot是沒有用的,因為係統要執行reboot必須要創建進程。這是讓人非常惱火的事情。

避免僵屍進程

1.wait/waitpid

程序通過wait/waitpid等待子進程結束,並清理進程表.

2.兩次fork

對於一些父進程不希望等待子進程結束的程序,可以通過兩次fork來避免僵屍進程

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
 pid_t pid;
 pid = fork();
 if (pid < 0)
 {
         perror(”fork”);
     }
 else if (pid == 0)
 {                                              // 第一個子進程
  pid = fork();
         if (pid < 0)
  {
   perror(”fork”);
   }
                else if (pid > 0)
  {
              exit(0);                       //第二個子進程的父進程終止(第一個子進程)
  }
  sleep(2);                              //保證父進程優先運行(第一個子進程)
  exit(0);                               //第二個子進程終止
 }

 if (waitpid(pid, NULL, 0) != pid)               //等待第一個子進程
  perror(”fork”);
 exit(0);                                        //第一個父進程終止
}

當父進程比子進程先終止時,子進程會被init進程接管,當子進程終止後會被init清理。

3.通過對SIGCHLD信號處理

void sig_chld(int signo)
{
        pid_t   pid;
        int     stat;

        while((pid = waitpid(-1, &stat, WNOHANG)) > 0) {
                printf(”child %d terminated\n”, pid);
        }
        return;
}

int main(void)
{
        int rc;

        rc = 0;
        signal(SIGCHLD, &sig_chld);
        return (rc);
}
在子進程終止時,父進程會收到SIGCHLD信號,可以在這個時候進行處理。也可以忽略此信號。但是忽略SIGCHLD信號並不是對所有的係統都有用

最後更新:2017-01-04 22:34:34

  上一篇:go linux 安裝sysstat使用iostat、mpstat、sar、sa
  下一篇:go Squid集群做CDN全網加速