我有一个子进程,它只是exit(0)
. 它变成了僵尸。有没有办法在没有父进程wait
或waitpid
在父进程中删除它?
R+ ./server //parent
R+ ./server //child
Z+ (server) //child zombie
您可以捕捉到SIGCHLD
信号(例如使用sigaction(2)等...)。请注意,很少有函数可以安全地从信号处理程序调用。多次阅读signal(7) & signal-safety(7)。在信号处理程序内部做的一件好事就是设置一些volatile sigatomic_t
标志(稍后您将在信号处理程序之外进行测试,例如在某个事件循环中)。或者,您可以在初始化时设置一个管道(7)(到您自己的进程)并在您的信号处理程序中写入几个字节(并在其他地方轮询(2)读取端),如Qt 所建议的那样。
并且可以告诉waitpid(2)不要停止WNOHANG
如果您从不等待您的子进程,它将成为僵尸。
阅读高级 Linux 编程。它有一个关于过程的好章节。
最简单的是让 SIGCHLD 在父级中被忽略:
signal(SIGCHLD, SIG_IGN);
之后,退出的子进程将完全消失,无需等待。
注意:这是一种快速而肮脏的方法,并假设您根本不关心子进程的退出状态,或者它何时退出。如果您确实关心,就像您在真正强大的应用程序中可能应该关心的那样,那么请参阅另一个答案,即创建适当的信号处理程序函数。
补充:这在 Unix 中不是通用的,但至少在 Linux 上有效。根据UNIX FAQ,这是 POSIX 中未定义的行为。此 Mac OS X 手册页表明此行为是在 FreeBSD 5.0 中引入的,并且适用于例如 OS X。
您可以使用双重fork
技术:
创建一个子子进程。并在此之后立即终止子进程。这样子子进程就会走下init
进程。该init
进程将在退出时自动等待子子进程。
这不会删除waitpid
,因为父进程必须等待子进程结束。因为子进程的生命周期总是很短,你可以waitpid
从父进程调用而不会长时间阻塞。
有关更多信息,请参阅本文。