消息队列就是具有足够权限的任何进程都可以往一个给定队列中放置一个消息,具有足够特权的任何进程都可以从一个给定队列中读出一个消息。在某个进程往一个队列中邪热一个消息之前,不求另外某个进程中在等待该队列上一个消息的到达。
消息队列可以视为一个消息链表。
相关函数为:
1,int msgget(key_t key,int oflag),该函数用于创建一个新的队列或访问一个已经存在的消息队列
系统调用msgget()中的第一个参数是关键字值(通常是由ftok()返回的)。然后此关键字值将会和其他已经存在于系统内核中的关键字值比较。这时,打开和存取操作是和参数msgflg中的内容相关的。
IPC_CREAT如果内核中没有此队列,则创建它。
IPC_EXCL当和IPC_CREAT一起使用时,如果队列已经存在,则失败。
如果单独使用IPC_CREAT,则msgget()要么返回一个新创建的消息队列的标识符,要么返回具有相同关键字值的队列的标识符。如果IPC_EXCL和IPC_CREAT一起使用,则msgget()要么创建一个新的消息队列,要么如果队列已经存在则返回一个失败值-1。IPC_EXCL单独使用是没有用处的。
2,int msgsnd(ing msgid,const void * ptr,size_t length,int flag) 该函数用于添加一个消息,msgid 为msgget函数成功返回的消息队列的标识符。ptr为自定义消息的指针。length为消息的大小,flag一般为0。
3,size_t msgrcv(int msgid,void × ptr,size_t length,long type,int flag);
返回值: 成功则返回消息的数据部分的长度, 出错则返回-1.
参数:
ptr: 指向一个长整型数(返回的消息类型存放在其中), 跟随其后的是存放实际消息数据的缓冲区.
nbytes: 数据缓冲区的长度. 若返回的消息大于nbytes, 且在flag中设置了MSG_NOERROR, 则该消息被截短.
type:
type == 0: 返回队列中的第一个消息.
type > 0: 返回队列中消息类型为type的第一个消息.
type < 0: 返回队列中消息类型值小于或等于type绝对值的消息, 如果这种消息有若干个, 则取类型值最小的消息.
说明: 当msgrcv成功返回时, 与消息队列相关的msqid_ds结构被更新, 以指示调用者的进程ID(msg_lrpid), 调用时间(msg_rtime)和队列中的消息数(msg_qnum)减1.
4,int msgctl(int msgid,int cmd,struct msqid_ds,×buf);消息队列的各种控制操作。
返回值: 成功则返回0, 出错则返回-1.
参数: cmd参数说明对msqid指定的队列要执行的命令:
IPC_STAT: 取此队列的msqid_ds结构, 并将它存放在buf指向的结构中.
IPC_SET: 按由buf指向结构中的值, 设置与此队列相关结构中的msg_perm.uid, msg_perm.gid, msg_perm.mode和msg_qbytes. 该命令只有下列两种进程可以执行:
有效用户ID等于msg_perm.cuid或msg_per.uid.
具有超级用户特权的进程.
IPC_RMID: 从系统中删除该消息队列以及仍在该队列中的所有数据. 执行权限同上.
实例
//client.cpp
#include <iostream>
#include "stdio.h"
#include "sys/msg.h"
#include "sys/ipc.h"
#include "sys/types.h"
#include "stdlib.h"
#include "string.h"
#define MAX_LINE 70
using namespace std;
typedef struct {
long type;
int fval;
int pid;
char strval[MAX_LINE];
} MY_TYPE_T;
int main() {
int msgid,selfid;
struct msqid_ds buf;
selfid=msgget(getpid(),0666|IPC_CREAT);
if (selfid > 0) {
printf("Client Message create OK!");
}
msgctl(selfid, IPC_STAT, &buf);
buf.msg_qbytes = 4096;
int ret = msgctl(selfid, IPC_SET, &buf);
if (ret == 0) {
printf("Size sucessfully changed for queue,message queue identifier is %d\n",
selfid);
}
msgid = msgget(1234,IPC_CREAT);
if (msgid > 0) {
printf("System Message Open OK!");
}
MY_TYPE_T msgb;
msgb.type=1;
msgb.fval=1;
msgb.pid=getpid();
bool flag;
flag=true;
int result;
MY_TYPE_T *recvMessage;
while(flag)
{
memset(msgb.strval,0,sizeof(msgb.strval));
cout<<"请输入数据:"<<endl;
cin>>msgb.strval;
result=msgsnd(msgid,&msgb,sizeof(MY_TYPE_T),0);
if(result!=-1){
printf("msgsnd Message msgb secessfull!\n");
}
recvMessage =(MY_TYPE_T *)malloc(sizeof(MY_TYPE_T));
int ret=msgrcv(selfid,recvMessage,sizeof(MY_TYPE_T),1,0);
if(ret>0){
printf("recv Message data is %s\n",recvMessage->strval);
}
}
//server.cpp
#include <iostream>
#include "stdio.h"
#include "sys/msg.h"
#include "sys/ipc.h"
#include "sys/types.h"
#include "stdlib.h"
#include "string.h"
#define MAX_LINE 70
#define MO_KEY12 1234;
using namespace std;
typedef struct {
long type;
int fval;
int pid;
char strval[MAX_LINE];
} MY_TYPE_T;
int main() {
int msgid, clientid;
struct msqid_ds buf;
msgid = msgget(1234, 0666 | IPC_CREAT);
if (msgid > 0) {
printf("System Message Create OK!");
}
msgctl(msgid, IPC_STAT, &buf);
buf.msg_qbytes = 4096;
int ret = msgctl(msgid, IPC_SET, &buf);
if (ret == 0) {
printf(
"Size sucessfully changed for queue,message queue identifier is %d\n",
msgid);
}
MY_TYPE_T *recvMessage;
bool flag;
flag = true;
while (flag) {
recvMessage = (MY_TYPE_T *) malloc(sizeof(MY_TYPE_T));
int ret = msgrcv(msgid, recvMessage, sizeof(MY_TYPE_T), 1, 0);
if (ret > 0) {
printf("recv Message data is %s\n", recvMessage->strval);
} else {
delete (recvMessage);
flag = false;
break;
}
clientid = msgget(recvMessage->pid, IPC_CREAT);
if(clientid<0)
{
printf("open client Message error!\n");
return -1;
}
memset(recvMessage->strval,0,sizeof(MY_TYPE_T));
memcpy(recvMessage->strval,"ServerRecv",sizeof("ServerRecv"));
msgsnd(clientid,recvMessage,sizeof(MY_TYPE_T),0);
}
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
编译client和server后,先运行server,再运行client