跨平台双向进程间通信(IPC)

3
我本以为这个项目会相对简单,但现在它变得比我想象的更加困难。首先,我要处理的大部分代码都是老式代码,我没有控制权,因此无法进行重大范式更改。
以下是我需要做的简化说明:假设我有大量简单的程序,可以从stdin读取并写入stdout(这些我无法更改)。基本上,输入到stdin的命令类似于“将温度设置为100”之类的命令。输出是一个事件,“温度已设置为100”或“温度低于设定点”。
我想编写一个应用程序,可以启动一堆这些简单程序,监视事件,然后根据需要向它们发送命令。我的初始计划是使用类似popen的东西,但我需要一个双向的popen来获取读和写管道。我拼凑了一些东西,称之为popen2,其中我传递要运行的命令和两个FILE*,它们会填充读取和写入流。然后,我只需要编写一个简单的循环,从每个进程的stdout中读取数据,执行所需的逻辑,然后将命令写回正确的进程。
以下是一些伪代码。
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个回答

6
在Windows上,您首先调用CreatePipe(类似于pipe(2)),然后调用CreateProcess。这里的诀窍是CreateProcess有一个参数,您可以通过它传递新创建进程的stdin,stdout和stderr。
请注意,当您使用stdio时,需要使用fdopen创建文件对象,该对象期望文件号。在Microsoft CRT中,文件号不同于操作系统文件句柄。因此,要将CreatePipe的另一端返回给调用者,您首先需要使用_open_osfhandle获取CRT文件号,然后在其上fdopen。
如果您想查看工作代码,请查看_PyPopen。

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


0

我认为你通过使用popen2()函数来抽象掉跨平台问题已经很好地开始了你的问题。在阅读问题后,我本来想建议使用“套接字”,但我相信这并不相关。你可以使用套接字代替管道——它将被隐藏在popen2()函数中。

我99%确定你可以使用Windows API在Windows上实现所需的功能。我无法可靠地指向正确的函数。然而,你应该知道Microsoft有大多数类似POSIX的API调用可用,但名称前缀为“_”。还有本地API调用可以实现fork和exec的效果。

你的评论表明你意识到数据可用性和可能的死锁问题——要谨慎。


WIN32中没有可用的fork()机制,尽管Interix产品显然支持它。 - Chris K
Cygwin也是如此。我知道存在问题和困难,因此使用了“实现fork和exec效果”的含糊词语。 - Jonathan Leffler

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