【问题标题】:Unbuffered CreateNamedPipe for use as stdout for CreateProcess用作 CreateProcess 的标准输出的无缓冲 CreateNamedPipe
【发布时间】:2010-12-06 20:47:55
【问题描述】:
我想执行任意命令行应用程序并在其生成时读取其标准输出。我使用CreateNamedPipe 创建一个管道,然后将另一端(打开使用的CreateFile)提供给CreateProcess。如果目标进程没有显式地使用标准输出缓冲进行操作,有没有办法确保有问题的管道没有缓冲,或者至少系统最小值用作缓冲大小?
【问题讨论】:
标签:
winapi
pipe
named-pipes
createprocess
output-buffering
【解决方案1】:
您无法真正控制缓冲区大小。您可以将读取和写入缓冲区大小 1 传递给CreateNamedPipe,但内核会自动增加这些缓冲区大小。基本上,缓冲区将始终至少与在任何给定时间已准备好读取的最大数据量一样大。换句话说,您对可用数据的响应越快,写入管道的数据块越小,保留的缓冲区就越小。
输入和输出缓冲区大小是建议性的。为命名管道的每一端保留的实际缓冲区大小是系统默认值、系统最小值或最大值,或者是向上舍入到下一个分配边界的指定大小。 ...每当发生管道写入操作时,系统首先尝试根据管道写入配额对内存进行收费。 ... 如果剩余管道写入配额太小而无法满足请求,系统将尝试使用为进程保留的非分页池来扩展缓冲区以容纳数据。
但是,我不认为缓冲区大小真的很重要。在缓冲区“满”之前,管道不会延迟数据的发送,并且没有什么相当于 TCP 的“nagle”选项,因此保持较小的缓冲区大小不会改善您的延迟。
请记住,当您将管道连接到控制台应用程序的stdout 时,输出通常由该应用程序缓冲在写入管道之前。如果您想要无缓冲的输出,则需要使用 stderr。
另外,使用继承的管道句柄时要注意的一点是,生成的应用程序将继承你所有的句柄,所以如果你打开了一个文件或套接字,你生成一个应用程序,然后关闭该句柄,文件/插座/等。将保持打开状态,直到生成的子进程停止,这可能导致意外的共享冲突和其他奇怪的问题。