
一、趣味开篇类比秒懂消息队列我们把System V 消息队列比作小区公共邮局信箱消息队列 一整个公共信箱柜Key 信箱唯一编号所有进程通过编号找到这个柜子消息类型 mtype 信件分类标签1 号文件、2 号通知、3 号加急件消息内容 mtext 信件正文msgsnd 投递信件塞进信箱msgrcv 取信按类型精准取信内核持久化所有进程退出信箱和信件不会消失必须手动销毁管道、FIFO 是 “流式流水传输”不分包、无类型System V 消息队列是带标签的数据包通信支持精准按类型收发这是它最大的核心优势。二、核心内核数据结构深度解析1. 队列整体结构体 msqid_ds信箱台账内核为每一个消息队列维护一个全局台账记录整个信箱的所有状态msg_perm权限所有者、读写权限msg_stime最后一次发消息时间msg_rtime最后一次收消息时间msg_ctime队列创建 / 修改时间msg_qnum当前队列堆积消息总数msg_qbytes队列最大容量字节数2. 单条消息结构体 msgbuf信件模板所有收发消息必须遵循固定模板Linux 标准原生结构体c运行struct msgbuf { long mtype; // 消息类型必须 0核心分类标识 char mtext[1]; // 消息正文可自定义大小 };三、三大核心原生 API 详解1. msgget () —— 申请 / 打开信箱作用通过 key 创建或打开一个消息队列返回队列唯一 ID。c运行int msgget(key_t key, int msgflg);IPC_CREAT不存在则创建存在则打开IPC_EXCL配合 CREAT存在则报错防止重复创建权限位0666 所有进程可读写2. msgsnd () —— 投递消息向指定队列发送带类型的消息内核原子入队。c运行int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);3. msgrcv () —— 接收消息核心特色精准按类型接收可以只取指定类型的消息跳过其他消息。c运行ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);msgtyp0只接收对应类型的消息msgtyp0按顺序接收队首所有消息4. msgctl () —— 队列管理查询 / 销毁c运行int msgctl(int msqid, int cmd, struct msqid_ds *buf);IPC_RMID销毁消息队列必须手动调用IPC_STAT获取队列状态四、原生完整可运行代码示例单进程模拟收发消息演示基础机制c运行#include stdio.h #include stdlib.h #include sys/ipc.h #include sys/msg.h #include string.h #include unistd.h #define MSG_SIZE 128 struct MyMsg { long mtype; char mtext[MSG_SIZE]; }; int main() { // 1. 生成信箱唯一key key_t key ftok(./msgtest.txt, 0x11); // 2. 创建消息队列 int msqid msgget(key, IPC_CREAT | 0666); if(msqid -1) { perror(msgget fail); return -1; } // 3. 发送消息类型1普通消息 struct MyMsg send_msg; send_msg.mtype 1; strcpy(send_msg.mtext, Hello System V Message Queue!); msgsnd(msqid, send_msg, MSG_SIZE, 0); printf(消息发送成功%s\n, send_msg.mtext); // 4. 接收消息 struct MyMsg recv_msg; msgrcv(msqid, recv_msg, MSG_SIZE, 1, 0); printf(消息接收成功%s\n, recv_msg.mtext); // 5. 销毁队列 msgctl(msqid, IPC_RMID, NULL); return 0; }编译运行bash运行touch msgtest.txt gcc msg_raw.c -o msg_raw ./msg_raw ipcs -q # 查看消息队列 ipcrm -q msqid # 手动删除五、本篇思维导图六、本篇小结原生 API 可以实现基础收发但存在大量工程硬伤代码零散、无法分类批量处理消息、多类型消息混杂处理混乱、无异常容错、极易资源泄露。第二篇将深度剖析痛点并做基础封装。