stdin 和 stdout 是否共享任何资源?

Do stdin and stdout share any resources?

标准输入和标准输出是否独立?

考虑一个父程序启动了一个子程序,父程序的标准输出附加到子程序的标准输入,子程序的标准输出附加到父程序的标准输入。

        stdin       <- stdout 
parent                        child
        stdout ->      stdin

如果子进程(异步地)不断地从其标准输入中读取数据并将数据写入其标准输出,但父进程只是写入子进程的标准输入而根本没有从子进程的标准输出中读取数据:

        stdin|     << stdout 
parent                       child
        stdout ==>==> stdin

最终会不会堵塞?标准输入和标准输出是否共享任何类型的缓冲区?如果需要回答,特别是通过 C++ std::cin (istream) 和 std::cout (ostream)。标准是否要求他们共享或不共享此类内容,还是留给实施?

会发生什么?

您不能 "attach" 一个进程的文件描述符到另一个进程的文件描述符。你所做的(如果你的操作系统支持的话)是将这两个文件描述符分配给 "pipe" 的末尾。 C/C++ 标准中的任何地方都没有指定管道(它们由 POSIX 定义),并且您不会找到任何引用它们的标准 C/C++ 库函数完全没有。

正如 Unix(和 Unix-like)系统所实现的那样,管道只不过是操作系统中某处的缓冲区。当缓冲区未满时,进程可以将数据写入管道的输入端;数据只是添加到缓冲区。当缓冲区不为空时,进程可以从缓冲区的输出端读取数据;数据从缓冲区中删除并移交给读取过程。如果进程试图写入缓冲区已满的管道或从缓冲区为空的管道读取,进程"blocks":即被内核调度程序标记为不可运行,并停留在那个状态,直到管道可以处理它的请求。

问题描述的场景需要涉及两个管道。一个管道用于允许 parent 的标准输出向 child 的标准输入发送数据,另一个用于允许 child 的标准输出向 child 的标准输出发送数据parent 的标准输入。这两个管道完全相互独立。

现在,如果 parent 停止从其标准输入读取,但 child 继续写入其标准输出,那么最终管道缓冲区将变满。 (实际上不会花很长时间。管道缓冲区不是很大,并且不会增长。)到那时,child 将阻止尝试写入管道。如果 child 不是多线程的,那么一旦它阻塞,就是这样。它停止 运行,所以它不会再从它的标准输入中读取。如果 child 停止从其标准输入读取数据,那么另一个管道将很快变满,并且 parent 也将阻止尝试写入其标准输出。

所以不需要为了实现死锁而共享资源。

这是进程中一个非常 well-known 的错误,它产生 child 并在读取 child 的响应时尝试向 child 提供数据。如果 reader 跟不上生成的数据,则可能会出现死锁。例如,通过搜索 "pipe buffer deadlock",您会找到很多关于它的信息。这里有一些示例链接,只是随机的:

Raymond Chen,在 MSDN 上:http://blogs.msdn.com/b/oldnewthing/archive/2011/07/07/10183884.aspx

就在 Whosebug 上(参考 Python 但问题相同):Can someone explain pipe buffer deadlock?

大卫·格拉瑟,2006 年:http://web.mit.edu/6.033/2006/wwwdocs/writing-samples/unix-DavidGlasser.html ("These limitations are not merely theoretical — they can be seen in practice by the fact that no major form of inter-process communication later developed in Unix is layered on top of pipe.")