一、消息队列的基本概念
消息队列是存储消息的线性表,是消息在传输过程中的容器。消息队列一经创建,即可以向队列中写入指定类型的消息,其他进程则可以从该队列中取出指定类型的消息。
1、1 队列
在数据结构中,队列定义为一种运算受限的线性表。它允许在队列中的一端进行插入,而在队列的一端进行删除。队列的数据输入输出是按照“先进先出”的原则进行的。队列的结构为:
1、2 消息
消息就是进程间传递的数据内容。在消息队列机制中,消息是有类型的。也就是说,一条消息包含的内容不仅是数据,而且包含消息的类型信息。
对于一个消息队列来说,可以存储不同类型的消息,进程可以根据需要从消息队列中取出自己所需要的类型的消息,也可以向队列中发送不同类型的消息。
Linux的IPC机制为描述消息专门提供了一个结构模板,名称为struct msgbuf,位于头文件sys/msg.h中,结构定义如下:
struct msgbuf
{
long int mtype; //消息类型,长整型变量
char mtxet[n]; //消息类型,字符串数组
};
1、3消息队列
消息队列具有队列的基本特征,也具有其独特的性质。在消息队列中,入队称为发送消息,出队称为接收消息,其模型如图:
除此之外:消息队列还具有以下特征:
·消息队列中的消息是有类型的。在发送一条消息时,可以指定消息类型。在接收进程中,可以按照该消息类型从消息队列中获取数据。在实际应用中,可以多个应用共用一个队列,用消息队列区分不同的应用。
·消息队列中的消息按照发送的顺序排队,对于相同类型的消息,先进消息队列的消息先被接收。
二、消息队列的创建
一个消息队列实际上是Linux在内核中分配的一个数据结构。要使用消息队列进行消息传输,首先要创建一个消息队列。其声明位于头文件sys/msg.h中
函数原型: int msgget ( key_t key, int flag); //若成功,返回消息队列的ID,失败返回-1
说明:该函数除了具有创建新的队列的功能外,还可以返回一个已存在的消息队列的标识符。
参数说明:key_t key :输入参数,键值,该参数的输入方式有3种:
(1)直接指定一个键值:例(key_t) 0x123456
(2)用fork产生一个键值作为输入
(3)用IPC_PRIVATE为参数输入,由系统创建一个可用的队列。
一旦调用msgget成功,操作系统在内核中分配了一个名称为msgqid_ds的数据结构用于管理该消息队列。
msgqid_ds的数据结构:(位于头文件bit/msq.h中)
三、消息队列的发送和接收(读写)
(1)消息队列的发送: 消息队列创建成功后,便可以调用消息发送函数向消息队列中发送消息了(消息队列的写)。由于消息是有类型的,因此在发送消息时,要用到之前说过的消息结构。要向队列中发送消息使用函数msgsnd
函数原型: int msgsnd ( int msgid, const void *ptr ,size_t nbytes, int flag);//成功,返回0,否则返回-1
参数说明:int msgid :输入参数,消息队列的标识符,由msgget函数返回的标识符;
const void *ptr: 输入参数,消息结构指针,该参数的类型为void *,实际上应该向该参数传递一 个“消息队列”的指针。不过在传递参数时候,强制转换为void *;
size_t nbytes :输入参数,消息的长度。这里指的是真正的消息内容的长度,而不是消息结构的尺寸
int flag :输入参数,发送消息的可选标志
(2)消息队列的接收: 消息已经发送到消息队列中,其他进程可以通过消息接收操作可以从消息队列中读取指定类型的消息,也可以不指定消息类型;函数msgrcv用于从队列中取消息。我们并不一定要以先进先出的次序取消息,也可以按消息的类型字段取消息
函数原型: ssize_t msgrcv ( int msgid, void *ptr ,size_t nbytes, long type, int flag);
//成功,返回消息数据部分的长度,否则返回-1
参数说明:int msgid :输入参数,消息队列的标识符,由msgget函数返回的标识符;
void *ptr: 输入参数,消息结构指针,该参数的类型为void *,实际上应该向该参数传递一个“消息队列”的 指针。(存储实际消息数据的缓冲区)
size_t nbytes :输入参数,要读取消息的长度(数据缓冲区的长度)。[注意参数设置]
long type :输入参数,要读取的消息类型
》: type==0 返回队列中的第一个消息
type > 0 返回队列中消息类型为type的第一个消息
type < 0 返回队列中消息类型小于等于type绝对值的消息,如果这种消息有若干个,则取 类型值最小的消息
int flag :输入参数,接收消息的可选标志,可以指定为IPC_NOWMSG,使操作不阻塞
四、消息队列的控制
消息队列创建成功后,内核不仅创建了消息队列结构用于存储消息,而且创建了消息队列的控制结构,就是介绍过得msgqid_ds。该结构中指定了该消息队列的权限信息、发送接收消息的进程、时间戳等信息。IPC机制提供了函数msgctl用于对该结构进行控制,可以对队列执行多种操作(包括删除操作)。
函数原型:int msgctl ( int msgid, int cmd , struct msqid_ds *buf); //成功,返回0,否则返回-1
参数说明:int msgid :输入参数,消息队列的标识符,由函数msgget函数返回的标识符
int cmd: 输入参数,指定对msqid指定的队列要执行的命令 struct msqid_ds *buf :输入或者输出参数,指向msqid_ds结构的指针。在cmd参数为IPC_STAT时,该参数用作输出;在cmd参数为IPC_SET式,该参数用作输入。