3

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

这是我需要做的简单解释:假设我有大量从标准输入读取并写入标准输出的简单程序。(这些我不能碰)。基本上,标准输入的输入是“将温度设置为 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 特定代码将在该函数中,我可以摆脱其他一切以相同方式工作的情况。

有任何想法吗?

谢谢!

4

2 回答 2

6

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

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

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

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

于 2008-10-31T17:52:15.053 回答
0

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

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

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

于 2008-10-31T17:22:56.440 回答