潍坊地区制作网站,wordpress编辑header,如何开发游戏,网站服务费怎么做凭证消息队列#xff08;Message Queue#xff09;是一种进程间通信#xff08;IPC#xff09;机制#xff0c;它允许进程通过在队列中添加和读取消息来交换数据。与管道#xff08;命名/匿名#xff09;相比#xff0c;消息队列具有结构化消息、异步通信和消息持久化等特点…消息队列Message Queue是一种进程间通信IPC机制它允许进程通过在队列中添加和读取消息来交换数据。与管道命名/匿名相比消息队列具有结构化消息、异步通信和消息持久化等特点更适合复杂的进程间数据交换场景。
核心特性消息结构化
每个消息都有一个类型标识通常是整数和数据内容接收进程可以根据类型选择性读取消息而无需按顺序处理所有数据。异步通信
发送进程发送消息后无需等待接收进程立即处理可继续执行其他操作接收进程可在需要时读取消息两者无需同步运行。消息持久化
消息存储在内核空间即使发送进程退出消息也会保留在队列中直到被接收进程读取或手动删除。多进程交互
多个进程可以向同一消息队列发送消息也可以从队列中读取消息通过类型筛选实现一对一、一对多通信。消息队列的使用System V 消息队列Linux 为例
System V 消息队列是最常用的实现通过以下系统调用操作
msgget()创建或获取消息队列msgsnd()发送消息到队列msgrcv()从队列接收消息msgctl()控制消息队列如删除、获取状态
1. 消息结构定义
消息需要按固定格式定义包含类型和数据
#include sys/msg.h// 消息结构必须以 long 类型的 mtype 开头
struct msgbuf {long mtype; // 消息类型0char mtext[1024]; // 消息数据可自定义大小和类型
};2. 创建/获取消息队列msgget
// 创建或获取消息队列返回队列 ID
int msgid msgget(key_t key, int flags);key用于标识消息队列的键值可通过 ftok() 生成唯一键flags创建权限和操作标志如 IPC_CREAT | 0666 表示创建队列权限为 666
3. 发送消息msgsnd
// 向队列发送消息成功返回 0失败返回 -1
int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg);msgid消息队列 IDmsgp指向消息结构的指针msgsz消息数据部分mtext的长度msgflg发送标志0 表示阻塞IPC_NOWAIT 表示非阻塞
4. 接收消息msgrcv
// 从队列接收消息成功返回接收的字节数失败返回 -1
ssize_t msgrcv(int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflg);msgtyp指定接收的消息类型0 接收任意类型0 接收指定类型0 接收小于等于其绝对值的类型其他参数同 msgsnd
5. 控制消息队列msgctl
// 控制消息队列如删除成功返回 0失败返回 -1
int msgctl(int msgid, int cmd, struct msqid_ds *buf);cmd操作命令IPC_RMID 表示删除队列
完整示例
发送进程sender.c
#include stdio.h
#include stdlib.h
#include string.h
#include sys/msg.h
#include sys/ipc.hstruct msgbuf {long mtype;char mtext[1024];
};int main() {// 生成唯一键文件路径和项目ID需与接收进程一致key_t key ftok(/tmp, A);if (key -1) {perror(ftok failed);exit(1);}// 创建或获取消息队列int msgid msgget(key, IPC_CREAT | 0666);if (msgid -1) {perror(msgget failed);exit(1);}// 准备消息类型为 1数据为 Hello, receiver!struct msgbuf msg;msg.mtype 1;strcpy(msg.mtext, Hello, receiver!);// 发送消息if (msgsnd(msgid, msg, strlen(msg.mtext) 1, 0) -1) {perror(msgsnd failed);exit(1);}printf(发送消息: %s\n, msg.mtext);return 0;
}接收进程receiver.c
#include stdio.h
#include stdlib.h
#include sys/msg.h
#include sys/ipc.hstruct msgbuf {long mtype;char mtext[1024];
};int main() {// 生成与发送进程相同的键key_t key ftok(/tmp, A);if (key -1) {perror(ftok failed);exit(1);}// 获取消息队列不创建只连接已存在的int msgid msgget(key, 0666);if (msgid -1) {perror(msgget failed);exit(1);}// 接收消息只接收类型为 1 的消息struct msgbuf msg;ssize_t n msgrcv(msgid, msg, sizeof(msg.mtext), 1, 0);if (n -1) {perror(msgrcv failed);exit(1);}printf(接收消息: %s\n, msg.mtext);// 接收完成后删除消息队列可选if (msgctl(msgid, IPC_RMID, NULL) -1) {perror(msgctl failed);exit(1);}return 0;
}运行方式
先编译并运行接收进程会阻塞等待消息。再编译并运行发送进程发送消息后接收进程会立即输出并删除队列。
关键注意事项消息类型的作用
接收进程可通过 msgtyp 筛选消息例如
按优先级处理高类型消息优先实现多进程定向通信不同进程使用不同类型消息大小限制
系统对单条消息的大小有限制可通过 msgmax 配置超过限制会导致发送失败。队列容量限制
消息队列的总字节数也有限制msgmnb满队列时发送操作会阻塞非阻塞模式下返回错误。资源释放
消息队列不会自动销毁需通过 msgctl(..., IPC_RMID, ...) 手动删除否则会残留内核中占用资源。与其他 IPC 的对比机制特点适用场景消息队列结构化消息、异步、按类型读取复杂数据交换、多进程通信管道流式数据、简单、顺序读取简单命令交互、父子进程通信共享内存速度最快、直接访问内存高频数据交换、大数据量传输信号量用于同步和互斥不传递数据控制进程对共享资源的访问
应用场景
分布式系统中的进程协作如服务端与多个客户端的消息交互。日志收集系统不同进程按类型发送日志收集进程分类处理。任务调度调度进程发送任务消息工作进程按类型接收并执行。
消息队列通过结构化和异步特性简化了复杂进程间通信的设计是中大型系统中常用的 IPC 方案。