System V 消息队列
通信方法
- 支持不同进程之间以消息(message)的形式交换数据
- 发送者
- 获取消息队列的ID(IPC标识符)
- 将数据放入一个带有标识的消息结构体,发送到消息队列
- 接收者
- 获取消息队列的ID
- 将指定标识的消息从消息队列中读出,然后进一步后续处理
消息队列
- 编程接口
- key_t ftok(const char *pathname, int proj_id);
- int msgget(key_t key, int msgflg);
- 创建或打开一个消息队列
- 首先既有消息队列中搜索与指定key对应的队列,返回该对象的标识符
- 若没找到,msgflg指定了IPC_CREAT,则创建一个队列,并返回IPC标识符
- int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
- 发送消息到消息队列
- ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
- 从消息队列中接收信息
- int msgctl(int msqid, int cmd, struct msqid_ds *buf);
- IPC_STAT: 获取消息队列的属性信息
- IPC_SET: 设置消息队列的属性
- IPC_RMID:删除消息队列
-
#include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ipc.h> #include <sys/msg.h> #define handle_error(s) \ {perror(s);exit(EXIT_SUCCESS);} int main(int argc, char *argv[]) { key_t key = 12345; int msg_id = msgget(key, O_CREAT|0666); struct msqid_ds info; if (msgctl(msg_id, IPC_STAT, &info) == -1) handle_error("msgctl") printf("uid:%d, gid:%d, cuid:%d ,cgid:%d\n", info.msg_perm.uid, \ info.msg_perm.gid, info.msg_perm.cuid, info.msg_perm.cgid); printf("mode:%03o, cbytes:%lu, qnum:%lu, qbytes:%lu\n", \ info.msg_perm.mode&0777, info.msg_cbytes, info.msg_qnum, info.msg_qbytes); info.msg_qbytes = 16777; if (msgctl(msg_id, IPC_SET, &info) == -1) handle_error("msgctl") if (msgctl(msg_id, IPC_STAT, &info) == -1) handle_error("msgctl") printf("mode:%03o, cbytes:%lu, qnum:%lu, qbytes:%lu\n", \ info.msg_perm.mode&0777, info.msg_cbytes, \ info.msg_qnum, info.msg_qbytes); return 0; }
查看消息队列命令
ipcs命令
如果你想看共享内存,因使用ipcs -m
如果你想看消息队列,因使用ipcs -q
在命令行删除消息队列
ipcrm -q xxx
Linux中的消息队列
内核实现:消息队列模型
- 相关数据结构:/usr/include/linux/msg.h、/ipc/msg.c
- msqid_ds:标识整个消息队列的基本情况:消息队列权限、所有者、操作权限、和2个指针,分别指向消息队列中的第一和最后一个消息
- msg:整个消息队列的主体,一个消息队列有若干个消息,每个消息数据结构的基本信息包括消息的类型、消息大小、消息内容指针和下一个消息的数据结构位置
- 消息队列是消息的链表,存储在内核中,由消息队列标识符识别
- IPC标识符:消息队列的ID