ConstStar
发布于 2025-11-28 / 3 阅读 / 0 评论 / 0 点赞

进程间通信:管道和消息队列对比

1. 数据格式与边界

  • 管道(pipe):数据是一串连续的字节,没有分条。写多少可以一次读,也可以分多次读。
  • 消息队列:数据是一条条的消息,消息有类型和长度。发一个消息,对方就是按消息一次性收,不会拆分。

2. 通信方式

  • 管道:单向通信。无名管道只能亲缘进程间使用;命名管道(FIFO)可以不相关进程用,但仍然单向。要双向得建两个管道。
  • 消息队列:支持双向通信。一个队列可以有多个进程收发消息,还能按类型选取消息。

3. 消息优先级和筛选

  • 管道:没有优先级。谁先写谁先被读,顺序不会变。
  • 消息队列:支持按类型或优先级拿消息,接收方可以指定只收特定类型的消息,也可以顺序收。

4. 数据大小限制

  • 管道:限制主要来自内核缓存(常见4KB~64KB),数据被读出就没了。没有“最大消息”的说法。
  • 消息队列:每条消息/整个队列/系统都有最大长度限制(如8KB/16KB),这些可以通过系统参数查看和设置。

5. 生命周期

  • 管道:随着进程结束而消失,没人用它了就被内核回收。
  • 消息队列:只要不手动删除,就一直存在内核里,进程退出消息还在,直到被删除或系统重启。

6. 性能

  • 管道:实现比较简单,系统开销小,就是数据的读写。
  • 消息队列:有额外的消息管理和查找,所以系统开销稍大一些,但是用起来更灵活。

7. 典型适用场景

场景 推荐用法
只需要简单地传一串数据 管道
需要按类型/优先级处理请求 消息队列
多个进程需要彼此交互、按消息分发 消息队列(或socket)
不相关进程间只需单向流式传输 命名管道(FIFO)
需要很好地管理单条消息,或对粘包敏感 消息队列

8. 常用接口对比

操作 管道 消息队列
创建 pipe(), mkfifo() msgget(), mq_open()
发送 write() msgsnd(), mq_send()
接收 read() msgrcv(), mq_receive()
关闭 close() msgctl(), mq_close()/mq_unlink()
阻塞/非阻塞 支持O_NONBLOCK 支持,可设非阻塞或超时

评论