一、什么是消息队列
消息队列是消息的链接表,存放在内核中并由消息队列标识符标识。消息队列向我们提供了一个进程向另一个进程发送数据块的方法。每个数据块都被认为含有一种类型,接受进程可以独立地接受含有不同类型的数据结构。
二、在linux中使用消息队列
在linux中提供了一系列消息队列的函数接口来让我们方便地使用它来实现进程间的通信。它的用法与信号量机制相似
1、msgget函数
该函数用于创建一个新队列或者获取一个现存的队列。它的函数原型是:
int msgget(key_t key,int flag); 返回值:若成功则返回消息队列ID,若出错返回-1
每个队列都有一个这样的结构体:
struct msgid_ds{
struct ipc_perm msg_perm;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
time_t msg_stime;
time_t msg_rtime;
time_t msg_ctime;
};
当创建一个新队列时,需初始化msgid_ds结构的以下成员:(1)flag权限设置。(2)msg_qnum、msg_lspid、msg_lrpid、msg_stime和msg_rtime都设置为0。(3)msg_ctime设置为当前时间。(4)nsg_qbytes设置为系统限制值。若创建成功,返回队列ID,此后,该值就可用于其他三个消息队列函数。
2、msgsnd函数
该函数用于将新消息添加到消息队列尾端。它的函数原型是:
int msgsnd(int msgid,const void *ptr,size_t nbytes,int flag); 返回值:若成功则返回0,若出错则返回-1
每个消息包含一个正长整型类型字段,一个非负长度以及实际数据字节,这些都在将消息添加到队列时,传送给msgsnd。在函数原型中,msgid是由msgget函数返回的消息队列标识符。ptr是一个指向准备发送消息的指针,消息结构有要求,它指向的消息结构一定要是以一个长整型成员变量开始的结构体,接收函数将用这个成员来确定消息的类型。qbytes为ptr指向的消息的长度,若qbytes为0,则无消息数据。若发送的最长消息为512字节,则可定义以下结构
struct mymesg{
long mtype;
char mtext[512];
};于是,pttr就是一个指向mymesg结构体的指针。参数flag的值可以定义为IPC_NOWAIT。msgsnd函数调用成功后,队列中的消息数加1
3、msgrcv函数
该函数用于从队列中获取消息。它的函数原型是:
ssize_t msgrcv(int msgid,void *ptr,size_t nbytes,long type,int flag);返回值:若成功则返回消息的数据部分的长度,若出错则返回-1
msgid、ptr、nbytes的作用和msgsnd函数中的是一样的。
参数type的取值可以指定我们想要哪一种消息。
(1)type=0,返回队列中的第一个消息
(2)type>0,返回队列中消息类型为type的第一个消息
(3)type<0,返回队列中消息类型值小于或等于type绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。
参数flag的值可以指定为IPC_NOWAIT,使进程不阻塞。这样,如果没有所指定的消息,则函数直接返回-1。msgrcv函数调用成功后,队列中的消息数减1
4、msgctl函数
该函数用于对消息队列执行多种操作。它的函数原型是:
int msgctl(int msgid,int cmd,struct msgid_ds *buf); 返回值:若成功则返回0,出错则返回-1
参数cmd是将要采取的动作,它可以取三个值
IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值
IPC_SET:如果进程有足够的权限,就把消息队列中的当前关联值设置为msgid_ds结构中给出的值
IPC_RMID:从系统中删除该消息队列以及仍在该队列中的所有数据
buf是指向nsgid_ds结构的指针,它指向消息队列模式和访问权限的结构