前言
消息队列与 FIFO 很相似,都是一个队列结构,都可以有多个进程往队列里面写信息,多个进程从队列中读取信息。但 FIFO 需要读、写的两端事先都打开,才能够开始信息传递工作。而消息队列可以事先往队列中写信息,需要时再打开读取信息。
System V IPC 机制消息队列的函数原型为:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
int msgsnd(int msgid, struct msgbuf *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msgid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg);
int msgctl(int msgid, int cmd, struct msqid_ds *buf);
一、msgget 函数
函数 msgget 创建和访问一个消息队列。
参数 key 是唯一标识一个消息队列的关键字,如果为 IPC_PRIVATE (值为 0 ,用于创建一个只有创建者进程才可以访问的消息队列),表示创建一个只由调用进程使用的消息队列;非 0 值的 key(可以通过 ftok 函数获得)表示创建一个可以被多个进程共享的消息队列;
参数 msgflg 指明队列的访问权限和创建标志,创建标志的可选值为 IPC_CREAT 和 IPC_EXCL ,如果单独指定 IPC_CREAT,msgget 要么返回新创建的消息队列 ID,要么返回具有相同 key 值的消息队列 ID ;如果 IPC_EXCL 和 IPC_CREAT 同时指明,则要么创建新的消息队列,要么当队列存在时,调用失败并返回 -1 。
函数成功的时候,返回一个消息队列的唯一标识符 ID(跟进程 ID 是一个类型),失败的时候,返回 -1。
二、msgsnd 函数
函数 msgsnd 和函数 msgrcy 用来将消息添加到消息队列中并从一个消息队列中获取信息。
参数 msgid 指明消息队列的 ID ,通常是 msgget 函数成功的返回值。
参数 msgbuf 是消息结构体,它的长度必须小于系统规定的上限,必须以一个长整型成员变量开始,接收函数将用这个成员变量来确定消息的类型。必须重写这个结构体,其中第一个参数不能改,其他自定义,如下:
struct msgbuf{
long mtype; /*type of message*/
char mtext[1]; /*message text*/
};
字段 mtype 是用户自己指定的消息类型(通常是 0~5 中的任意一个数值),该结构体第 2 个成员仅仅是一种说明性的结构,实际上用户可以使用任何类型的数据,就是消息内容。
参数 msgsz 是消息体的大小,每个消息体最大不要超过 4K;
参数 msgflg 可以为 0 (通常为 0 )或 IPC_NOWAIT,如果设置 IPC_NOWAIT,则 msgsnd 和 msgrcv 都不会阻塞,此时如果队列满并调用 msgsnd 或队列空时调用 msgrcv 将返回错误;也就是说如果没有设置为 IPC_NOWAIT ,则当队列满并调用 msgsnd 或队列空时调用 msgrcv 将会阻塞,直到队列条件满足为止。
参数 msgtyp 有 3 种选项:
msgtyp == 0 接收队列中的第 1 个消息(通常为 0 )
msgtyp > 0 接收队列中的第 1 个类型等于 msgtyp 的消息
msgtyp < 0 接收其类型小于或等于 msgtyp 绝对值的第 1 个最低类型消息
三、msgctl 函数
函数 msgctl 是消息队列的控制函数,常用来删除消息队列。
参数 msgid 是由 msgget 返回的消息队列标识符。
参数 cmd 通常为 IPC_RMID ,表示删除消息队列。
参数 buf 通常为 NULL 即可。
补充
另外,可用
ipcs -q 命令查看系统的消息队列;
ipcs -m 查看系统的共享内存;
ipcs -s 查看系统的信号量集。