msgget函数用于创建一个新的消息队列或访问一个已存在的消息队列
IPC_NOWAIT标志使得msgsend调用非阻塞:如果没有存放新消息的可用空间,该函数就马上返回.这个条件可能发生的情况包括:
1.在指定的队列中已有太多的字节
2.在系统范围存在太多的消息
如果这两个条件中有一个存在,而且IPC_NOWAIT标志已指定,msgsnd就返回一个EAGAIN错误.如果这两个条件中有一个存在,但是IPC_NOWAIT标志未指定,那么调用纯种被投入睡眠.直到:
1.具备存放新消息的空间
2.由msqid标识的消息队列从系统中删除(这种情况下返回一个EIDRM错误)
3.调用线程被某个捕获的信号反中断(这种情况下返回一个EINTR错误)
msgctl函数提供一个消息队列上的各种控制操作
http://dash1982.iteye.com/blog/296583
MsgQueue.h
#ifndef MSGQUEUE_H
#define MSGQUEUE_H
namespace Utility
{
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
#define COMMON_MESSAGE 1
struct Message
{
long msgType;
int bufLen;
int addr;//地址
int reserved1;
int reserved2;
};
//初始化消息队列
int initMessageQueue(const char* msgfile,int& msgId,int msgType);
//关闭消息队列
int closeMessageQueue(int& msgId);
//清空消息
void clearMessage(int key,int& msgId,int msgType);
//发送普通消息
int sendMessage(const Message &msg,int msgId);
}//end of namespace Utility
#endif // MSGQUEUE_H
MsgQueue.cpp
#include "MsgQueue.h"
#include <sys/msg.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <iostream>
using namespace std;
namespace Utility
{
/*
清空消息
*/
void clearMessage(int key,int& msgId,int msgType)
{
int ret = 0;
msgId = msgget(key, 0660);
if (msgId<0){
return;
}
while (1)
{
if(msgType==COMMON_MESSAGE)
{
Message msg;
bzero(&msg,sizeof(msg));
ret=msgrcv(msgId, &msg, sizeof(msg), 0, IPC_NOWAIT);
if(ret<0){
break;
}
}
}
}
/*
初始化消息队列
*/
int initMessageQueue(const char* msgFile,int & msgId,int msgType)
{
//删除文件,避免引起不必要的问题,不删除可能会造成msgsend时卡死或发送失败的现象
unlink(msgFile);
msgId = -1;
int fid = open(msgFile, O_RDWR | O_CREAT, FILE_MODE);
if(fid<0)
{
cout << "创建文件:" << msgFile << "失败!" << endl;
return fid;
}
close(fid);
int key = ftok(msgFile, 'a');
if(key<0)
{
cout << "创建消息队列失败!" << endl;
return key;
}
if((msgId = msgget(key, IPC_CREAT | IPC_EXCL | 0660))==-1)
{
clearMessage(key,msgId,msgType);
if (msgId<0)
{
cout << "创建消息队列失败!" << strerror(errno) << endl;
return msgId;
}
}
cout << "初始化消息队列成功.msgFile:" << msgFile << ",msgId:" << msgId << endl;
return 0;
}
/*
关闭消息队列
*/
int closeMessageQueue(int& msgId)
{
int tmpMsgId = msgId;
int ret = msgctl(msgId, IPC_RMID, 0);
if(ret<0){
cout << "关闭消息队列失败" << endl;
}else{
cout << "关闭消息队列成功,msgId:" << tmpMsgId << endl;
}
return ret;
}
/*
发送普通信息
*/
int sendMessage(const Message &msg,int msgId)
{
int ret = msgsnd(msgId, &msg, sizeof(msg), IPC_NOWAIT);
if(ret<0){
cout << "向消息队列发送消息失败,msgId:" << msgId << endl;
}else{
cout << "向消息队列发送消息成功,msgId:" << msgId << ",长度:" << msg.bufLen << endl;
}
return ret;
}
}//end of namespace Utility
test
#include "MsgQueue.h"
#include <pthread.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <iostream>
using namespace std;
using namespace Utility;
int g_msgId = 0;
class A
{
public:
int value;
};
void* testRecvMessage(void*)
{
Message msg;//收数据的结构体
char rcvbuf[100];
bzero(rcvbuf,100);
int ret = 0;
while(true)
{
ret = msgrcv(g_msgId, &msg, sizeof(msg), 0, IPC_NOWAIT);
if (-1 != ret)
{
if(msg.msgType==COMMON_MESSAGE)
{
A** a = (A**)(msg.addr);
cout << "bufLen:" << msg.bufLen << ",value:" << (*a)->value << endl;
delete *a;
*a = NULL;
msg.addr = 0;
}
break;
}else
{
usleep(1000);
}
}
pthread_detach(pthread_self());
return 0;
}
int main()
{
pthread_t pid;
pthread_create(&pid,NULL,testRecvMessage,NULL);
int msgType = COMMON_MESSAGE;
initMessageQueue("/tmp/test1.msg",g_msgId,msgType);
A* a = new A;
a->value = 10;
Message message;
bzero(&message,sizeof(message));
message.msgType = COMMON_MESSAGE;
message.bufLen = sizeof(message);
message.addr = (int)&a;
sendMessage(message,g_msgId);
sleep(5);
closeMessageQueue(g_msgId);
}
初始化消息队列成功.msgFile:/tmp/test1.msg,msgId:32769
向消息队列发送消息成功,msgId:32769,长度:20
bufLen:20,value:10
关闭消息队列成功,msgId:32769