一、消息队列概述
消息队列是一些消息的列表。用户可以从消息队列中添加消息和读取消息等。消息队列具有一定的FIFO特性,但是它可以实现消息的随机查询,比FIFO具有更大的优势。这些消息存在于内核中,由“队列ID”标识。
二、消息队列的应用
(1)函数说明
消息队列的实现包括创建或打开消息队列、添加消息、读取消息和控制消息队列:
(1) msgget()创建或打开消息队列:创建的消息队列的数量会受到系统消息队列数量的限制 |
(2) msgsnd()添加消息:它把消息添加到已打开的信息队列末尾 |
(3) msgrcv()读取消息:它把消息从消息队列中取走,与FIFO不同的是,这里可以指定取走某一条消息 |
(4) msgclt()控制消息队列:它可以完成多项功能 |
(2)函数格式
所需头文件 | #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> |
---|---|
函数原型 | int msgget(key_t key,int msgflg) |
函数传入值 | key:消息队列的键值,多个进程可以通过它访问同一个消息队列,其中有个特殊值IPC_PRIVATE。它用于创建当前进程的私有消息队列。 |
msgflg:权限标志位 | |
函数返回值 | 成功:消息队列ID |
出错:-1 |
所需头文件 | #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> | |
---|---|---|
函数原型 | 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 |
所需头文件 | #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> | |
---|---|---|
函数原型 | 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 |
所需头文件 | #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> | |
---|---|---|
函数原型 | 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 <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#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.\n");
exit(1);
}
while(1)
{
if(fgets(msg.mtext,BUFSIZE,stdin) == NULL)
{
printf("SEND:fgets error.\n");
exit(1);
}
msg.mtype = getpid();
if(msgsnd(msgid,&msg,BUFSIZE,0) == -1)
{
printf("SEND:msgsnd error.\n");
exit(1);
}
if(strncmp(msg.mtext,"quit",4) == 0)
{
break;
}
}
exit(0);
}
msgrcv.c
/* msgrcv.c */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#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.\n");
exit(1);
}
do
{
memset(msg.mtext,0,BUFSIZE);
if(msgrcv(msgid,(void *)&msg,BUFSIZE,0,0) == -1)
{
printf("RECV:msgrcv error.\n");
exit(1);
}
printf("RECV:%s\n",msg.mtext);
}while(strncmp(msg.mtext,"quit",4));
if(msgctl(msgid,IPC_RMID,NULL) == -1)
{
printf("RECV:msgctl(IPC_RMID) error.\n");
exit(1);
}
exit(0);
}