C 如果从管道读取数据时尾部出现故障怎么办
因此,与上面的链接相关,我有一个孩子正在执行C 如果从管道读取数据时尾部出现故障怎么办,c,unix,pipe,stderr,tail,C,Unix,Pipe,Stderr,Tail,因此,与上面的链接相关,我有一个孩子正在执行tail,而家长正在通过管道读取其输出 dup2(pipefd[1], STDOUT_FILENO); dup2(pipefd[1], STDERR_FILENO); 我的问题是,如果tail以某种方式失败,我正在读取的管道会发生什么情况?我在stderr上有什么消息吗?tail是否自行终止?或者它可能挂在那里,因为已失效?当tail终止时,内核将向管道上的另一个进程发送SIGPIPE信号。此信号的默认操作(如果未安装处理程序)是终止进程 如果不想处
tail
,而家长正在通过管道读取其输出
dup2(pipefd[1], STDOUT_FILENO);
dup2(pipefd[1], STDERR_FILENO);
我的问题是,如果tail
以某种方式失败,我正在读取的管道会发生什么情况?我在stderr
上有什么消息吗?tail
是否自行终止?或者它可能挂在那里,因为已失效
?当tail
终止时,内核将向管道上的另一个进程发送SIGPIPE
信号。此信号的默认操作(如果未安装处理程序)是终止进程
如果不想处理信号,可以忽略父级中的SIGPIPE
(这样当tail
终止时,它不会终止),而是在每次读取后检查errno
的值是否为EPIPE
。此外,您必须从父级调用wait
或waitpid
,以获取僵尸子级。如果读取时未获得EPIPE,则只有write将返回EPIPE。您将得到EOF,由read返回0表示,并且由于您读取了stderr,因此也将得到错误消息(在EOF之前)
进程将变成僵尸,您可以使用wait/waitpid获取退出状态,如果出现错误,退出状态将为非零。如果tail失败,管道读取端的任何读取都将返回EOF。如果tail失败,它已经终止,“失败”的定义是它以非零退出状态终止。它将保留在进程表中(即“已失效”),直到父进程等待它
但是为什么你让tail对stderr和stdout使用相同的管道呢?为什么不做两根管子呢?这似乎可以消除区分两个输出流的问题。因为它们是重复的,我认为关闭一个的子级也会关闭另一个,导致后续对另一个的写入失败。父级将获得文件的结尾。但我不是100%肯定。@wberry:事实上,关闭是一件可以使用复制文件描述符而不影响其其他别名的事情。谢谢。我只想了解为什么SIGPIPE是一个古老的、几乎是历史性的Unix约定,但至今仍在使用。尽管如此,您仍然可以忽略SIGPIPE
,并检查errno
是否在父级中的read
之后是EPIPE
。SIGPIPE不是在管道关闭时发送的,而是在尝试写入另一端时发送的。谢谢,我相信,现在我甚至不需要读取stderr
。如果tail
失败,stdout
将获得EOF
,对吗?无论如何,我都在等待孩子。所以,它会被清理干净。听起来对吗?