标准输出(stdout)是否有缓冲区大小限制?

12

我正在尝试查找与Windows上的标准输出数据限制相关的信息,但在MSDN上似乎找不到这些信息。

  1. 是否存在可以写入标准输出的数据量限制?如果有,那么当达到限制时会发生什么?数据会丢失吗?

  2. 如果标准输出被重定向(例如通过从.Net启动进程并使用ProcessStartInfo.RedirectStandardOutput属性),那么这是否会影响可以写入的数据量?当我从调用进程中读取标准输出流时,这是否会影响限制?

  3. 这些限制是否与命名管道有任何关系?

3个回答

19

这取决于它要去哪里 - 但是在.NET中重定向输出时,如果您不读取输出,可能会遇到问题。当缓冲区耗尽时,子进程中对stdout的写入将会阻塞。一个常见的死锁原因是"父"进程等待"子"进程退出,然后读取输出 - 如果子进程需要父进程读取输出来释放缓冲区空间,则此方法不起作用。

.NET通过使用Process.OutputDataReceivedProcess.ErrorDataReceived允许事件驱动方法,从而使此过程略微简化。这意味着您不需要启动两个线程(一个用于读取stdout,另一个用于读取stderr)只是为了防止进程阻塞...


1
这比我发布的要有用得多。删除我的帖子并投票支持你。 - David
现在这是一个非常方便的功能。我想知道Java将来是否会添加类似的东西。 - Michael Myers
(+1) 从.NET的角度来看,这可能更有用,因为我相信所做的决定是为了简化程序员的工作——尽管在C语言中,默认情况下stdout也非常简单。 - Hassan Syed
酷,谢谢!在Win32环境中是一样的吗?例如,如果我从命令行运行“process1.exe | process2.exe”,那么process1将能够写入标准输出,直到缓冲区已满,然后将阻塞,直到process2读取了足够的数据,以便它可以再次写入?我在MSDN上没有看到任何关于此的信息。有没有可用的缓冲区大小等信息? - jameswelle
当使用System.Diagnostics.Process启动子进程并重定向stderr和stdout时,我们如何在PowerShell中使用它? - Adarsha
@Adarsha:重定向在什么方面?你尝试过直接使用那些成员,调用 BeginOutputReadLineBeginErrorReadLine 来启动进程吗?我不知道 PowerShell 会有什么区别。如果这样做不起作用,我建议你用 [mcve] 提出一个新问题。 - Jon Skeet

4

需要注意以下几点:

1) Jon是对的 - 如果缓冲区限制已达到,子进程中的写入调用将会阻塞。如果stdout流没有被重定向到可以自动排空的位置(例如文件),则需要排空stdout流。管道需要排空,通常,如果您可以“附加”到子进程的输出,则正在附加到管道。

2) 输出流的I/O 可能 是带有缓冲的,这意味着如果子进程在没有显式调用flush()的情况下将一些信息写入stdout,您可能看不到输出。当进程退出时,将自动调用Flush,因此,如果它是一个短小的子进程,则应该没问题,但如果不是,则没有真正的方法可以强制其输出显示出来。

3) 命名管道本质上是操作系统维护的缓冲区,可以从中写入和读取 - 也就是说,它们像是一个文件,您可以从一个进程中写入并从另一个进程中读取,而实际上并没有磁盘上的文件开销。非常适用于进程间通信,但所有与缓冲/满缓冲的I/O限制仍然适用。


3

标准输出有一个1024字节的缓冲区


7
这个断言有来源吗? - Zero3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接