6

我使用 pipe()、fork()、dup()、execve() 生成了一个子进程。

从父母那里,等待孩子的标准输入和标准输出关闭(即 read() 两者都返回 0),然后执行 waitpid() 来收集终止状态是否安全?

或者在没有关闭标准输入和标准输出的情况下,进程是否会失败?(因此我的程序永远不会进入waitpid)


为了澄清,我问以下是否安全:

while (child_stdin != -1 && child_stdout != -1) {
    poll(...)

    if (got_stdout) {
        n = read(child_stdout);
        if (n >= 0) {
            // do something with output
        } else if (n == 0) {
            child_stdout = -1
        }
    }

    // same for stdin
}

waitpid(child_pid)

或者孩子会终止,但我永远不会在 read() 或 write() 上得到 0。

不涉及任何信号,只是 poll()-ing。

4

2 回答 2

6

如果进程a生成进程b,并且进程b生成进程cc的孙子进程也是如此a),b则可以终止并关闭作为其标准输出的文件描述符的副本(推测b's标准输出是正在监视的管道的写入端a。)但c仍然有该管道打开,因此a将从中获取 SIGCHLD b,但不会在管道上获取 EOF。换句话说,是的,可能会发生子进程终止但父进程没有看到管道关闭的情况。

此外,这是一个常见的编码错误,a仍然使管道的写入端处于打开状态。在这种情况下,b可以终止并关闭其管道写入端的副本,但父级永远不会看到管道关闭,因为父级保持它处于打开状态。

于 2012-11-01T17:18:48.670 回答
2

系统在进程退出时关闭所有文件描述符。可能发生的情况是,缓冲区中存储了一些输出,尚未刷新。

如果子进程永远不会终止,那么它可能会发生,你的父进程永远等待并且永远不会到达waitpid().

编辑:

当您的孩子终止时,所有描述符都将关闭,然后您最终将获得 0 read()(如果出现问题,则为 -1!)。因此,您可能希望更改为:

...
if (n > 0) {
    // do something with output
} else if (n <= 0) {
    child_stdout = -1
}

但是,您的代码不会终止,因为:

if (n >= 0) {  // n > 0 || n == 0
    // ...
} else if (n == 0) {
    // Never reached!
}
于 2012-11-01T17:14:34.630 回答