本例中使用一个文件路径加上课题ID(0~255)调用ftok函数产生一个关键字。
代码如下:
CMsgQueue.h
/*************************************************************************
> File Name: CMsgQueue.h
> Author: KentZhang
> Mail: [email protected]
> Created Time: Wed 02 Sep 2015 08:10:35 PM CST
************************************************************************/
#ifndef _CLASSES_CMSGQUEUE_H__
#define _CLASSES_CMSGQUEUE_H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
//封装消息队列
class CMsgQueue
{
public:
CMsgQueue(const char* path, int id);
~CMsgQueue();
bool MsgGet();
bool MsgCreat();
bool MsgSnd(const void *msg, size_t nbytes, int flag);
bool MsgRcv(void *msg, size_t nbytes, long type, int flag);
int GetMsgQueueID();
bool Destroy();
private:
int m_MsgQueueID;//消息队列的ID
key_t m_MsgKey; //创建消息队列需要的关键字
};
#endif
CMsgQueue.cpp
/*************************************************************************
> File Name: CMsgQueue.cpp
> Author: KentZhang
> Mail: [email protected]
> Created Time: Wed 02 Sep 2015 08:20:14 PM CST
************************************************************************/
#include "CMsgQueue.h"
#ifndef RELEASE
#define DEBUG_ERROR(format,...) do{ printf(""format", FileName:%s, FuncName:%s, LineNum:%d\n",\
##__VA_ARGS__, __FILE__, __func__, __LINE__);}while(0)
#else
//当软件release时,这个宏应该把出错信息写入文件中,当然要考虑多线程的情况,此处代码省略
#define DEBUG_ERROR(format,...) do{ /*此处代码省略*/ }while(0)
#endif
//构造函数中只是产生一个关键字
CMsgQueue::CMsgQueue(const char* path, int id)
{
m_MsgKey = ftok(path, id);
if (m_MsgKey < 0 )
{
DEBUG_ERROR("CMsgQueue() ftok(%s, %d) failed:%s", path, id, strerror(errno));
}
m_MsgQueueID = -1;
}
CMsgQueue::~CMsgQueue()
{
//在析构函数中,如果调用msgctl函数删除消息队列,
//那么有可能别的进程正在使用,因此谁创建,应该由
//谁调用Destory函数删除
}
//打开或者新建一个消息队列
bool CMsgQueue::MsgGet()
{
m_MsgQueueID = msgget(m_MsgKey, IPC_CREAT|0666);
if(-1 == m_MsgQueueID)
{
DEBUG_ERROR("CMsgQueue::MsgGet() failed:%s", strerror(errno));
return false;
}
return true;
}
//新创建消息队列
//有时候进程非正常退出时,消息队列没有删除,如果里面还有消息,
//将对程序的下一次运行产生影响,下面的函数可保证是新创建的消息队列
bool CMsgQueue::MsgCreat()
{
int nQueueID = msgget(m_MsgKey, IPC_CREAT|IPC_EXCL|0666);
if(-1 == nQueueID)
{
this->MsgGet();
msgctl(m_MsgQueueID, IPC_RMID, NULL);
m_MsgQueueID = 0;
return this->MsgGet();
}
m_MsgQueueID = nQueueID;
return true;
}
//发送消息
bool CMsgQueue::MsgSnd(const void *msg, size_t nbytes, int flag)
{
int nResult = msgsnd(m_MsgQueueID, msg, nbytes, flag);
if( -1 == nResult)
{
DEBUG_ERROR("CMsgQueue::msgSnd() failed:%s", strerror(errno));
return false;
}
return true;
}
//接收消息
bool CMsgQueue::MsgRcv(void *msg, size_t nbytes, long type, int flag)
{
int nResult = msgrcv(m_MsgQueueID,msg, nbytes, type, flag);
if( -1 == nResult)
{
DEBUG_ERROR("CMsgQueue::msgRcv() failed:%s", strerror(errno));
return false;
}
return true;
}
//获得消息队列ID
int CMsgQueue::GetMsgQueueID()
{
return m_MsgQueueID;
}
//删除消息队列
bool CMsgQueue::Destroy()
{
int nResult = msgctl(m_MsgQueueID, IPC_RMID, NULL);
if(-1 == nResult)
{
DEBUG_ERROR("CMsgQueue::Destroy() failed:%s", strerror(errno));
return false;
}
return true;
}
由于笔者的水平有限,出错在所难免,恳请读者拍砖指正,谢谢阅读。