linux后台开发中避免僵尸进程的方法总结( 二 )

程序运行期间通过ps命令的确没有发现僵尸进程的存在 。
在man文档中有这段话:
Note that even though the default disposition of SIGCHLD is "ignore", explicitly setting the disposition to SIG_IGN results in different treatment of zombie process children.
意思是说尽管系统对信号SIGCHLD的默认处理就是“ignore”,但是显示的设置成SIG_IGN的处理方式在在这里会表现不同的处理方式(即子进程结束后,资源由系统自动收回,所以不会产生僵尸进程),这是信号SIGCHLD与其他信号的不同之处 。
在man文档中同样有这样一段话:
The original POSIX standard left the behavior of setting SIGCHLD to SIG_IGN unspecified. 看来这个方法不是每个平台都使用,尤其在一些老的系统中,兼容性不是很好,所以如果你在写一个可移植的程序的话,不推荐使用这个方法 。
第二种方法,即通过两次fork来避免僵尸进程,我们来看一个例子avoid_zombie2.c:
#include <stdio.h>  #include <stdlib.h>  #include <signal.h>  #include <unistd.h>  #include <errno.h>    int main(int argc, const char *argv[])  {      pid_t pid;        while (1) {          if ((pid = fork()) == 0) {  /* child */              if ((pid = fork()) > 0)                  _exit(0);              sleep(1);              printf("grandchild, parent id = %ldn",                              (long)getppid());              _exit(0);          }          if (waitpid(-1, NULL, 0) != pid) {              perror("waitpid error");              _exit(EXIT_FAILURE);          }      }        exit(EXIT_SUCCESS);  }  这的确是个有效的办法,但是我想这个方法不适宜网络并发服务器中,应为fork的效率是不高的 。
最后来看第三种方法,也是最通用的方法
先看我们的测试程序avoid_zombie3.c
#include <stdio.h>  #include <stdlib.h>  #include <errno.h>  #include <string.h>  #include <libgen.h>  #include <signal.h>  #include <unistd.h>  #include <sys/wait.h>  #include <sys/types.h>      void avoid_zombies_handler(int signo)  {      pid_t pid;      int exit_status;      int saved_errno = errno;        while ((pid = waitpid(-1, &exit_status, WNOHANG)) > 0) {          /* do nothing */      }        errno = saved_errno;  }    int main(int argc, char *argv[])  {      pid_t pid;      int status;      struct sigaction child_act;         memset(&child_act, 0, sizeof(struct sigaction));      child_act.sa_handler = avoid_zombies_handler;      child_act.sa_flags = SA_RESTART | SA_NOCLDSTOP;       sigemptyset(&child_act.sa_mask);      if (sigaction(SIGCHLD, &child_act, NULL) == -1) {          perror("sigaction error");          _exit(EXIT_FAILURE);      }        while (1) {          if ((pid = fork()) == 0) {  /* child process */              _exit(0);          } else if (pid > 0) {        /* parent process */          }      }            _exit(EXIT_SUCCESS);  }  


推荐阅读