让我们考虑一个常见的场景
创建管道和叉子(假设没有发生错误)
pipe (pipefd); fork();
父进程写入管道,关闭它并等待其子进程
write(pipefd[1], str, strlen(str);
close(pipefd[1]);
wait(NULL);
子进程从管道中读取数据直到EOF
while ((len = read(pipefd[0], buf, BUF_SIZE)) > 0)
write(STDOUT_FILENO, &buf, len);
close(pipefd[0]);
exit(len == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
close(pipefd[1])
可能会失败并出现错误。在这种情况下,孩子的结局会怎样呢?孩子是否也应该收到读取错误或可以在
read
通话中保持阻塞状态?在这种情况下,此代码是否会导致死锁(子级位于
read
,父级位于
wait
)?处理这种情况的正确方法是什么?
pipefd[1]
。不管怎样,孩子必须这样做才能期望它的
read(pipefd[0])
调用报告 EOF 条件。
在父级上调用 close(是的,一般来说,从某种意义上说,
pipefd[1]
) 可能会失败并显示 由于某些原因出现错误。
close()
可能会返回-1并设置
errno
。但这并不一定意味着文件描述符没有关闭。这是一个棘手的情况。您应该阅读close(2) 手册页 的注释部分进行讨论,该部分太长,无法在此处重现。
孩子的结局会发生什么 案件?如果孩子也收到读取错误或可能仍然被阻止这要看情况。在提出问题的一般性水平上没有答案。
read
电话?
在某些系统(例如 Linux)上,
close()
always 会关闭指定的文件描述符,前提是它最初是有效的打开文件描述符,即使它最终报告错误也是如此。在这样的系统上,孩子的
read()
很可能(但不能保证)不会无限期地阻塞。
这段代码会导致死锁吗(如果父进程忽略了管道写入端的失败?是的,孩子继续阻塞
read
上的孩子, 家长在wait
)在这种情况下?
close()
是在 POSIX 允许的可能性范围内。如果父母继续对孩子进行
read()
,那么这可能会陷入僵局。处理这个问题的正确方法是什么 情况?
失败,则父级应以某种方式报告错误 - 例如,诊断消息、以失败状态退出或返回错误代码。它还可以考虑尝试强制子进程终止,例如,向其发送如果
wait()
close()
甚至
SIGTERM
。即使不杀死孩子,在这种情况下您也必须假设可能存在数据丢失或损坏,因此杀死孩子并不会让您在这方面的情况变得更糟。