【linux】消息队列

📅 发布时间:2026/7/20 21:14:27
【linux】消息队列 一、消息队列的概述消息队列是消息的链表存放在内存中由内核维护消息队列的特点。1、消息队列中的消息是有类型的。2、消息队列中的消息是有格式的。3、消息队列可以实现消息的随机查询。消息不一定要以先进先出的次序读取编程时可以按消息的类型读取。4、消息队列允许一个或多个进程向它写入或者读取消息。5、与无名管道、命名管道一样从消息队列中读出消息消息队列中对应的数据都会被删除。 6、每个消息队列都有消息队列标识符消息队列的标识符在整个系统中是唯一的。7、只有内核重启或人工删除消息队列时该消息队列才会被删除。若不人工删除消息队列消息队列会一直存在于系统中 在ubuntu 某些版本中消息队列限制值如下: 每个消息内容最多为8K字节 每个消息队列容量最多为16K字节 系统中消息队列个数最多为1609个 系统中消息个数最多为16384个在ubuntu 某些版本中消息队列限制值如下:每个消息内容最多为8K字节每个消息队列容量最多为16K字节系统中消息队列个数最多为1609个系统中消息个数最多为16384个二、消息队列的API1、获取系统唯一的key值#include sys/types.h#include sys/ipc.hkey_tftok(const char *pathname, int proj_id)功能 获得项目相关的唯一的IPC键值。参数pathname路径名proj_id项目ID非0整数(只有低8位有效)返回值 成功返回key值失败返回 -12、创建消息队列#include sys/msg.hintmsgget(key_t key, int msgflg)功能 创建一个新的或打开一个已经存在的消息队列。不同的进程调用此函数只要用相同的key值就能得到同一个消息队列的标识符。参数keyIPC键值。msgflg标识函数的行为及消息队列的权限。参数: msgflg的取值IPC_CREAT创建消息队列。IPC_EXCL检测消息队列是否存在。位或权限位消息队列位或权限位后可以设置消息队列的访问权限格式和open函数 的mode_t一样但可执行权限未使用。返回值 成功消息队列的标识符失败返回-1查看消息队列ipcs ‐q删除消息队列:ipcrm ‐q msqid3、消息队列的信息 格式定义typedef struct _msg {long mtype; /*消息类型 必须是第一个成员 必须是long类型*/char mtext[100]; /*消息正文 不止一个成员*/.../*消息的正文可以有多个成员*/}MSG;4、发送消息#include sys/msg.hintmsgsnd(int msqid, const void *msgp,size_t msgsz, int msgflg);功能 将新消息添加到消息队列。参数msqid消息队列的标识符。msgp待发送消息结构体的地址。msgsz消息正文的字节数。msgflg函数的控制属性 0msgsnd调用阻塞直到条件满足为止。 IPC_NOWAIT: 若消息没有立即发送则调用该函数的进程会立即返回。返回值 成功0失败返回-15、接收消息#include sys/msg.hssize_tmsgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgf lg);功能 从标识符为msqid的消息队列中接收一个消息。一旦接收消息成功则消息在消息队 列中被删除。参数msqid消息队列的标识符代表要从哪个消息列中获取消息。msgp 存放消息结构体的地址。msgsz消息正文的字节数。msgtyp感兴趣消息的类型、可以有以下几种类型msgtyp 0返回队列中的第一个消息msgtyp 0返回队列中消息类型为msgtyp的消息msgtyp 0返回队列中消息类型值小于或等于msgtyp绝对值的消息如果这 种消息有若干个则取类型值最小的消息。注意若消息队列中有多种类型的消息msgrcv获取消息的时候按消息类型获取不是先进先出的。在获取某类型消息的时候若队列中有多条此类型的消息则获取最先添加的消息 即先进先出msgflg函数的控制属性0msgrcv调用阻塞直到接收消息成功为止。MSG_NOERROR:若返回的消息字节数比nbytes字节数多,则消息就会截短到nbytes字 节,且不通知消息发送进程。IPC_NOWAIT:调用进程会立即返回。若没有收到消息则立即返回-1。 返回值 成功返回读取消息的长度失败返回-1总结不管是发送者还是接收者ftok 得到唯一的keymsgget 创建消息队列发送者:MSG msg;msg.mtype 接收感兴趣的类型值;msgsnd(msg_id, msg, sizeof(MSG) ‐ sizeof(long), 0);//发送消息到消息队列接收者MSG msg;msgrcv(msg_id, msg, sizeof(MSG) ‐ sizeof(long), 30, 0);msgrcv(msg_id, msg, sizeof(MSG) ‐ sizeof(long), 接收感兴趣的类型值, 0);三、示例代码1、bob.c负责发送-20/-30消息#include stdio.h #include sys/types.h #include sys/ipc.h #include sys/msg.h #include string.h //定义一个消息类型结构 typedef struct MyStruct { long mtype; //消息类型 char mtext[64]; //消息正文 char name[32]; //发送者的姓名 } MSG; int main(int argc, char const *argv[]) { //获取IPC的唯一KEY值 key_t key ftok(/, 2021); printf(key%#x\n, key); //创建一个消息队列 int msg_id msgget(key, IPC_CREAT | 0666); printf(msg_id%d\n, msg_id); //发送消息 给lucy‐‐20发消息 MSG msg; memset(msg, 0, sizeof(msg)); msg.mtype 20; //msg.mtype 30; strcpy(msg.name, bob); strcpy(msg.mtext, hello msg); msgsnd(msg_id, msg, sizeof(MSG) ‐ sizeof(long), 0); return 0; }2、lucy.c负责接收--20的消息#include stdio.h #include sys/types.h #include sys/ipc.h #include sys/msg.h #include string.h //定义一个消息类型结构 typedef struct MyStruct { long mtype; //消息类型 char mtext[64]; //消息正文 char name[32]; //发送者的姓名 } MSG; int main(int argc, char const *argv[]) { //获取IPC的唯一KEY值 key_t key ftok(/, 2021); printf(key%d\n, key); //创建一个消息队列 int msg_id msgget(key, IPC_CREAT|0666); //接收消息 MSG msg; memset(msg, 0, sizeof(msg)); msgrcv(msg_id, msg, sizeof(MSG)‐sizeof(long), 20, 0); printf(发送者%s\n, msg.name); printf(消息%s\n, msg.mtext); return 0; }3、tom.c负责接收-30的消息#include stdio.h #include sys/types.h #include sys/ipc.h #include sys/msg.h #include string.h //定义一个消息类型结构 typedef struct MyStruct { long mtype; //消息类型 char mtext[64]; //消息正文 char name[32]; //发送者的姓名 } MSG; int main(int argc, char const *argv[]) { //获取IPC的唯一KEY值 key_t key ftok(/, 2021); printf(key%d\n, key); //创建一个消息队列 int msg_id msgget(key, IPC_CREAT | 0666); //接收消息 MSG msg; memset(msg, 0, sizeof(msg)); msgrcv(msg_id, msg, sizeof(MSG) ‐ sizeof(long), 30, 0); printf(发送者%s\n, msg.name); printf(消息%s\n, msg.mtext); return 0; }