跨平台双向IPC

发布于 2024-07-07 11:30:39 字数 1597 浏览 5 评论 0原文

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

这是我需要做的事情的简化解释:假设我有大量从标准输入读取并写入标准输出的简单程序。 (这些我不能碰)。 基本上,标准输入的输入是“将温度设置为 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 中做到这一点? 基本上,我想创建一个popen2,它在Windows 中的工作方式与我的unix 版本相同。 这样,唯一的 Windows 特定代码将在该函数中,并且我可以摆脱其他所有事情以相同的方式工作。

有任何想法吗?

谢谢!

I have a project that I thought was going to be relatively easy, but is turning out to be more of a pain that I had hoped. First, most of the code I'm interacting with is legacy code that I don't have control over, so I can't do big paradigm changes.

Here's a simplified explanation of what I need to do: Say I have a large number of simple programs that read from stdin and write to stdout. (These I can't touch). Basically, input to stdin is a command like "Set temperature to 100" or something like that. And the output is an event "Temperature has been set to 100" or "Temperature has fallen below setpoint".

What I'd like to do is write an application that can start a bunch of these simple programs, watch for events and then send commands to them as necessary. My initial plan was to something like popen, but I need a bidrectional popen to get both read and write pipes. I hacked something together that I call popen2 where I pass it the command to run and two FILE* that get filled with the read and write stream. Then all I need to do is write a simple loop that reads from each of the stdouts from each of the processes, does the logic that it needs and then writes commands back to the proper process.

Here's some pseudocode

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);
}

The real program is more complicated where it peeks in the stream to see if anything is waiting, if not, it will skip that process, likewise if it doesn't need to send a command to a certain process it doesn't. But this code gives the basic idea.

Now this works great on my UNIX box and even pretty good on a Windows XP box with cygwin. However, now I need to get it to work on Win32 natively.

The hard part is that my popen2 uses fork() and execl() to start the process and assign the streams to stdin and stdout of the child processes. Is there a clean way I can do this in windows? Basically, I'd like to create a popen2 that works in windows the same way as my unix version. This way the only windows specific code would be in that function and I could get away with everything else working the same way.

Any Ideas?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

抚笙 2024-07-14 11:30:39

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

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

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

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

On Windows, you invoke CreatePipe first (similar to pipe(2)), then CreateProcess. The trick here is that CreateProcess has a parameter where you can pass stdin, stdout, stderr of the newly-created process.

Notice that when you use stdio, you need to do fdopen to create the file object afterwards, which expects file numbers. In the Microsoft CRT, file numbers are different from OS file handles. So to return the other end of CreatePipe to the caller, you first need _open_osfhandle to get a CRT file number, and then fdopen on that.

If you want to see working code, check out _PyPopen in

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

分分钟 2024-07-14 11:30:39

我认为通过使用 popen2() 函数抽象出跨平台问题,您已经很好地解决了您的问题。 我本来希望过来建议“套接字”,但我确信在阅读问题后这并不相关。 您可以使用套接字代替管道 - 它将隐藏在 popen2() 函数中。

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

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

I think you've made a very good start to your problem by using the popen2() function to abstract away the cross-platform issues. I was expecting to come and suggest 'sockets', but I'm sure that's not relevant after reading the question. You could use sockets instead of pipes - it would be hidden in the popen2() function.

I am 99% sure you can implement the required functionality on Windows, using Windows APIs. What I cannot do is point you to the right functions reliably. However, you should be aware the Microsoft has most of the POSIX-like API calls available, but the name is prefixed with '_'. There are also native API calls that achieve the effects of fork and exec.

Your comments suggest that you are aware of issues with availability of data and possible deadlocks - be cautious.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文