消息队列允许进程以消息的形式交换数据。
1、创建或者打开一个消息队列
msgget()系统调用创建一个新消息队列或者打开一个既有消息队列的标志符:
#include <sys/types.h>
#include <sys/msg.h>
int msgget(key_t key,int msgflg);
Return message queue identifier on success,or -1 on error.
参数key:是ftok()函数生成的一个键,或者=IPC_PRIVATE。
参数msgflg:是一个指定施加于新消息队列之上的权限或检查一个既有队列的权限掩码。可以指定open()函数中的标志,还可以指定以下参数:
IPC_CREAT:
如果没有与指定的key对应的消息队列,那么就创建一个新队列。
IPC_EXCL:
如果同时还指定了IPC_CREAT,并且与指定的key对应的队列已经存在,那么调用就会失败并返回EEXIST错误。
2、利用消息队列发送信息
msgsnd()系统调用向消息队列中写入一条消息
#include <sys/types.h>
#include <sys/msg.h>
int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);
Return 0 On success,or -1 on error.
使用msgsnd()函数发送消息必须将消息结构中的mtype字段的值设为一个大于0的值并将所需传递的信息复制到程序员定义的mtext字段中,
struct mymsg
{
long mtype; /*Message type*/
char mtext[]; /*Message body*/
}
参数msgsz:指定结构体mymsg中的mtext字段中包含的字节数。
参数msgflg:指定一组掩码,用于msgsnd()的操作。如下:
IPC_NOWAIT:执行一个非阻塞的发送操作。
3、利用消息队列进行接收消息
msgrcv()函数调用从消息队列中读取一条消息并将其内容复制进入msgp指向的缓冲区中。
#include <sys/types.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t maxmsgs, long msgtyp, int msgflg)
Return number of bytes copied into mtext field,or -1 on error
msgp缓冲区中mtext字段的最大可用空间是通过maxmsgsz参数来指定的。如果队列中待删除的消息体的大小超过了maxmsgsz字节,那么就不会从队列中删除消息,并且msgrcv()会返回错误E2BIG。
读取消息的顺序无需与消息被发送一致。可以根据mtype字段的值来选择消息,而这个过程由msgtyp参数来控制,具体如下:
- 如果msgtyp等于0,那么会删除队列的第一条消息并将其返回给调用进程。
- 如果msgtyp大于0,那么会将队列中第一条mtype等于msgtyp的消息删除并将其返回给调用进程。
- 如果msgtyp小于0,那么就会将等待消息当成优先队列来处理。
参数msgflg是一个位掩码,其值可以通过将下列标记中的零个或者多个取OR来确定。
IPC_NOWAIT:
执行一个非阻塞接收。
MSG_EXCEPT:
此标记为Linux特有。只有当msgtyp大于0 时这个标记才会起作用,会强制对常规操作进行补足,即将队列中的第一条mtype不等于msgtyp的消息删除并将其返还给调用者。
MSG_NOERROR
当mtext字段的大小超出了可用空间,如果指定了该值,那么msgrcv()会从队列中删除消息并将其mtext字段的大小截短weimaxmsgsz字节,然后将消息返还给调用者,被截去的数据将会丢失。