Bash 脚本和 C++ 之间的持久 IPC;
问题: 有一个 C 应用程序,每次事件发生时都会调用 Bash 脚本。还有一个C++ 应用程序需要跟踪这些事件。 C++ 应用程序 由 select() 事件循环驱动。在 Bash 脚本 和 C++ 应用程序 之间实现的最简单的 IPC 是什么?
C Application ---Each time calls Bash script---> Bash application ---???---> C++ Application
我想到的解决方案很少:
- 使用 TCP 网络套接字,但这意味着 select 必须处理侦听套接字和实际套接字的事件
- 使用命名管道,但一旦 bash 脚本终止,管道的另一端就是也已关闭
有没有更简单的方法可以让我在 select() 中仅使用一个文件描述符?
Problem:
There is a C application that calls a Bash script each time an event happens. And there is also a C++ application that needs to track down those events. The C++ application is driven by a select() event loop. What would be the most simplest IPC to implement between Bash script and C++ application?
C Application ---Each time calls Bash script---> Bash application ---???---> C++ Application
Few solutions that came into my mind:
- To use TCP networking sockets, but this would mean that select will have to handle events for both Listening and Actual sockets
- To use Named pipes, but once the bash script terminates then the other end of the pipe is closed as well
Is there something simpler that would allow me to use only one File Descriptor in select()?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用轻量级消息队列,例如 ZeroMQ。我认为你会使用它的推拉机制。您的 C 程序或 bash 脚本推送事件,而 C++ 应用程序拉取事件。 ZeroMQ 是用 C 语言编写的,但除了许多其他语言之外,还存在 C++ 和 Python 绑定。有关推拉示例,请参阅此处。
You could use a lightweight messaging queue like ZeroMQ. I think you would use its PUSH-PULL mechanism. Your C program or the bash script pushes events while the C++ application pulls them. ZeroMQ is written in C but, besides many others, there exists a C++ and a Python binding for it. See here for a PUSH-PULL example.
Unix 数据报 或 UDP 套接字即可。 bash 脚本只会向该套接字发送一个数据报(您可能需要一个在该套接字上执行
sendmsg()
或sendto()
的帮助程序,例如 socat 或 netcat/nc)。接收方不需要接受数据报套接字的连接,一旦准备好读取,就必须有一个数据报在等待。受数据报长度限制。Unix datagram or UDP socket would do. The bash script would just send a datagram to that socket (you may need a helper program that does
sendmsg()
orsendto()
on that socket, such as socat or netcat/nc). The receiver does not need to accept connections for datagram sockets, once it is ready for read there must be a datagram waiting. Subject to datagram length restrictions.我会使用未命名的
pipe()
来完成此操作。请记住:在 UNIX 中,文件描述符在两个进程中的fork()
和execve()
之后保持打开状态!因此,您可以使用pipe()
获取一对文件描述符,然后使用 bash 的echo >&FD
写入 fd,其中FD
是文件描述符编号。这非常简单、简单,并且比我想象的任何其他方法都使用更少的资源。使用
select()
没有问题,只是不要在read()
上阻塞,这是我在示例中所做的,但在select()
上pfds[0]
。示例程序(生成 10 个 bash 进程,这些进程发送“hello work,我的 pid:XXX”,在生成进程之间等待 1 秒。该示例仅对所有子进程使用一个管道。我这样更改了它,因为作者询问了这一点。在实践中,我不推荐它(参见示例下面的注释)):
示例程序输出:
有效,bashs使用一个管道向父进程发送“hello world,我的pid:XXX \ n” :-)。
尽管如此,这似乎可以像演示程序所示那样工作(使用 POSIX 语义应该没问题,并且在 Linux 和 MacOS X 下进行了测试),我建议每个子进程使用一个
pipe()
。这将减少问题,并且一次运行多个子进程也是可能的。select()
或epoll()
(如果你有很多子进程)是你的朋友。由于
pipe()
非常便宜,特别是与 bash! 相比,我绝对不会为多个子级使用同一个管道(正如我更新的示例现在所做的那样)。I would do it with a unnamed
pipe()
. Remember: In UNIX file descriptors remain open afterfork()
andexecve()
in both processes! So you can usepipe()
to get a pair of file descriptors and then write into the fd using bash'secho >&FD
whereFD
is the file descriptor number.That is very straight forward, easy and uses less resources than anything else I assume. The use of
select()
is no problem, just do not block onread()
is I do in my sample butselect()
onpfds[0]
.Sample program (spawns 10 bash processes which send 'hello work, my pid: XXX', waiting 1s between spawning the processes. The sample only uses one pipe for all the children. I changed it that way because the author asked about that. In practice, I would NOT recommend it (see the note below the sample)):
sample program output:
works, bashs send 'hello world, my pid: XXX\n' to parent process all using one pipe :-).
Nevertheless that seems to work as the demo program shows (should be ok using the POSIX semantics and tested under Linux and MacOS X), I would recommend using one
pipe()
per child process. That will lead to fewer problems and running more than one child process at a time is possible, too.select()
orepoll()
(if you have MANY child processes) are your friend.Since
pipe()
is very cheap, in particular compared to bash!, I would definitely not use the same pipe for more than more than one child (as my updated sample now does).