欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

消息队列

程序员文章站 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的那一位不一样
  1. 若单独使用IPC_CREAT:不存在,创建;存在返回
  2. 单独使用IPC_EXCL:没有任何意义,所以一般两个一起用
  3. 两个一起使用:如果目标消息队列已存在,出错返回,如果目标消息队列不存在,创建返回
  • 返回值:成功返回一个非负整数,即消息队列标识码,失败返回-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);
  • 参数解析:
  1. msqid:由msgget函数返回的消息队列标识码
  2. cmd:要采取的动作,有三个可取值:IPC_STAT(拷贝),IPC_SET(设置),IPC_RMID(删除)
  3. 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);

  • 参数解析:
  1. msqid:由msgget返回的消息队列标识码
  2. msgp:一个指针,指向准备返回的消息
  3. msgsz:msgp指向消息的长度
  4. msgflg:控制当前消息队列满或到达系统上限时将要发送的失去,缺省为0,默认为阻塞方式。msgflg=IPC_NOWAIT表示队列满不等待,返回EAFAIN错误
  • 返回值:成功返回0,失败返回-1
  • 说明:
  1. 消息结构必须小于系统规定的上限值
  2. 消息结构必须以一个长整形开始,接受者将利用这个长整形确定消息的类型
  3. 消息结构的参考类型如下:
struct msgbuf
{
    long mtype;
    char mtext[1];
}

4.msgrcv函数

  • 函数功能:从一个消息队列接收一个消息
  • 函数原型:
ssize_t msgrcv(int msqid,void *msgp,size_t msgz,long msgtyp,int msgflg);
  • 参数解析:
  1. msqid:由msgget函数返回的消息队列标识码
  2. msgp:一个指针,指向准备发送的消息
  3. msgsz:msgp指向消息的长度
  4. msgtype:实现结束优先级的简单形式
  5. msgflg:控制当前消息队列满或到达系统上限时要发生是事情,失败返回-1
  • 说明:
  1. msgtype=0,返回消息队列的第一条信息
  2. msgtype>0,返回消息队列第一天类型等于msgtype的消息
  3. msgtype<0,返回消息队列第一条类型小于等于msgtype绝对值的消息,并且是满足条件的消息类型最小的消息
  4. msgflg = IPC_NOWAIT,队列没有可读消息,不等待,返回ENOMSG错误
  5. msgflg = MSG_NOERROR,消息大小超过msgsz时被截断
  6. 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);
  • 参数解析:
  1. pathname:一个存在的可访问的路径或文件
  2. peoj_id:该函数的后8为与第一个参数一起确定一个key值,所以该参数是产生key的关键。且同一个参数不能出现在同一个路径下
  • 返回值:失败返回-1,成功返回一个key值

 ipcs&ipcrm命令:

  • ipcs:查看IPC资源
  • ipcrm:删除IPC资源

使用ctrl+c命令中止的进程,还未调用销毁消息队列的代码,所以创建的IPC未销毁,在下次运行代码时会出错

所以我们要使用命令ipcrm手动删除资源。