2013-05-03 56 views
5

我有一个子进程,只是exit(0)。它变成了僵尸。在父进程中没有waitwaitpid,有没有办法删除它?僵尸进程删除无需等待C

R+ ./server //parent 
R+ ./server //child 
Z+ (server) //child zombie 
+0

不知道这是一个C的帖子。也许是因为Unix是用C创建的? :) – 2013-05-03 17:00:52

+0

为什么你不想使用'wait'或'waitpid'? – FDinoff 2013-05-03 17:01:24

+0

,因为'wait'会停止父进程,直到子进程退出。 – 2013-05-03 17:02:37

回答

5

最简单的就是让SIGCHLD父忽略:

signal(SIGCHLD, SIG_IGN); 

之后,退出子进程将只是干净走开,而无需进行等待上。

注意:这是一个快速的&脏方法,并且假定您根本不在乎子进程的退出状态,或者关于它何时退出。如果你真的关心,你可能应该在一个真正强大的应用程序中,然后看看另一个答案,关于创建一个合适的信号处理函数。

此外:这在Unix中不是通用的,但至少在Linux上起作用。根据an UNIX FAQ,它在POSIX中是未定义的行为。例如,This Mac OS X man page表明此行为是在FreeBSD 5.0中引入的,并且适用于OS X。

+1

仅当父进程退出时,子进程不会消失(不是僵尸)吗?换句话说,他们不是僵尸,直到父母退出?我可以想象,即使忽略了'SIGCHLD'信号,父类仍然可以'waitpid',因此内核必须对子进程进行zombify(但我可能是错的,因为我没有测试它)。 – 2013-05-03 17:52:20

+0

@BasileStarynkevitch增加了一段和解释更多的链接。但是当它工作时,然后退出/终止的子进程真的会消失,没有僵尸,无法等待。 – hyde 2013-05-05 06:18:16

+0

但子进程立即消失,还是仅在父进程退出? – 2013-05-05 12:24:02

6

你可以赶上SIGCHLD信号(例如使用sigaction(2)等)。要小心,很少的函数可以从信号处理程序安全地调用。多次阅读signal(7) & signal-safety(7)。在信号处理器内部做的一件好事是设置一些volatile sigatomic_t标志(稍后将测试,在信号处理器的之外,例如在某些event loop中)。或者你可以在初始化时设置一个pipe(7)(对你自己的进程),并在你的信号处理器上写入几个字节(poll(2)读取结束),如suggested by Qt

而且waitpid(2)可以告诉不WNOHANG

停止如果你从来没有等待你的子进程,它将成为zombie

阅读Advanced Linux Programming。它有很好的流程章节。

2

您可以使用双fork技术:

创建一个子子进程。之后立即终止子进程。 通过这种方式,子孩子进程将在init进程下进行。当子进程退出时,init进程将自动等待。

这不会删除waitpid,因为父级必须等待子进程结束。 由于子进程的生命周期总是最短,因此您可以从父进程调用waitpid而不会阻塞。

查看this article了解更多信息。