Linux的消息队列有啥缺点?
Posted
技术标签:
【中文标题】Linux的消息队列有啥缺点?【英文标题】:What are the disadvantages of Linux's message queues?Linux的消息队列有什么缺点? 【发布时间】:2012-03-22 16:51:26 【问题描述】:我正在研究用于嵌入式 Linux 上的进程之间通信的消息队列。我想知道为什么我不使用 Linux 提供的消息队列如下:
msgctl, msgget msgrcv, msgsnd.
不是创建共享内存,而是与信号量同步?
直接在商业嵌入式产品上使用这组功能有什么缺点?
【问题讨论】:
消息传递和共享内存是不同的编程范式。事实上,消息传递可能更容易编码。 【参考方案1】:函数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:请详细说明为什么套接字对您来说更好?【参考方案2】:System V 消息队列(由 msg* 系统调用操纵的队列)有很多奇怪的怪癖和陷阱。对于新代码,我强烈建议使用 UNIX 域套接字。
话虽如此,我也强烈建议通过共享内存方案传递消息的 IPC。共享内存更容易出错,而且更容易出错。
【讨论】:
【参考方案3】:消息传递非常适合小数据块和需要保持不变性的地方,因为消息队列复制数据。
共享内存区域不会在发送/接收时复制数据,并且可以更有效地处理更大的数据集,但要以不太干净的编程模型为代价。
【讨论】:
实际上即使对于大数据块,单独共享内存也不是一个好主意。将数据存储在公共内存中,而不是使用信号量或互斥量来访问该内存,使用 ipc 将是减少容易出错的编程的好主意。 @theB:只是为了确保我理解,对于大数据,您仍然会使用shm
,但不会使用sem
锁定它?你会写信给shm
,然后传递一个ipc消息来宣布数据准备好了?【参考方案4】:
消息队列的缺点是微不足道的 - 一些系统调用和复制开销 - 这对大多数应用程序来说都不算什么。好处远远超过了开销。同步是自动的,它们可以以多种方式使用:阻塞、非阻塞,并且由于在 linux 中消息队列类型是作为文件描述符实现的,它们甚至可以用于select()
多路复用调用。在 POSIX 变体中,除非您非常迫切地需要使用 SYSV 队列,否则您应该使用它,您甚至可以自动生成线程或信号来处理队列项。最重要的是,它们已经过全面调试。
【讨论】:
【参考方案5】:消息队列和共享内存是不同的。选择使用哪个取决于程序员和他的要求。在共享内存中,您必须小心阅读和写作。并且这些过程应该是同步的。所以执行顺序在共享内存中非常重要。在共享内存中,无法找到读取的值是新写入的值还是旧的值。而且没有明确的等待机制。
消息队列和共享内存是不同的。选择使用哪个取决于程序员和他的要求。有预定义的功能可以让您在消息队列中轻松生活。
【讨论】:
以上是关于Linux的消息队列有啥缺点?的主要内容,如果未能解决你的问题,请参考以下文章