Linux17 进程间的通信 消息队列
12.5消息队列
消息队列是在消息传输过程中保存消息的容器,是分布式系统中重要的中间件。消息是被传送的数据单位,可以非常简单(如文本字符串),也可以更复杂(如包含嵌入对象)。
核心特性
- 异步通信:发送者发送消息后无需等待接收者处理完成即可继续执行
- 解耦系统:将消息的生产者和消费者解耦,提高系统灵活性
- 削峰填谷:应对突发流量,保护下游服务
- 顺序处理:通常按照先进先出(FIFO)的原则处理消息

12.5.1消息队列相应函数
创建或获取消息队列-msgget()
int msgget((key_t)key,int msgflg);参数说明:
- key :消息队列键值,可以使用 ftok() 生成或 IPC_PRIVATE
- msgflg :权限标志,如 IPC_CREAT | 0666
发送消息-msgsnd()
int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);参数说明:
- msqid 消息队列标识符
- const void *msgp消息队列结构体指针
struct msgbuf {long mtype; // 消息类型(必须 > 0)char mtext[1]; // 消息数据(可变长度)};- msgsz消息大小
- msgflg访问模式如SHM)RDONLY只读 可为0
接收消息-msgrcv()
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);参数说明:
- msgtyp :指定接收的消息类型
- = 0 :接收队列中的第一条消息
- > 0 :接收指定类型的第一个消息
- < 0 :接收类型小于等于绝对值的消息
控制消息队列-msgctl()
int msgctl(int msqid, int cmd, struct msqid_ds *buf);- IPC_RMID :删除消息队列
- IPC_STAT :获取状态信息
- IPC_SET :设置参数
12.5.2 消息队列示例
msg.h代码如下:
struct mess{long msgtype;char mess[128];};c.c代码如下:
#include<stdio.h>#include<string.h>#include<sys/msg.h>#include<sys/types.h>#include<unistd.h>#include<stdlib.h>#include"msg.h"int main(){int msgid=msgget((key_t)1234,IPC_CREAT|0600);if(msgid==-1){exit(1);}struct mess m1;m1.msgtype=1;printf("input: ");fgets(m1.mess,128,stdin);int b=msgsnd(msgid,&m1,strlen(m1.mess),0);if(b==-1){exit(1);}exit(0);}d.c代码如下:
#include<stdio.h>#include<string.h>#include<sys/msg.h>#include<sys/types.h>#include<unistd.h>#include<stdlib.h>#include"msg.h"int main(){int msgid=msgget((key_t)1234,IPC_CREAT|0600);if(msgid==-1){exit(1);}struct mess m1;int n=msgrcv(msgid,&m1,128,1,0);printf("recv=%s\n",m1.mess);//msgctl(msgid,IPC_RMID,NULL);exit(0);}运行结果如下:

12.5.3消息队列总结
消息队列是一种异步通信机制,它允许进程将数据(消息)发送到一个队列,并由其他进程从队列中读取。消息队列独立于发送和接收进程存在,实现了进程间的解耦。
特性/组件 | 说明 |
|---|---|
核心概念 | 消息队列是内核维护的链表结构,用于存储格式化的消息(消息类型 + 数据体)。消息可视为一个结构体,通常包含类型和内容。 |
消息结构 (如) struct msgbuf | long m type; (消息类型,必须 > 0) char m text[1]; (消息数据,实际使用时定义足够长度) |
关键函数 (System V) | msgget : 创建或获取消息队列。 msgsnd : 向队列发送消息。 msgrcv : 从队列接收消息。 msgctl : 控制消息队列(如删除)。 |
主要优势 | 解耦: 生产者和消费者无需同时运行或直接交互。 异步性: 发送者不必等待接收者立即处理。 削峰填谷: 应对突发流量,保护下游系统。 顺序保证: 消息通常按FIFO顺序处理。 |
选型对比 (Kafka vs RabbitMQ等) | Kafka: 高吞吐、分布式、持久化,适合大数据、日志流。 RabbitMQ: 支持多种协议(如AMQP)、灵活路由,适合企业级应用、复杂路由。 RocketMQ/Pulsar: 低延迟、高可靠,适合金融、电商等场景。 |
12.5.4消息队列的特点与注意事项
- 内核持久性: System V 消息队列是随内核持续的。即使当前没有进程打开它,队列及其中的消息依然存在,直到被显式删除或系统重启。
- 生命周期管理: 使用完毕后,应使用 msgctl (msqid, IPC_RMID, NULL) 删除队列,防止资源泄漏。
- 同步与阻塞: 默认情况下, msgsnd 和 msgrcv 是阻塞的。当队列满时 msgsnd 阻塞,当队列空或没有指定类型的消息时 msgrcv 阻塞。使用 IPC_NO WAIT 可改为非阻塞模式。
- 系统限制: 系统对消息队列的数量、单个消息的最大长度、队列的总容量等都有限制。可通过 ipcs - l 命令查看。
