我正在查看我教授的命令行随机数生成器代码(为之前的项目提供了模板)。在代码的最后,他做了以下事情:
int main (int argc, char *argv[]) {
...
if (fclose (stdout) != 0)
output_errno = errno;
if (output_errno)
{
errno = output_errno;
perror ("output");
}
finalize ();
return !!output_errno;
}
我一直不确定为什么。然而,现在我面临着为另一个项目设计一个 UNIX Pipe,说明如下:
您可能会注意到您的程序挂起等待输入。您必须对您的进程中未明确使用的任何文件描述符调用关闭。未能调用 close 将通知操作系统您尚未完成它,并且它永远不会从读取系统调用返回文件结束。
然而,输入没有输出,所以我想知道为什么。有什么想法吗?
为什么以下代码片段会关闭 STDOUT?
如果程序正在将输出写入文件,就像在 shell 命令中将标准输出重定向到文件时发生的那样,它可能会失败,因为磁盘已满,因为网络卷变得不可用或者磁盘被强制卸载或物理删除由用户或出于其他原因。这并不总是让程序更早知道,因为像
printf
这样的普通调用会缓冲它们的输出。调用 fclose
并检查结果使程序有机会通知用户输出未完全写入,方法是将消息写入标准错误流并向调用环境返回非零退出状态(在从main
返回)。
您可能会注意到您的程序挂起等待输入......它永远不会从读取系统调用返回文件结束。
多个进程之间的管道通常是通过打开一个管道,分叉创建一个新进程,并在一个进程中关闭管道的读取端而在另一个进程中关闭管道的写入端来创建的。只要管道的写入端在任何进程中都是打开的,就有可能(从操作系统的角度来看)进程可以将数据写入管道,因此操作系统会保持任何进程读取管道等待潜在数据的管道。只有当所有进程都关闭了管道的写入端时,操作系统才会通知读取器没有更多数据了。