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#include #include #include #include #include #include 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#include #include #include #include #include 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