C waitpid()在Linux中是一个原子操作吗?
例如,在父进程中,我分叉了一个子进程并等待子进程:C waitpid()在Linux中是一个原子操作吗?,c,linux,unix,signals,system-calls,C,Linux,Unix,Signals,System Calls,例如,在父进程中,我分叉了一个子进程并等待子进程: int main() { setSignal(SIGCHLD, sigchld_handler) while(1) { // fork some child processes myForkFunction() waitpid(-1, &status, 0) } } 此外,我还有一个SIGCHLD信号处理器: void sigchld_handler(in
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\u handler()函数中。我想知道waitpid
是否可以被SIGCHLD
中断。如果它可以被SIGCHLD
中断,那么会发生什么
有人对此有什么想法吗?是的,在这个意义上,对于给定的子进程,只有其中一个能够成功;如果信号处理程序中断了main
中的子进程,那么在信号处理程序返回后,子进程将已被捕获,而main
中的调用将失败
尽管如此,编写这样的代码是不好的做法。您应该在一个地方处理给定子进程的收获,通常情况下,信号处理程序是一个非常糟糕的选择,因为它是全局的,它必须知道您的程序可能完成的所有可能的子进程,并有一种方法将这些结果传达给程序的适当部分
相反,通常最好通过进出子进程的管道上的poll
来监视子进程的终止,并且只有在知道子进程终止后才进行waitpid
,或者从其唯一任务是等待子线程的线程执行阻塞waitpid
。的POSIX规范部分说明:
如果定义了_POSIX_REALTIME_SIGNALS,并且实现将SIGCHLD信号排队,那么如果wait()
或waitpid()
由于子进程的状态可用而返回,则应丢弃与子进程的进程ID相关联的任何挂起的SIGCHLD信号。任何其他未决信号应保持未决状态
否则,如果SIGCHLD被阻止,如果wait()
或waitpid()
由于子进程的状态可用而返回,则应清除任何挂起的SIGCHLD信号,除非另一个子进程的状态可用
对于所有其他条件,未指定在发送SIGCHLD信号时子状态是否可用
引用的第三段似乎暗示你如履薄冰。它没有提到“已定义的实现”或类似内容——未指定的意思是该标准没有说明将发生什么,并且您可能从特定于实现的文档中获得任何信息
POSIX规范中有很多(非常密集的)信息。这里也有一些例子和一个基本原理,其中提到了和。整个waipd()
页面都值得一读。你可能也应该读一些过于密集的阅读。(总有一天,我也会这么做——当我需要知道一些我以前没有涉及过的信号时。)
为什么您使用WUNTRACED
而不是0
或WNOHANG
WUNTRACED
是一种非常特殊的情况-POSIX说:
WUNTRACED
pid指定的已停止且自停止后其状态尚未报告的任何子进程的状态也应报告给请求进程
类似的注释适用于WCONTINUED
。这两个标志在您需要时非常有用,但您很少需要它们
我建议您通常在waitpid()
的第三个参数中使用0
或WNOHANG
为什么要使用WUNTRACED
而不是0
或WNOHANG
WUNTRACED
是一个非常特殊的条件-POSIX说:WUNTRACED pid指定的任何停止的子进程的状态,并且其状态在停止后尚未报告,也应报告给请求进程。(这里面有一个我在第一次阅读时错过的“也”,但即便如此,干扰停止/跟踪的进程也是不寻常的。)是的,WUNTRACED
非常奇怪,可能不是OP想要的…@JonathanLeffler是的,你是对的。谢谢你搞错了。您应该将其更改为WNOHANG
(而不是0
)<如果您有一个尚未完成的孩子,代码>0将导致信号处理程序阻塞。谢谢您的帮助!在问这个问题之前,我正在读CSAPP的书。似乎POSIX规范是查找这些信息的更好地方。谢谢我在“监控子进程”一章中翻了翻,没有找到任何直接相关的内容,该章涵盖了大量关于SIGCHLD和waitpid()
——或者在我看过的同一本书的其他几个地方。这远不是一个确定的“未涵盖”,但这表明它可能没有涵盖。