74

我最近一直在 Linux 中使用消息队列(System V,但 POSIX 也应该没问题),它们似乎非常适合我的应用程序,但是在阅读了 The Art of Unix Programming 我不确定它们是否真的是一个不错的选择.

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

System V IPC 设施存在于 Linux 和其他现代 Unix 中。但是,由于它们是遗留功能,因此它们并不经常使用。到 2003 年中期,Linux 版本仍然存在缺陷。似乎没有人足够关心来修复它们。

System V 消息队列在最近的 Linux 版本中是否仍然存在错误?我不确定作者是否意味着 POSIX 消息队列应该没问题?

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

我不知道我使用嵌入式 Linux 是否相关?

4

5 回答 5

84

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

几个想法:

  • 其中一些只是时尚。旧的东西又变成了新的。在消息队列上添加一个闪亮的老爸,它们可能是明年最新和最热门的东西。看看 Google 的 Chrome 使用单独的进程而不是其选项卡的线程。突然之间,人们很兴奋,当一个标签被锁定时,它并没有关闭整个浏览器。

  • 共享内存有点像 He-man 光环。如果您没有将最后一个循环从机器中挤出,那么您就不是“真正的”程序员,并且 MQ 的效率略低。对于许多(如果不是大多数)应用程序来说,这完全是无稽之谈,但有时一旦形成一种心态就很难打破这种心态。

  • MQ 确实不适合具有无限数据的应用程序。像管道或套接字这样的面向流的机制更容易使用。

  • System V 变体确实已经失宠。作为一般规则,尽可能使用 POSIX 版本的 IPC。

于 2009-06-09T00:02:33.607 回答
15

是的,我认为消息队列适用于某些应用程序。POSIX 消息队列提供了一个更好的界面,特别是,您可以给队列名称而不是 ID,这对于故障诊断非常有用(更容易看出哪个是哪个)。

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

于 2009-06-09T07:02:22.540 回答
12

我实际上并没有使用过 POSIX 消息队列,因为我总是想保留在网络上分发我的消息的选项。考虑到这一点,您可能会查看更健壮的消息传递接口,例如zeromq或实现AMQP的东西。

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

于 2009-06-08T22:45:29.893 回答
10

POSIX 消息队列的最大缺点:

  • POSIX 消息队列不要求兼容select().(select()在 Linux 中可以使用,但在 Qnx 系统中不可用)
  • 它有惊喜。

Unix 数据报套接字执行与 POSIX 消息队列相同的任务。而 Unix 数据报套接字工作在套接字层。可以将它与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()方法规范不一致。

我不认为消息队列应该用于同步。eventfd并且signalfd适合那个。

它(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 数据报套接字而不是 POSIX 消息队列。

于 2017-06-08T19:27:00.400 回答
0

消息队列对于构建本地解耦应用程序非常有用。它们超级快,它们是块组织的(不需要缓冲,切割等,这是蒸汽套接字的情况),基本上很少的 memcpy() 操作(用户代码复制块到内核,内核复制块到其他进程读取q),这就是消息传递的故事。一些行业知名的中间件,例如 Oracle Tuxedo 或 Mavimax Enduro/X 使用这些队列来帮助构建负载平衡、高性能、容错的分解分布式应用程序。当多个可执行文件从同一个队列中读取时,这些队列允许进行负载平衡,并且内核调度程序只是将消息分发给曾经处于空闲状态的进程。Linux 的好处是轮询可以在 Posix 队列上完成,这有助于解决某些场景。

例如,两个进程可以通过队列轻松地在本地进行通信,并具有令人印象深刻的吞吐量(~70k req+rply/sec):

通过队列/性能发送和回复消息

如果需要联网,例如 Enduro/X 提供 tpbridge 进程,该进程基本上从本地队列中读取消息,将块发送到其他机器,另一端将消息注入本地队列中。

此外,与套接字相比,您不会遇到任何队列问题,例如当某些二进制文件崩溃时的繁忙/延迟套接字,即启动时的程序可以立即开始读取队列并进行处理。

于 2021-12-14T23:39:39.103 回答