C 是否保证在进程终止后关闭stdin/stderr?

C 是否保证在进程终止后关闭stdin/stderr?,c,posix,C,Posix,我使用pipe()、fork()、dup()、execve()生成子进程 从父级,是否可以安全地等待子级的stdin和stdout关闭(即read()同时返回0),然后执行waitpid()以收集终止状态 或者,在不关闭stdin和stdout的情况下,进程会失败吗?(因此,我的程序从未到达waitpid) 为了澄清,我想问以下各项是否安全: while (child_stdin != -1 && child_stdout != -1) { poll(...)

我使用pipe()、fork()、dup()、execve()生成子进程

从父级,是否可以安全地等待子级的stdin和stdout关闭(即read()同时返回0),然后执行waitpid()以收集终止状态

或者,在不关闭stdin和stdout的情况下,进程会失败吗?(因此,我的程序从未到达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


不涉及任何信号,只需轮询()。

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

如果子进程从未终止,则可能会发生这样的情况:您的父进程将永远等待,并且永远不会到达
waitpid()

编辑:

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

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

如果进程
a
生成进程
b
,而进程
b
生成进程
c
(因此
c
a
的孙辈),
b
可以终止并关闭其标准文件描述符的副本(大概,
b的stdout是
a
正在监视的管道的写入端。)但是
c
仍然打开该管道,因此
a
将从
b
获取SIGCHLD,但不会在管道上获取EOF。换句话说,是的,可能发生子管道终止,但父管道未关闭的情况


另外,
a
仍然打开管道的写入端也是一个常见的编码错误。在这种情况下,
b
可以终止并关闭管道写入端的副本,但是父级从未看到管道关闭,因为父级一直将其打开。

啊,是的,当然。这只是一个简单的示例。谢谢您的回答但是我选择了William的,因为它更全面。当父母的stdin从后台而不是前台运行的孩子那里收到一个信号时,它会收到一个EOF。我怎么能在信号处理程序中忽略这个EOF?EOF不是一个信号,所以你不能忽略它。EOF甚至不是一个东西,只是一个方便的语言抽象。当进程尝试从不再有任何数据且所有写入端都已关闭的管道中读取时,
read
fread
将返回0。
fgetc
getc
,等等。返回一个整型值,C预处理器通过标签“EOF”标识该整型值,人类会缩短表达式n“当所有写入端都关闭且数据已耗尽时,尝试在管道上读取”和“管道达到EOF”。您永远不会“接收EOF”。
if (n >= 0) {  // n > 0 || n == 0
    // ...
} else if (n == 0) {
    // Never reached!
}