English 中文(简体)
跨平台双向IPC
原标题:
  • 时间:2008-10-31 17:03:17
  •  标签:

我有个项目,我本来以为这会是相对容易的事情,但实际上它正在变得比我预想的更加麻烦。首先,我与之互动的大部分代码都是老代码,我无法控制,因此我不能进行大范式的更改。

这是我需要做的简化说明:假设我有很多简单的程序,它们从 stdin 读取并写入 stdout。(这些程序我不能动)。基本上,stdin 的输入是一个命令,比如“把温度设置为 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()来启动进程,并将流分配给子进程的stdin和stdout。在Windows中有没有一种干净的方式可以做到这一点?基本上,我想创建一个在Windows中与我的unix版本相同的popen2。这样,唯一的Windows特定代码将位于该函数中,我可以摆脱其他所有东西都以相同的方式工作的情况。

任何想法?

谢谢!

最佳回答

在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 http://svn.python.org/view/python/trunk/Modules/posixmodule.c?view=markup

问题回答

我认为你通过使用popen2()函数抽象掉跨平台问题已经有了非常好的开端。我原本打算建议使用套接字,但看完问题后我确信那已不再相关。你可以使用套接字而不是管道 - 它会被隐藏在popen2()函数中。

我百分之九十九确定,在Windows上使用Windows API可以实现所需的功能。 我无法可靠地指向正确的函数。 但是,您应该知道微软拥有大多数类似于POSIX的API调用,但名称带有前缀_。 还有本地API调用,可以实现 fork exec 的效果。

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





相关问题