Linux IPC,带单写器、多读卡器

Linux IPC,带单写器、多读卡器,linux,sockets,client-server,ipc,datagram,Linux,Sockets,Client Server,Ipc,Datagram,在我的应用程序中,我有一个进程从外部硬件读取数据。此过程应向多个“读卡器”提供一致的数据包 问题: 一个进程如何向多个客户机发送一致的数据包(不阻塞),而这些客户机看到类似个人fifo结束的情况?我使用的是DebianLinux 1) 在我的第一种方法中,我尝试了“数据报-unix域套接字”,效果很好。 但使用“writer”作为服务器,所有客户端都必须永久轮询服务器:-( 他们多次收到一个数据包;如果轮询速度不够快,就会错过一个数据包 2) 我的第二种方法是FIFO(命名管道),它也能工作,但

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

问题: 一个进程如何向多个客户机发送一致的数据包(不阻塞),而这些客户机看到类似个人fifo结束的情况?我使用的是DebianLinux

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

2) 我的第二种方法是FIFO命名管道),它也能工作,但有几个读者“奇怪的事情发生了”,我在这里得到了证实:

我试了一整天,在网上搜索,但是我找不到一个合理的答案


编辑:对不起,我没有提到:我不能使用
socketpair()
fork
。我的程序是独立开发的。我希望在开发新的读卡器时,编写器准备就绪。

如果编写器进程是一个服务器,它可能会
分叉
客户端进程,只是为了通信。如果没有父/子关系,请考虑用“或”代码“AFXUNIX < /代码>套接字(参见和…))进行双向命名(<代码> AFSUIX套接字),比在同一台机器上的TCP/IP或UDP/IP快得多。
请注意,writer进程正在从硬件设备读取数据,并且正在向多个读卡器客户端写入或发送数据。因此,writer进程同时处理许多文件描述符(要读取的硬件设备和要写入客户端的套接字或管道,每个客户端至少有一个文件描述符)

然而,重要的是有一些(特别是在服务器端,也可能在客户端)。这意味着您可以像在循环中一样调用一些多路复用系统调用,并在每次迭代中“决定”您是在读、写还是在连接(以及应该读、应该写或应该连接哪个文件描述符)。另见、、等。。。请注意,您应该使用事件循环缓冲数据(因为
read
write
可能在“部分”或“不完整”消息上)

请注意,
poll
在等待I/O时不会占用CPU资源。您可以(但不应该)使用一些旧的多路复用系统调用(如过时的…)使用

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

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

你应该阅读并了解这本书

如果信号或计时器很重要(请仔细阅读,并且是Linux特有的),并且可能非常有用,因为它们可以很好地处理事件循环。这些特定于linux的系统调用(
signalfd
&
timerfd\u create
..)太新,在高级linux编程中无法提及

顺便说一句,您可以研究与您类似的现有自由软件的源代码,和/或使用它来了解它们正在进行的确切系统调用

如果在多路复用系统调用(a la)周围没有循环,那么就没有事件循环,并且您的设计有缺陷,不可能可靠地工作(因为您需要同时对多个文件描述符做出反应)


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

ZeroMQ有解决此问题的模式。速度快,支持多种编程语言。请参阅:(免费和开源)。

您应该有一个事件循环,因此应该使用多路复用系统调用,如
poll(2)
。你的链接没有提到这一点!在我的第一种方法中,我使用数据报套接字
AF\u UNIX
socket(AF\u UNIX,SOCK\u DGRAM,0)
。在第二种方法中,我使用带有
mknod的命名管道(FIFO_NAME,S_-IFIFO | 0666,0)但它们不能包含多个阅读器,请参阅相关链接。如果我理解你的答案,那就是你的建议。我不想轮询,而是获取一个事件(连接)或简单的比较fifo索引。事件循环不应该是问题所在。请稍等,我得了解一下您的信息。;-)您确实需要一个事件循环。这意味着你需要缓冲。。。另外,请花点时间关注我给你的所有网络链接……好的,你对事件循环的理解是绝对正确的;但在我的两种方法中,我都有某种事件循环。否则,例如,服务器将无法处理多个连接并同时收集外部数据。关键是我选择的IPC概念。我测试的两种方法(与您提到的相同)都不令人满意,因为它们产生的问题比它们解决的问题多。我认为一个作家,几个当地的IPC读者是一个普遍的问题。应该有一个通用的方法。显示您的代码,特别是您的事件循环。。。。我不明白你所说的IPC概念是什么意思。一个简单的
mkfifo()
-循环方法示例,你可以在这里找到[1]。但这不适用于多个阅读器,因此这是错误的IPC概念。[1] 准确地显示轮询(2)
(或您实现的任何事件循环)周围的循环。即使只有一个读卡器和多个写卡器通道,您也需要这样一个循环(当您处理多个文件描述符时,您就需要它)。在处理多个文件描述符(读、写或两者兼有,或连接)时,正确的“IPC概念”