首页 文章

waitpid()是Linux中的原子操作吗?

提问于
浏览
1

例如,在父进程中,我分叉子进程并等待子进程:

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 中断,那么会发生什么?

有没有人对此有任何想法?

2 回答

  • 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指定的任何子进程的状态,如果已停止,并且自停止后尚未报告其状态,也应报告给请求进程 .

    类似的评论适用于 WCONTINUED . 当你需要它们时,这两个标志很有用,但你很少需要它们 .

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

  • 1

    是的,从某种意义上说,只有其中一个能够成功完成特定的子进程;如果信号处理程序中断了 main 中的那个,那么在信号处理程序返回之后,子项将已经被收获并且 main 中的调用将失败 .

    然而,据说,它是全局的,它必须知道您的程序可能已经完成的所有可能的子进程,并且有办法将这些结果传达给程序的适当部分 .

    相反,通常最好通过管道进出子进程监视子进程的终止,并且只有 waitpid 才知道它被终止,或者从一个唯一的工作是等待子进程的线程执行阻塞 waitpid . .

相关问题