C 如果管道已满,进程是否会写入管道块?

C 如果管道已满,进程是否会写入管道块?,c,winapi,pipe,createprocess,C,Winapi,Pipe,Createprocess,我目前正在深入研究Win32 API,并为CreateProcess和CreatePipe编写一个包装类。我只是想知道如果我打开的进程写了太多的输出而管道缓冲区无法容纳,会发生什么。这个过程会一直等到我从管道的另一端读取数据吗?CreatePipe函数的注释表明: 当进程使用WriteFile写入匿名管道时,只有在写入所有字节后,写入操作才会完成。如果管道缓冲区在写入所有字节之前已满,则WriteFile不会返回,直到另一个进程或线程使用ReadFile来提供更多的缓冲区空间 假设我使用Cre

我目前正在深入研究Win32 API,并为
CreateProcess
CreatePipe
编写一个包装类。我只是想知道如果我打开的进程写了太多的输出而管道缓冲区无法容纳,会发生什么。这个过程会一直等到我从管道的另一端读取数据吗?
CreatePipe
函数的注释表明:

当进程使用WriteFile写入匿名管道时,只有在写入所有字节后,写入操作才会完成。如果管道缓冲区在写入所有字节之前已满,则WriteFile不会返回,直到另一个进程或线程使用ReadFile来提供更多的缓冲区空间


假设我使用
CreateProcess
打开一个进程,然后使用
WaitForSingleObject
等待进程退出。如果进程超出其标准输出管道的缓冲区大小,该进程是否会退出?

WaitForSingleObject
对于具有重定向输出的进程来说,确实是一个死锁。您需要保持输出管道排空,以便让子进程运行到完成

通常,您会在管道上使用重叠I/O,然后在循环中的句柄对1(进程句柄、管道读取事件句柄)上使用
WaitForMultipleObjects
,直到进程句柄发出信号

Raymond Chen写到了输入也通过管道传输的场景:



1正如Hans所评论的,可以有多个输出流
stdout
stderr
是典型的,甚至可以通过句柄继承实现更多。排出流程中的所有管道。

如果官方参考称
WriteFile
功能“直到…”才返回,则与阻塞相同。那么答案是肯定的,写满一根管子会阻塞。顺便说一下,这也是POSIX系统(如Linux或OSX)上的标准行为。在POSIX系统中,确实会发生这种情况:生产者被阻止,直到有空间写入。例如,当您执行
ls-R/|less
时,
less
将读取一些文本屏幕,然后阻止
ls
,直到用户向下滚动。如果用户终止读卡器进程(例如,通过退出
less
),原始进程将被终止。这可以节省大量无用的计算。“不返回”==块。如果您不读取重定向的输出,那么,是的,进程很可能会死锁。一个相当标准的bug是排出stdout而不是stderr。在所有3个句柄上都需要WaitForMultipleObjects()。@HansPassant如果进程退出,输出是否会关闭,这样您就可以只读取输出管道而不包括进程?你能把stderr留在控制台上,这样就不是你的问题了吗?@Random832:当然你能把
stderr
绑定到控制台流上。或者将
stdout
stderr
都连接到同一管道。感谢您提供的信息性答案。我还有一个问题:当我在为流程创建的所有管道上调用
CloseHandle
时,死锁是否仍然会发生,或者我是否可以安全地调用
WaitForSingleObject
?我想添加一个
Wait()
方法,该方法将简单地忽略进程生成的任何输出,但会阻止它,直到它终止。您是否询问CloseHandle是父进程还是子进程?这将防止死锁,但管道的另一端在父进程中尝试写入或零字节读取时将遇到错误。“子进程中的句柄”指的是我在
STARTUPINFO
结构中指定的句柄吗?假设子进程从标准输入读取数据,而我从父进程将其关闭,那么子进程是会遇到错误,还是只会在标准输入管道中读取任何内容(或剩余内容)?@NiklasR:如果管道的写入端关闭,则读取端将开始返回零长度读取。应将其识别为“文件结束”条件。