管道 vs 消息队列

20

消息队列和Linux中的管道有什么区别?

2个回答

22

直接脑补,如果你所说的是 posix 消息队列(不是 SysV 那一种):

  • 管道没有大小限制,消息队列有。
  • 使用文件描述符可以集成管道到系统中,消息队列有自己的一套函数,尽管 Linux 上的 select()poll()epoll() 等函数也支持 mqd_t
  • 关闭管道后,需要在双方都配合下才能重新建立连接;而关闭消息队列只需要单方面操作即可。
  • 管道是“扁平”的,类似于流,要实现消息结构,必须在双方都实现协议。而消息队列已经是面向消息的,不需要考虑如何获取队列中的第五个消息等问题。

好的,非常感谢...但我有一个小疑问:“一旦关闭的管道需要在两端提供某种支持”,您的意思是强调管道不是内核持久的,而消息队列是...那么一旦关闭管道,需要什么样的支持来重新建立它呢? - mint9
@mint9:一般来说,您需要捕获SIGPIPE信号,优雅地处理它,然后“重新打开”管道。我想您可以fork()您的进程(在两侧),dup您的stdin/stdout,保持父进程运行(它们充当卫兵),然后在关闭时让您的子进程死亡(在两侧),并重新进行fork/dup/pipe过程。 - hroptatyr

14

实际上,它们是非常不同的东西。

最大的实际区别在于管道没有“消息”的概念,它只是一个用于write()写入字节和read()读取字节的管道。接收端必须知道哪个数据片段在您的程序中构成了“消息”,并且您必须自行实现该功能。此外,字节的顺序是固定的:字节将按照您放置它们的顺序输出,并且通常它只有一个输入和一个输出。

消息队列用于传输具有类型和大小的“消息”。因此,接收端只需等待特定类型的一个“消息”,而无需担心是否完整。多个进程可以向同一个队列发送和接收。

有关更多信息,请参见man mq_overview和/或man svipc


1
即使在队列中,您也可以发送任何结构作为消息,因此在这种情况下,接收端必须知道“在您的程序中哪个数据部分构成消息”。 - Amol Sharma
它们真的传递消息吗?我查看了SO上的这个例子,似乎只是传递抽象字符,我没有看到任何消息传递。 - Hi-Angel
@Hi-Angel,你所说的“message”是什么意思? - mvds
1
@Hi-Angel,区别在于类型和长度信息是由API提供的,它们不像TLV中的有效载荷一样。 - mvds
好的,但是在我在第一条评论中提供的示例中,这个API被用来接收抽象字符,就像read()函数一样。他们使用了错误的函数吗?是否有返回/接收某些结构体的函数可用? - Hi-Angel
显示剩余2条评论

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