消息队列
程序员文章站
2022-05-18 10:46:02
...
- 消息队列提供了一个从一个进程向另一个进程发送数据块的方法
- 每个数据库都被认为是一个类型,接收者进程接收的数据块可以有不同的类型值
- 消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的,每个消息队列的总的字节数也是有上限的,系统上消息队列的总数也有一个上限
消息队列的特点:
- 消息队列是基于消息的,而管道是基于字节流的
- 消息队列的读取不一定是先入先出
- 消息队列的生命周期随内核,所以如果没有显示的删除它,那么在关机之前它一直在
IPC对象数据结构:
- 内核为每一个IPC对象维护一个数据结构
每一个对象都有一个唯一标识:_key,可以通过它找到一个消息队列
消息队列结构:
消息队列是一个链式队列,他的第一个成员就是上述的IPC对象,_first,_last是它的头指针和尾指针
消息队列之间的通信:
进程1可以通过消息队列访问进程2,进程2也可以通过消息队列访问1(通过消息队列的节点)
那么怎么保证进程1,2看到的是同一个消息队列呢?——约定
- 进程1,2通过调用ftok函数产生俩个相同的key,这样就可以看到用一个消息队列了
Linux系统提供以下几个函数实现消息队列的通信
1.msgget函数:
- 函数原型:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgget(key_t key,int msgflg);
- 函数功能:用来访问和创建一个消息队列
- 参数解析:
- key:某个消息队列的名字
- msgflg:可以有以下几个选择:IPC_CREAT,IPC_EXCL,他们俩个比特位中只有一位是1,其余为0,且为1的那一位不一样
- 若单独使用IPC_CREAT:不存在,创建;存在返回
- 单独使用IPC_EXCL:没有任何意义,所以一般两个一起用
- 两个一起使用:如果目标消息队列已存在,出错返回,如果目标消息队列不存在,创建返回
- 返回值:成功返回一个非负整数,即消息队列标识码,失败返回-1
2.msgctl函数
- 函数功能:控制消息队列(可根据参数进行相关操作)
- 函数原型
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
- 参数解析:
- msqid:由msgget函数返回的消息队列标识码
- cmd:要采取的动作,有三个可取值:IPC_STAT(拷贝),IPC_SET(设置),IPC_RMID(删除)
- buf:消息队列管理结构体,不使用的时候设置为NULL
- 返回值:成功返回0,失败返回-1
3.msgsnd函数
- 函数功能:把一条消息添加到消息队列中
- 函数原型:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);
- 参数解析:
- msqid:由msgget返回的消息队列标识码
- msgp:一个指针,指向准备返回的消息
- msgsz:msgp指向消息的长度
- msgflg:控制当前消息队列满或到达系统上限时将要发送的失去,缺省为0,默认为阻塞方式。msgflg=IPC_NOWAIT表示队列满不等待,返回EAFAIN错误
- 返回值:成功返回0,失败返回-1
- 说明:
- 消息结构必须小于系统规定的上限值
- 消息结构必须以一个长整形开始,接受者将利用这个长整形确定消息的类型
- 消息结构的参考类型如下:
struct msgbuf
{
long mtype;
char mtext[1];
}
4.msgrcv函数
- 函数功能:从一个消息队列接收一个消息
- 函数原型:
ssize_t msgrcv(int msqid,void *msgp,size_t msgz,long msgtyp,int msgflg);
- 参数解析:
- msqid:由msgget函数返回的消息队列标识码
- msgp:一个指针,指向准备发送的消息
- msgsz:msgp指向消息的长度
- msgtype:实现结束优先级的简单形式
- msgflg:控制当前消息队列满或到达系统上限时要发生是事情,失败返回-1
- 说明:
- msgtype=0,返回消息队列的第一条信息
- msgtype>0,返回消息队列第一天类型等于msgtype的消息
- msgtype<0,返回消息队列第一条类型小于等于msgtype绝对值的消息,并且是满足条件的消息类型最小的消息
- msgflg = IPC_NOWAIT,队列没有可读消息,不等待,返回ENOMSG错误
- msgflg = MSG_NOERROR,消息大小超过msgsz时被截断
- msgtype>0且 msgflg = MSG_EXCEPT ,接收不等于msgtype的第一条消息
5.ftok函数
- 函数功能:要使俩个进程看到同一个key值,这个ftok函数就是用来产生key值的
- 函数原型:
#include<sys/types.h>
#include<sys/ipc.h>
key_t ftok(const char *pathname,int proj_id);
- 参数解析:
- pathname:一个存在的可访问的路径或文件
- peoj_id:该函数的后8为与第一个参数一起确定一个key值,所以该参数是产生key的关键。且同一个参数不能出现在同一个路径下
- 返回值:失败返回-1,成功返回一个key值
ipcs&ipcrm命令:
- ipcs:查看IPC资源
- ipcrm:删除IPC资源
使用ctrl+c命令中止的进程,还未调用销毁消息队列的代码,所以创建的IPC未销毁,在下次运行代码时会出错
所以我们要使用命令ipcrm手动删除资源。