跨平台双向IPC

mik*_*ked 3 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);
}
Run Code Online (Sandbox Code Playgroud)

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

现在这在我的UNIX机器上运行得很好,甚至在带有cygwin的Windows XP机箱上也很不错.但是,现在我需要让它在本机上运行Win32.

困难的部分是我的popen2使用fork()和execl()来启动进程并将流分配给子进程的stdin和stdout.有没有一种干净的方式我可以在Windows中做到这一点?基本上,我想在windows中创建一个与我的unix版本相同的popen2.这样,唯一的Windows特定代码将在该函数中,并且我可以以相同的方式处理其他所有工作.

有任何想法吗?

谢谢!

Mar*_*wis 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