【发布时间】:2015-04-24 15:53:17
【问题描述】:
我目前正在深入研究 Win32 API,并为CreateProcess 和CreatePipe 编写一个包装类。我只是想知道如果我打开的进程写入了太多输出以使管道缓冲区无法容纳会发生什么。该过程会等到我从管道的另一端读取数据吗? CreatePipe 函数的备注表明:
当进程使用 WriteFile 写入匿名管道时,直到写入所有字节后,写入操作才会完成。如果在写入所有字节之前管道缓冲区已满,则 WriteFile 不会返回,直到另一个进程或线程使用 ReadFile 来提供更多可用缓冲区空间。
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365152%28v=vs.85%29.aspx
假设我使用CreateProcess 打开一个进程,然后使用WaitForSingleObject 等待进程退出。如果进程超出其标准输出管道的缓冲区大小,它会退出吗?
【问题讨论】:
-
如果官方引用说
WriteFile函数“直到...才返回”,这与它阻塞相同。那么答案是肯定的写入一个完整的管道会阻塞。顺便说一句,这是标准行为,例如POSIX 系统(如 Linux 或 OSX)也是如此。 -
在 POSIX 系统中确实会发生这种情况:生产者被阻塞,直到有空间可以写入。例如,当您执行
ls -R / | less时,less将读取一些文本屏幕,然后阻止ls,直到用户向下滚动。如果用户杀死阅读器进程(例如通过退出less),原始进程将被杀死。这样可以节省很多无用的计算。 -
“不返回” == 块。如果您不阅读重定向的输出,那么,是的,该过程很可能会死锁。一个非常标准的错误是耗尽标准输出而不是标准错误。您需要在所有 3 个句柄上使用 WaitForMultipleObjects()。
-
@HansPassant 如果进程退出,输出不会被关闭,所以你可以只读取输出管道而不包括进程?你能把 stderr 留在控制台上,这样就不是你的问题了吗?
-
@Random832:当然,您可以将
stderr绑定到控制台流。或者stdout和stderr到同一个管道。
标签: c winapi pipe createprocess