Linux的消息队列有哪些缺点?

14

我正在开发一种用于在嵌入式Linux进程之间通信的消息队列。我想知道为什么不使用Linux提供的消息队列,比如:

msgctl、msgget、msgrcv和msgsnd。

而是创建共享内存,并与信号量进行同步?

直接在业务嵌入式产品上使用这组函数有什么缺点?


2
消息传递和共享内存是不同的编程范例。实际上,消息传递可能更容易编写代码。 - Basile Starynkevitch
5个回答

10

msgctl()msgget()msgrcv()msgsnd() 是“System V IPC”消息队列函数。虽然这些函数能够满足您的需求,但它们比较庞大。它们已经被POSIX标准化。

POSIX同样提供了一组更现代的函数,包括mq_close()mq_getattr()mq_notify()mq_open()mq_receive()mq_send()mq_setattr()mq_unlink(),对于您来说可能更好(这真是一个富裕的尴尬)。

但是,您需要检查默认情况下是否在目标平台上安装了其中任何一个。特别是在嵌入式系统中,您可能需要配置它们,甚至需要安装它们,因为它们不是默认安装的(共享内存和信号量也有同样的情况)。

使用这两组消息功能的主要优势在于它们已经经过预调试,因此并发问题已经得到解决 - 而如果您要自己使用共享内存和信号量来实现相同的功能,则需要做大量工作。

因此,尽可能地重复使用。 如果可以选择,使用其中一个消息队列系统而不是重新发明自己的。 如果最终发现存在性能瓶颈或类似问题,则可以调查编写自己的替代方案,但在那之前 — 重用!


但是为什么不直接使用套接字呢?它们也是经过预调试的,等等。当然,也许你想要AF_UNIX和SOCK_SEQPACKET类型的语义,但对我来说,套接字似乎更好。 - tchrist
@tchrist:您能详细说明为什么您认为套接字更好吗? - Gauthier

6

System V消息队列(由msg*系统调用操作的那些)有很多奇怪的缺陷和陷阱。对于新代码,我强烈建议使用UNIX域套接字。

话虽如此,我也强烈建议使用消息传递IPC而不是共享内存方案。共享内存更容易出错,并且往往会出现更严重的故障。


2

消息传递适用于小数据块和需要保持不变性的情况,因为消息队列会复制数据。

共享内存区域在发送/接收时不会复制数据,可以更有效地处理较大的数据集,但编程模型不太干净。


1
实际上,即使对于大数据块,仅使用共享内存也不是一个好主意。将数据存储在公共内存中,而不是使用信号量或互斥锁来访问该内存,使用IPC将是编程更少出错的好主意。 - theB
@theB:只是为了确保我理解,对于大数据,您仍然会使用shm,但不使用sem进行锁定?您会写入shm,然后传递IPC消息以宣布数据已准备好? - Gauthier

1
消息队列的缺点非常微小 - 一些系统调用和复制开销 - 对于大多数应用程序来说几乎可以忽略不计。而好处远远超过了这种开销。同步是自动的,它们可以以各种方式使用:阻塞、非阻塞,由于在Linux中消息队列类型被实现为文件描述符,因此甚至可以在select()调用中用于多路复用。在POSIX版本中,除非您有真正迫切的需要使用SYSV队列,否则您甚至可以自动生成线程或信号来处理队列项。最重要的是,它们已经完全调试好了。

0
消息队列和共享内存是不同的。选择使用哪种方式取决于程序员及其需求。在共享内存中,读写需要特别小心。进程应该被同步,所以执行顺序在共享内存中非常重要。在共享内存中,没有办法区分读取的值是新写入的值还是旧的值。也没有显式机制来等待。
消息队列和共享内存是不同的。选择使用哪种方式取决于程序员及其需求。在消息队列中,有预定义的函数使你的生活更加轻松。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接