如何防止僵尸子进程?

14

我正在编写一个服务器,使用fork()生成客户端连接的处理程序。 服务器不需要知道分叉进程发生了什么-它们可以自己工作,完成任务后应该死亡而不是变成僵尸进程。 有什么简单的方法可以实现这一点?


1
这可能是最简单的方法:https://dev59.com/fWw05IYBdhLWcg3wiyfg#7171836 - andrewsh
@andrewsh 哦,不错。您认为这些问题是否足够相似,可以将其标记为重复吗? - thejh
3个回答

16

有几种方法,但是在父进程中使用带有 SA_NOCLDWAITsigaction 可能是最简单的一种:

struct sigaction sigchld_action = {
  .sa_handler = SIG_DFL,
  .sa_flags = SA_NOCLDWAIT
};
sigaction(SIGCHLD, &sigchld_action, NULL);

3
更简单的写法:signal(SIGCHLD, SIG_IGN);,意思是忽略子进程结束信号。 - domsson

7

使用双重fork。让您的孩子立即复制另一个副本,并使原始子进程退出。

http://thinkiii.blogspot.com/2009/12/double-fork-to-avoid-zombie-process.html

在我看来,这比使用信号更简单且更易理解。

void safe_fork()
{
  pid_t pid;
  if (!pid=fork()) {
    if (!fork()) {
      /* this is the child that keeps going */
      do_something(); /* or exec */
    } else {
      /* the first child process exits */
      exit(0);
    }
  } else {
    /* this is the original process */  
    /* wait for the first child to exit which it will immediately */
    waitpid(pid);
  }
}

3
但是,如果有人想要查看流程树或类似的内容,这样会弄乱它,对吗? - thejh
不确定,但似乎很可能。 - xaxxon
进程不会变成僵尸进程,但每次执行 safe_fork() 时,都会在 ps 中创建另一个进程,该进程仅在所有父进程终止时结束。 - Puffy
@AbelRomeroPérez 它们被重新分配给 init,一旦完成就会清理它们。短暂的进程会立即被父进程清理。 - xaxxon
@xaxxon,每次执行我的safe_fork()实现时,为什么ps中会出现一个新的进程?:( - Puffy
显示剩余4条评论

0

如何消除僵尸进程?

你不能像杀死普通进程一样使用SIGKILL信号来杀死僵尸进程,因为僵尸进程无法接收任何信号。所以养成良好的习惯非常重要。

那么在编程时,如何消除大量的僵尸进程?根据上述描述,当子进程死亡时,它将向父进程发送SIGCHLD信号。默认情况下,系统会忽略此信号,因此最好的方法是在信号处理函数中调用wait(),这可以避免僵尸进程在系统中滞留。 了解更多信息:http://itsprite.com/how-to-deep-understand-the-zombie-process-in-linux/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接