【问题标题】:Crossplatform Bidirectional IPC跨平台双向 IPC
【发布时间】:2010-09-20 05:36:16
【问题描述】:

我有一个项目,我认为这会相对容易,但结果却比我希望的更痛苦。首先,我与之交互的大部分代码都是我无法控制的遗留代码,因此我无法进行大的范式更改。

下面是对我需要做的事情的简化说明:假设我有大量从标准输入读取并写入标准输出的简单程序。 (这些我不能碰)。基本上,标准输入的输入是“将温度设置为 100”之类的命令或类似的命令。并且输出是一个事件“温度已设置为 100”或“温度已降至设定值以下”。

我想做的是编写一个应用程序,它可以启动一堆这些简单的程序,监视事件,然后根据需要向它们发送命令。我最初的计划是使用类似 popen 的东西,但我需要一个双向的 popen 来获得读写管道。我一起破解了一些我称之为popen2的东西,在那里我将运行命令和两个填充了读写流的FILE *传递给它。然后我需要做的就是编写一个简单的循环,从每个进程的每个标准输出中读取,执行它需要的逻辑,然后将命令写回正确的进程。

这是一些伪代码

FILE *p1read, *p1write;
FILE *p2read, *p2write;
FILE *p3read, *p3write;

//start each command, attach to stdin and stdout
popen2("process1",&p1read,&p1write);
popen2("process2",&p2read,&p2write);
popen2("process3",&p3read,&p3write);

while (1)
{
   //read status from each process
   char status1[1024];
   char status2[1024];
   char status3[1024];
   fread(status1,1024,p1read);
   fread(status2,1024,p2read);
   fread(status3,1024,p3read);

   char command1[1024];
   char command2[1024];
   char command3[1024];
   //do some logic here

   //write command back to each process
   fwrite(command1,p1write);
   fwrite(command2,p2write);
   fwrite(command3,p3write);
}

真正的程序更复杂,它在流中查看是否有任何东西在等待,如果没有,它将跳过该进程,同样,如果它不需要向某个进程发送命令,它就不需要.但是这段代码给出了基本的想法。

现在这在我的 UNIX 机器上工作得很好,甚至在带有 cygwin 的 Windows XP 机器上也很好。但是,现在我需要让它在本地运行在 Win32 上。

困难的部分是我的 popen2 使用 fork() 和 execl() 来启动进程并将流分配给子进程的标准输入和标准输出。有没有一种干净的方法可以在 Windows 中做到这一点?基本上,我想创建一个popen2,它在windows 中的工作方式与我的unix 版本相同。这样,唯一特定于 Windows 的代码将在该函数中,我可以摆脱其他一切以相同方式工作的情况。

有什么想法吗?

谢谢!

【问题讨论】:

    标签: c++ c winapi ipc pipe


    【解决方案1】:

    在 Windows 上,首先调用 CreatePipe(类似于 pipe(2)),然后是 CreateProcess。这里的技巧是 CreateProcess 有一个参数,您可以在其中传递新创建的进程的 stdin、stdout、stderr。

    请注意,当您使用 stdio 时,您需要在之后执行 fdopen 来创建文件对象,该对象需要文件编号。在 Microsoft CRT 中,文件编号与 OS 文件句柄不同。所以要将 CreatePipe 的另一端返回给调用者,首先需要 _open_osfhandle 获取 CRT 文件号,然后 fdopen 就可以了。

    如果您想查看工作代码,请查看 _PyPopen in

    http://svn.python.org/view/python/trunk/Modules/posixmodule.c?view=markup

    【讨论】:

      【解决方案2】:

      我认为您已经通过使用 popen2() 函数抽象出跨平台问题来解决您的问题。我期待来建议“套接字”,但我确信在阅读了这个问题后这并不相关。您可以使用套接字而不是管道 - 它会隐藏在 popen2() 函数中。

      我 99% 确信您可以使用 Windows API 在 Windows 上实现所需的功能。我不能做的是可靠地为您指出正确的功能。但是,您应该知道 Microsoft 提供了大多数类似 POSIX 的 API 调用,但名称以“_”为前缀。还有原生API调用实现forkexec的效果。

      您的 cmets 建议您了解数据可用性问题和可能的死锁 - 请谨慎。

      【讨论】:

      • 在 WIN32 中没有可用的 fork() 机制,尽管 Interix 产品显然支持它。
      • Cygwin 也是如此。我知道存在问题和困难 - 因此黄鼠狼的话“实现了 fork 和 exec 的效果”。
      猜你喜欢
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 2015-12-04
      • 2011-10-18
      • 2012-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多