一、消息队列概述
消息队列是一些消息的列表。用户可以从消息队列中添加消息和读取消息等。消息队列具有一定的FIFO特性,但是它可以实现消息的随机查询,比FIFO具有更大的优势。这些消息存在于内核中,由“队列ID”标识。
二、消息队列的应用
(1)函数说明
消息队列的实现包括创建或打开消息队列、添加消息、读取消息和控制消息队列:
(1) msgget()创建或打开消息队列:创建的消息队列的数量会受到系统消息队列数量的限制
(2) msgsnd()添加消息:它把消息添加到已打开的信息队列末尾
(3) msgrcv()读取消息:它把消息从消息队列中取走,与FIFO不同的是,这里可以指定取走某一条消息
(4) msgclt()控制消息队列:它可以完成多项功能
(2)函数格式
msgget()函数语法要点
所需头文件 |
#include
#include
#include
函数原型 |
int msgget(key_t key,int msgflg)
函数传入值 |
key:消息队列的键值,多个进程可以通过它访问同一个消息队列,其中有个特殊值IPC_PRIVATE。它用于创建当前进程的私有消息队列。
msgflg:权限标志位
函数返回值 |
成功:消息队列ID
出错:-1
msgsnd()函数语法要点
所需头文件 |
#include
#include
#include
函数原型 |
int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg)
函数传入值 |
msgid:消息队列的队列ID
msgp:指向消息结构的指针。该消息结构msgbuf通常为:
struct msgbuf
{
long mtype; /* 消息类型,该结构必须从这个域开始 */
char mtext[1]; /* 消息正文 */
}
msgsz:消息正文的字节数(不包括消息类型指针变量)
msgflg:
IPC_NOWAIT若消息无法立即发送(比如:当消息队列已满),函数会立即返回
0:msgsnd调阻塞直到发送成功为止
函数返回值 |
成功:0
出错:-1
msgrcv()函数语法要点
所需头文件 |
#include
#include
#include
函数原型 |
int msgrcv(int msgid,void *msgp,size_t msgsz,long int msgtyp,int msgflg)
函数传入值 |
msqid:消息队列的队列ID
msgp:消息缓冲区,同于msgsnd()函数的msgp
msgsz:消息正文的字节数(不包括消息类型指针变量)
msgtyp:
0:接收消息队列中第一个消息
大于0:接收消息队列中第一个类型为msgtyp的消息
小于0:接收消息队列中第一个类型值不小于msgtyp绝对值且类型值又最小的消息
msgflg:
MSG_NOERROR:若返回的消息比msgsz字节多,则消息就会截短到msgsz字节,且不通知消息发送进程
IPC_NOWAIT:若在消息队列中并没有相应类型的消息可接收,则函数立即返回
0:msgrcv()调用阻塞直到接收到一条相应类型的消息为止
函数返回值 |
成功:0
失败:-1
msgctl()函数语法要点
所需头文件 |
#include
#include
#include
函数原型 |
int msgctl(int msgid,int cmd,struct msgid_ds *buf)
函数传入值 |
msgid:消息队列的队列ID
cmd:
参数命令
IPC_STAT:读取消息队列的数据结构msgid_ds,并将其存储在buf指定的地址中
IPC_SET:设置消息队列的数据结构msgid_ds中的ipc_perm域(IPC操作权限描述结构)值。这个值取自buf参数。
IPC_RMID:从系统中删除消息队列
buf:描述消息队列的msgid_ds结构类型变量
函数返回值 |
成功:0
出错:-1
(3)使用实例
msgsnd.c
/* msgsnd.c */
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFSIZE 512
struct msgbuf
{
long mtype;
char mtext[BUFSIZE];
};
int main()
{
int msgid;
struct msgbuf msg;
if((msgid = msgget((key_t)1234,IPC_CREAT|0666)) == -1)
{
printf("SEND:msgget error.
");
exit(1);
}
while(1)
{
if(fgets(msg.mtext,BUFSIZE,stdin) == NULL)
{
printf("SEND:fgets error.
");
exit(1);
}
msg.mtype = getpid();
if(msgsnd(msgid,&msg,BUFSIZE,0) == -1)
{
printf("SEND:msgsnd error.
");
exit(1);
}
if(strncmp(msg.mtext,"quit",4) == 0)
{
break;
}
}
exit(0);
}
msgrcv.c
/* msgrcv.c */
#include
#include
#include
#include
#include
#include
#include
#define BUFSIZE 512
struct msgbuf
{
long mtype;
char mtext[BUFSIZE];
};
int main()
{
int msgid;
struct msgbuf msg;
if(msgid = msgget((key_t)1234,IPC_CREAT|0666) == -1)
{
printf("RECV:msgget error.
");
exit(1);
}
do
{
memset(msg.mtext,0,BUFSIZE);
if(msgrcv(msgid,(void *)&msg,BUFSIZE,0,0) == -1)
{
printf("RECV:msgrcv error.
");
exit(1);
}
printf("RECV:%s
",msg.mtext);
}while(strncmp(msg.mtext,"quit",4));
if(msgctl(msgid,IPC_RMID,NULL) == -1)
{
printf("RECV:msgctl(IPC_RMID) error.
");
exit(1);
}
exit(0);
}