消息队列在Linux中过时了吗?


71

我最近在Linux中一直在使用消息队列(系统V,但是POSIX也可以),它们对于我的应用程序似乎很完美,但是在阅读了《 Unix编程的艺术》之后,我不确定它们是否真的是一个不错的选择。

http://www.faqs.org/docs/artu/ch07s02.html#id2922148

System V IPC的上层消息传递层已大大停用。在需要执行互斥锁定和在同一台计算机上运行的进程之间进行一些全局数据共享的情况下,由共享内存和信号量组成的较低层仍然具有重要的应用程序。这些System V共享内存功能演变为POSIX共享内存API,在Linux,BSD,MacOS X和Windows下受支持,但经典MacOS不支持。

http://www.faqs.org/docs/artu/ch07s03.html#id2923376

Linux和其他现代Unix中都有System V IPC功能。但是,由于它们是传统功能,因此并不经常使用。到2003年中期为止,Linux版本仍存在错误。似乎没有人足够在意修复它们。

在最新的Linux版本中,System V消息队列是否仍然存在错误?我不确定作者是否认为POSIX消息队列应该正常吗?

似乎套接字是几乎所有对象(?)的首选IPC,但是我看不到用套接字或其他方法实现消息队列是多么简单。还是我想得太复杂了?

我不知道与嵌入式Linux合作是否有意义?

Answers:


80

我个人非常喜欢消息队列,并认为它们可以说是unix世界中使用率最低的IPC。它们快速且易于使用。

一些想法:

  • 其中一些只是时尚。旧事物再次变得新。在消息队列上添加一个闪亮的爸爸,它们可能是明年的最新和最热门的事情。使用单独的进程而不是其标签的线程来查看Google的Chrome。突然,人们为一个选项卡锁定而无法关闭整个浏览器而感到兴奋。

  • 共享内存对此有些犹豫。如果您没有挤掉机器的最后一个循环,并且MQ的效率略低,那么您不是一个“真正的”程序员。对于许多(即使不是大多数)应用程序来说,这完全是胡说八道,但有时一旦掌握就很难打破思维定势。

  • MQ确实不适用于具有无限制数据的应用程序。面向流的机制(例如管道或套接字)更容易使用。

  • System V变体的确不受欢迎。通常,请尽可能使用POSIX版本的IPC。


2
7年后..希望这不是太多是还是有点相关:我想知道的消息队列的默认设置Ubuntu 14.04linux 3.13cat /proc/sys/fs/mqueue/msg_max表10(在队列中的消息)和/proc/sys/fs/mqueue/msgsize_max8192(字节) -他们是奇怪的小。这些默认值是否存在严格的原因,或者它们太旧了?(man mq_overviewmsg_max的硬限制约为32768,这是很高的。)我不是要创建像流一样的无限队列,但是100-1000可以msg_max吗?
xealits '16

2
有点晚了,但是:当我使用POSIX队列时,我的队列中有5-100条消息,并且没有遇到问题@xealits
Xunnamius,

14

是的,我认为消息队列适合某些应用程序。POSIX消息队列提供了一个更好的接口,特别是,您可以给队列指定名称而不是ID,这对于故障诊断非常有用(可以更轻松地查看哪个是哪个)。

Linux允许您将posix消息队列挂载为文件系统,并使用“ ls”查看它们,并使用“ rm”删除它们,这也非常方便(系统V取决于笨拙的“ ipcs”和“ ipcrm”命令)


此功能也可用于UNIX Datagram套接字。我可以将数据报套接字绑定到文件并以与POSIX消息队列相同的方式接收。我什netcat至可以用来将测试数据发送到数据报套接字文件。
舒瓦

12

我实际上没有使用过POSIX消息队列,因为我一直想保持打开状态以在网络上分发消息。考虑到这一点,您可能会看到更健壮的消息传递接口,例如zeromq或实现AMQP的接口。

关于0mq的好处之一是,当在多线程应用程序的相同进程空间中使用它时,它使用了非常快的无锁零复制机制。不过,您也可以使用相同的接口通过网络传递消息。


7

POSIX消息队列的最大缺点:

  • POSIX消息队列并不要求与兼容select()。(它select()在Linux中可用,但在Qnx系统中不可用)
  • 令人惊讶。

Unix数据报套接字执行POSIX消息队列的相同任务。Unix Datagram套接字在套接字层工作。可以将它与select()/poll()或其他IO-wait方法一起使用。在设计基于事件的系统时,使用select()/poll()具有优势。这样可以避免繁忙循环。

消息队列中有惊喜。想一想mq_notify()。它用于获取接收事件。听起来我们可以通知有关消息队列的信息。但是它实际上是在注册通知而不是通知任何东西。

更令人惊讶的mq_notify()是,它必须在every之后被调用mq_receive(),这可能会导致竞争条件(当and调用mq_send()之间有其他进程/线程调用时)。mq_receive()mq_notify()

并且它具有mq_open, mq_send(), mq_receive() and mq_close()自己定义的全套,这是多余的,并且在某些情况下与套接字open(),send(),recv() and close()方法规范不一致。

我认为不应将消息队列用于同步。eventfdsignalfd适合于此。

但是它(POSIX消息队列)具有一些实时支持。它具有优先功能。

Messages are placed on the queue in decreasing order of priority, with newer messages of the same priority being placed after older messages with the same priority.

但是,此优先级也可以作为带外数据用于套接字!

最后,对我来说,POSIX消息队列是旧版API。只要不需要实时功能,我总是更喜欢Unix Datagram套接字而不是POSIX消息队列。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.