Windows:具有重定向输入和输出的子进程

Posted

技术标签:

【中文标题】Windows:具有重定向输入和输出的子进程【英文标题】:Windows: Child Process with Redirected Input and Output 【发布时间】:2011-04-12 22:51:34 【问题描述】:

我正在尝试创建一个具有重定向输入和输出的子进程(如此处所述 - http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx)。

对于不想费心阅读该页面上的源代码的人,作者正在使用匿名管道来重定向孩子的输入和输出。父进程写入子进程的输入并从子进程的输出中读取。

然而,在该代码中,程序在读取和写入后关闭管道(在 WriteToPipe 和 ReadFromPipe 中),因此实际上程序只是读取一个文件,将其转储到子进程输入流中,然后读取子进程响应。

现在,我正在寻找的代码是我们不会关闭管道,但我们会不断发布请求并读取子进程响应(与仅发出 1 个请求相反)。

我已经尝试对上面发布的链接中给出的源代码进行多次修改,但无论我尝试什么,在 ReadFromPipe() 函数中调用 ReadFile() 时程序总是挂起(它可能等待孩子退出 - 但正如我所说,我喜欢得到孩子的回应,然后向它发送其他请求)。

关于如何克服这个问题的任何想法?

更新:

谁能告诉我使用带有RedirectStandardInputRedirectStandardOutput 的.NET Process 类是否是一个不错的选择?

【问题讨论】:

示例代码和文档似乎表明您必须关闭写句柄以防止 ReadFile() 挂起。我想我以前做过类似的事情,但那是很久以前的事了,我不记得细节了。 @Luke 说得对,具体来说,写句柄的所有副本都必须关闭,要么通过CloseHandle() 显式关闭,要么通过进程退出隐式关闭。 【参考方案1】:

是的 - 如果您使用 RedirectStandardInputRedirectStandardOutput,.Net Process 类使用匿名管道以与链接示例非常相似的方式重定向子进程的标准输入/输出,所以这可能是一个相当好的选项。

至于为什么ReadFile 挂起 - 听起来这个函数正在等待子进程发回一些数据,或者关闭管道。如果您想不断地向子进程发布请求,那么您需要:

准确了解何时适合读取,这样您就不会等待/阻塞子进程(例如,您只能在发送请求后立即读取)。这种策略非常冒险,因为子进程总是有可能无法按预期运行,而您将无限期地等待子进程。

有一个专用线程用于读取 - 如果您有一个专用线程用于读取,那么线程可能无限期地等待子进程并不重要,因为您的其他线程仍在能够发送请求并正常运行。这种方法比第一种方法更复杂,但是如果操作得当,它会更加健壮。这种方法的唯一另一个缺点是,它要求您为每个子进程都有一个额外的读取线程,这意味着如果您需要与大量子进程通信,它的扩展性就不是很好。

李>

使用异步 IO - 可以以始终立即返回的方式调用 ReadFile 函数,但是会在读取完成时通知您(我是因为我更习惯于 C#,所以关于它如何工作的确切细节有点模糊)。这被称为Asynchronous IO,是这三种方法中最通用的一种,因为它允许您与许多子进程进行通信,而无需为每个子进程分配一个专用线程。然而,权衡是它也是最复杂的正确操作(至少在我看来)。

【讨论】:

【参考方案2】:

遇到了完全相同的问题,并通过使用PeekNamedPipe(根据 MSDN 也适用于匿名读取管道)在每次调用 ReadFile 之前检查可用数据来解决它。这消除了我遇到的阻塞问题,并允许我的 GetExitCodeProcess() 看到进程已退出并清理管道。

【讨论】:

以上是关于Windows:具有重定向输入和输出的子进程的主要内容,如果未能解决你的问题,请参考以下文章

获取 node.js 中所有嵌套子进程的标准输出

c shell 输入重定向保持打开状态

使用重定向输入和输出的 C++ 进程间通信不适用于发布版本

如何处理 C++ 重定向进程的输出

Linux文件编辑器vim输出输入重定向管道以及进程

如何重定向 fork() 创建的子进程的 IO 并使用 exec() 函数?