Linux IPC:单一作家,多个读者 - 概念

时间:2014-01-02 17:54:35

标签: linux sockets client-server ipc datagram

在我的应用程序中,我有一个进程(“编写者”)从外部硬件读取数据。 此过程应向多个“读者”提供一致的数据包

问题: 一个进程如何在看到类似个人FIFO的结尾时向多个客户端发送一致的数据包(不阻塞)?我在Debian Linux上。


1)在我的第一种方法中,我尝试了“数据报 - unix域套接字”,效果很好。 但是使用“writer”作为服务器,所有客户端都必须永久轮询服务器。 :-( 他们多次得到一个包;如果没有足够快速地进行轮询,则会丢失数据包。

2)我的第二种方法是 FIFO 命名管道)也有效,但是有几位读者“发生了奇怪的事情”,我在这里得到了证实:{{ 3}}

我试过这个,整天搜索网络和stackoverflow,但我找不到合理的答案。

编辑:抱歉,我没有提及:我无法使用socketpair()fork。我的程序是独立开发的。我想在开发新读者的同时准备好作家

2 个答案:

答案 0 :(得分:1)

如果编写者进程是服务器,则可能fork客户端进行处理,并且只是pipe(2)进行通信。如果没有父/子关系,请考虑使用mkfifo(3)AF_UNIX套接字创建的命名管道(请参阅unix(7)scoket(2) ... 。)双向AF_UNIX套接字比同一台机器上的TCP / IP或UDP / IP快得多。)

请注意,您的编写器进程正在从您的硬件设备读取数据,并正在向多个 reader 客户端写入或发送数据。因此,您的编写器进程同时处理许多文件描述符(要读取的硬件设备,要写入客户端的套接字或管道,每个客户端至少有一个文件描述符)。

然而,重要的是有一些event loop (特别是在服务器端,也可能在客户端内)。这意味着您在循环中调用了一些多路复用系统调用,如poll(2),并且“决定”您是在读取还是正在写入或连接(以及应该读取哪个文件描述符,或者应该是在每次迭代中写入或应该连接。另请参阅read(2)write(2)connect(2)send(2)recv(2)等...请注意,您应该使用事件循环缓冲数据(自{{1 }和read可以是“部分”或“不完整”的消息。)

请注意,write在等待I / O时没有占用CPU资源。你可以,但你不应该再使用一些旧的多路复用系统调用(就像过时的select(2) ...)。 使用poll(2) 。功能

您可能希望使用库来提供事件循环,例如libeventlibev ...另见this answer。那个事件循环也应该(在服务器端)轮询然后读取硬件设备。

如果某些程序正在使用GUI工具包(例如在客户端),如Qt或Gtk,那么他们应该从该工具包提供的现有事件循环中获利......

您应该阅读Advanced Linux Programming 并了解C10K problem

如果信号或计时器很重要(仔细阅读 signal(7)time(7)),那么特定于Linux的signalfd(2)timerfd_create(2)可能会非常有用他们很好地使用事件循环。这些特定于Linux的系统调用(poll& signalfd ...)太新了,无法在高级Linux编程中提及。

顺便说一句,您可以研究与您类似的现有免费软件的源代码,和/或使用strace(1)来了解他们正在进行的确切系统调用。

如果您没有围绕多路复用系统调用(例如poll(2))的循环,那么您没有事件循环,并且您的设计存在错误,并且无法可靠且可靠地工作(因为您需要立即对几个文件描述符做出反应)。

您也可以使用多线程方法,但它更复杂,在您的特定情况下不值得付出努力。

答案 1 :(得分:0)

ZeroMQ具有解决此问题的模式。快速并且支持许多编程语言。 Pub-Sub。请参阅:https://zeromq.org/(免费和开源)。