跨平台双向IPC

时间:2008-10-31 17:03:17

标签: c++ c winapi ipc pipe

我有一个我认为相对容易的项目,但结果却变成了我所希望的更多痛苦。首先,我正在与之交互的大多数代码都是我无法控制的遗留代码,所以我无法进行大范式更改。

这是我需要做的简化说明:假设我有大量从stdin读取并写入stdout的简单程序。 (这些我无法触及)。基本上,输入到stdin是一个命令,如“将温度设置为100”或类似的命令。输出是“温度已设置为100”或“温度低于设定值”的事件。

我想做的是编写一个应用程序,可以启动一堆这些简单的程序,监视事件,然后根据需要向它们发送命令。我最初的计划是像popen这样的东西,但我需要一个双向的popen来获取读写管道。我一起攻击了一些我称之为popen2的东西,我将命令传递给它,两个FILE *充满了读写流。然后我需要做的就是编写一个简单的循环,从每个进程的每个stdouts读取,执行它需要的逻辑,然后将命令写回正确的进程。

这是一些伪代码

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()来启动进程并将流分配给子进程的stdin和stdout。有没有一种干净的方式我可以在Windows中做到这一点?基本上,我想在windows中创建一个与我的unix版本相同的popen2。这样,唯一的Windows特定代码将在该函数中,并且我可以以相同的方式处理其他所有内容。

任何想法?

谢谢!

2 个答案:

答案 0 :(得分:5)

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

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

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

中的_PyPopen

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

答案 1 :(得分:0)

我认为你通过使用popen2()函数来抽象出跨平台问题,从而为你的问题做了一个很好的开端。我本来期待提出“套接字”,但我确信在阅读问题之后这并不重要。您可以使用套接字而不是管道 - 它将隐藏在popen2()函数中。

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

您的意见表明您了解数据可用性和可能的​​死锁问题 - 请谨慎。