【问题标题】:Is waitpid() an atomic operation in Linux?waitpid() 是 Linux 中的原子操作吗?
【发布时间】:2016-11-05 15:35:31
【问题描述】:

比如在父进程中,我fork了一个子进程,等待子进程:

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() 函数中。我想知道waitpid 是否可以被SIGCHLD 打断。如果它可以被SIGCHLD打断,那会发生什么?

有人对此有任何想法吗?

【问题讨论】:

  • 您为什么使用WUNTRACED 而不是0WNOHANGWUNTRACED 是一个非常特殊的条件 - POSIX waitpid() 说:WUNTRACED 由 pid 指定的任何已停止的子进程的状态,并且自停止后尚未报告其状态,也应报告给请求进程。(我在第一次阅读时错过了一个“也”,但即便如此,搞乱停止/跟踪的进程是不寻常的。)
  • 是的,WUNTRACED 很奇怪,可能不是 OP 想要的...
  • @JonathanLeffler 是的,你是对的。谢谢!
  • 你修错了。你应该把它改成WNOHANG(不是0)。 0 如果您有一个尚未完成的孩子,将导致您的信号处理程序阻塞。

标签: c linux unix signals system-calls


【解决方案1】:

是的,从某种意义上说,对于给定的子进程,它们中只有一个可以成功;如果信号处理程序中断了main 中的那个,那么在信号处理程序返回后,孩子将已经被收割,main 中的调用将失败。

话虽如此,但编写这样的代码是一种不好的做法。您应该在一个地方处理给定子进程的收割,通常信号处理程序是一个非常糟糕的选择,因为它是全局的,它必须知道您的程序可能完成的所有可能的子进程,和有办法将这些结果传达给程序的适当部分

相反,通常最好通过poll 在通往/来自子进程的管道上监视子进程的终止,并且仅在您知道它已终止之后使用waitpid,或者从线程执行阻塞waitpid他们唯一的工作就是等孩子。

【讨论】:

    【解决方案2】:

    waitpid() 的 POSIX 规范部分说明:

    如果定义了 _POSIX_REALTIME_SIGNALS,并且实现对 SIGCHLD 信号进行排队,那么如果 wait()waitpid() 因为子进程的状态可用而返回,则任何与子进程的进程 ID 相关联的未决 SIGCHLD 信号应被丢弃。任何其他未决的 SIGCHLD 信号应保持未决。

    否则,如果 SIGCHLD 被阻塞,如果 wait()waitpid() 因为子进程的状态可用而返回,则应清除任何未决的 SIGCHLD 信号,除非另一个子进程的状态可用。

    对于所有其他条件,未指定在传递 SIGCHLD 信号时子状态是否可用。

    引用的第三段似乎暗示你如履薄冰。它没有提到“定义的实现”或类似的东西——未指定意味着标准没有说明会发生什么,您可能会或可能不会从特定于实现的文档中获得任何信息。

    POSIX 规范中有很多(措辞非常密集的)信息。还有一些例子和理由——提到了sigwait()sigwaitinfo()。值得阅读整个waipid() 页面。您可能还应该阅读有关Signal concepts 的内容——更密集的阅读。 (有一天,我也会这样做——当我需要了解一些我以前没有涉及的信号时。)


    您为什么使用WUNTRACED 而不是0WNOHANGWUNTRACED 是一个非常特殊的条件——POSIX 说:

    WUNTRACED
    pid 指定的任何已停止的子进程的状态,以及自停止后尚未报告其状态的子进程的状态,也应报告给请求进程。

    类似的 cmets 适用于 WCONTINUED。这两个标志在您需要它们时很有用,但您很少需要它们。

    我建议您通常应该在waitpid() 的第三个参数中使用0WNOHANG

    【讨论】:

    • 感谢您的帮助!在问这个问题之前,我正在阅读 CSAPP 的书。似乎 POSIX 规范是查找这些信息的更好地方。谢谢!
    • 我在The Linux Programming Interface 上一探究竟,并没有在“监控子进程”一章中找到任何直接相关的内容,该章涵盖了很多关于 SIGCHLD 和 waitpid() 的材料——或者在其他几个地方在我看过的同一本书中。这远不是一个明确的“它没有被覆盖”,但它表明它可能不是。
    猜你喜欢
    • 1970-01-01
    • 2015-01-10
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    相关资源
    最近更新 更多