[英]Is waitpid() an atomic operation in Linux?
例如,在父进程中,我分叉子进程并等待子进程:
int main() {
setSignal(SIGCHLD, sigchld_handler)
while(1) {
// fork some child processes
myForkFunction()
waitpid(-1, &status, 0)
}
}
此外,我有一个SIGCHLD信号处理程序:
void
sigchld_handler(int sig) {
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
// Reap zombie processes
}
}
可以看出, waitpid()
出现在main()
函数和sigchld_handler()
函数中。 我想知道SIGCHLD
是否可以中断waitpid
。 如果它可以被SIGCHLD
打断,那会发生什么?
有没有人对此有任何想法?
waitpid()
的POSIX规范部分说明:
如果定义了_POSIX_REALTIME_SIGNALS,并且实现对SIGCHLD信号进行排队,那么如果由于子进程的状态可用而返回
wait()
或waitpid()
,则应丢弃与子进程的进程ID关联的任何挂起的SIGCHLD信号。 任何其他待处理的SIGCHLD信号应保持未决状态。否则,如果SIGCHLD被阻止,如果由于子进程的状态可用而返回
wait()
或waitpid()
,则除非另一个子进程的状态可用,否则应清除任何未决的SIGCHLD信号。对于所有其他条件,未指定在传送SIGCHLD信号时是否可以使用子状态。
所引用的段落中的第三段似乎意味着你正在踩着薄冰。 它没有提到“实现定义”或类似 - 未指定意味着标准没有说明将发生什么,您可能会或可能不会从特定于实现的文档中获取任何信息。
POSIX规范中有很多(措辞非常密集)信息。 还有一些例子和理由 - 提到了sigwait()
和sigwaitinfo()
。 值得阅读整个waipid()
页面。 您也应该阅读有关Signal概念的内容 - 阅读更加密集。 (其中一天,我也会这样做 - 当我需要知道以前没有涉及的信号时。)
你为什么使用WUNTRACED
而不是0
或WNOHANG
? WUNTRACED
是一个非常专业的条件 - POSIX说:
WUNTRACED
pid指定的任何已停止的子进程的状态,以及自其停止后尚未报告其状态的状态,也应报告给请求进程。
类似的评论适用于WCONTINUED
。 当你需要它们时,这两个标志很有用,但你很少需要它们。
我建议你通常应该在waitpid()
的第三个参数中使用0
或WNOHANG
。
是的,从某种意义上说,只有其中一个能够成功完成特定的子进程; 如果信号处理程序中断了main
中的那个,那么在信号处理程序返回之后,子项将已经被收获并且main
的调用将失败。
尽管如此,编写这样的代码是不好的做法。 应该有一个地方处理给定子进程的收获,通常信号处理程序是一个非常糟糕的选择,因为它是全局的,它必须知道您的程序可能已经完成的所有可能的子进程, 并且有办法将这些结果传达给程序的适当部分 。
相反,它是通常更好地监测通过子进程的终止poll
上管/从孩子的过程,只有waitpid
,你知道后,它的终止,或进行阻止waitpid
从一个线程,其唯一的工作就是等待孩子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.