跟Posix消息队列一样,不存在这样的要求:某个进程往一个队列中写入一个消息,另外一个进程下在等待该队列上一个消息的到达
系统中的消息队列,定义在<sys/msg.h>头文件中的信息结构:
struct msqid_ds
{
struct ipc_perm msg_perm;读写权限
struct msg *msg_first;队列中的第一个消息
struct msg *msg_last;队列中的最后一个消息
msglen_t msg_cbytes;队列中的字节数
msgqnum_t msg_qnum;队列中的消息数
msglen_t msg_qbytes;队列上的允许的最大字节数
pid_t msg_lspid;前一个用msgsnd()的进程id
pid_t msg_lrpid;前一个用msgrcv()的进程id
time_t msg_stime;前一个用msgsnd()的时间
time_t msg_rtime;前一个用msgrcv()的时间
time_t msg_ctime;前一个msgctl()的时间
};
1、msgget函数
用于创建一个新的消息队列或访问一个已存在的消息队列
#include <sys/msg.h>
int msgget(key_t key, int oflag);
成功返回非负标识符,失败返回-1
返回值是一个整数标识符,key可以是ftok的返回值 ,也可以是常值IPC_PRIVATE,oflag可以有MSG_R(0400),MSG_W(0200),MSG_R>>3(0040),MSG_W>>3(0020),MSG_R>>6(0004),MSG_W(0002),也可以与IPC_CREAT和IPC_EXCL按位或
MSG_R:用户(属主)读
MSG_W:用户(属主)写
MSG_R>>3:由(属)组成员读
MSG_W>>3:由(属)组成员写
MSG_R>>6:由其他用户读
MSG_W>>6:由其他用户写
当创建一个新的消息队列时,msqid_ds结构的如下成员被初始化:
(1)msg_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cgid成员被设置成当前进程的有效组ID
(2)oflags中的读写权限位存放在msg_perm.mode中
(3)msg_qnum,msg_lspid,msg_lrpid,msg_stime,msg_rtime被置为0
(4)msg_ctime被设置成当前时间
(5)msg_qbytes被设置成系统限制值
2、msgsnd函数
往队列中放入一个消息
#include <sys/msg.h>
int msgsnd(int msqid, const void *ptr, size_t length, int flag);
成功返回0,失败返回-1
ptr是一个结构指针,该结构有如下模板,定义在<sys/msg.h>中
struct msgbuf
{
long mbyte; 消息类型
char mtext[1]; 消息数据
};
消息类型要大于0
flag参数可以是0,也可以是IPC_NOWAIT。IPC_NOWAIT标志使得msgsnd调用非阻塞,如果没有存放消息的可有空间,函数立即返回。发生情况包括:
(1)在队列中已有太多的字节 msqid_ds结构中的msg_qbytes
(2)在系统范围存在太多的消息
如果这两个条件中有一个存在,而且IPC_NOWAIT标志已指定,msgsnd返回一个EAGAIN错误
3、msgrcv函数
从队列中读出一个消息
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *ptr, size_t length, long byte, int flag);
成功返回读入缓冲区数据的字节数,失败返回-1
type指定希望从给定的队列中读出什么样的消息
(1)type == 0,返回该队列中的第一个消息
(2)type > 0,返回类型值为type的第一个消息
(3)type < 0,返回类型值<=type参数的绝对值的消息中类型值最小的第一个消息
flag指定所请求的消息不在队列时的处理。在没有消息可得的情况下,如果设置了IPC_NOWAIT位,立即返回一个ENOMSG错误,否则阻塞到下列某个事件发生为止
(1)有一个所请求类型的消息可获取
(2)由msqid标识的消息队列被从系统中删除
(3)调用线程被某个捕获的信号所中断
flag参数中另有一位可以指定MSG_NOERROR,当所接收消息的真正数据部分大于length参数时,如果设置了该位,msgrcv函数只是截短数据部分,而不返回错误,否则,返回一个E2BIG错误
4、msgctrl函数
在消息队列上的控制操作
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buff);
成功返回0,失败返回-1
有三个命令:
(1)IPC_RMID:从系统中删除msqid指定的消息队列。当前在该队列上的任何消息都被丢弃
(2)IPC_SET:给队列设置其中的msqid_ds结构的四个成员:msg_perm.uid, msg_perm.gid, msg_perm.mode和msg_qbytes
(3)IPC_STAT:给调用者返回指定队列的当前msqid_ds结构