1. MsgQue.h
#ifndef MSG_QUE_H #define MSG_QUE_H #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <sys/ipc.h> #include <sys/types.h> #include <sys/msg.h> #include "Typedef.h" #include "./Print.h" #define MSG_QUE_SERVER 0 //消息队列作为服务端 #define MSG_QUE_CLIENT 1 //消息队列作为客户端 #define MSG_QUE_LEN 2048 //消息队列数据长度 //消息队列缓冲区 typedef struct{ int iKey; //发送或接收的微应用key值,例如A发往B,这里的key值表示B的键值 char buf[MSG_QUE_LEN]; //消息缓冲区 int iLen; //消息的有效长度 }TMsgBuf; //IPC消息队列 typedef struct { long iMsgtype; //消息类型 TMsgBuf tMsgBuf; //消息数据 }TMsgQue; class CMsgQue{ public: //描述:IPC消息队列构造函数 //参数:@key IPC键值,4字节16进制表示 // @fDebugInfo 用于调试信息输出 CMsgQue(key_t key, bool fDebugInfo=true); //描述:析构函数 ~CMsgQue(); private: CPrint *m_pCPrint; key_t m_key; int m_iMsgId; //描述:创建消息队列 //参数:无 //返回:小于0失败,反之成功 int MsgQueCreate(); //描述:销毁消息队列 //参数:无 //返回:小于0失败,反之成功 int MsgQueDestory(); public: //描述:消息发送 //参数:@pTMsgBuf 发送消息结构体 // @iBlockMode 阻塞模式,IPC_NOWAIT--非阻塞,0--阻塞 //返回:小于0失败,反之为发送的字节数 int MsgSend(const TMsgBuf *pTMsgBuf, int iBlockMode=IPC_NOWAIT); //描述:消息接收 //参数:@pTMsgBuf 接收消息结构体 // @iBlockMode 阻塞模式,IPC_NOWAIT--非阻塞,0--阻塞 //返回:小于0失败,反之为接送的字节数 int MsgRecv(TMsgBuf *pTMsgBuf, int iBlockMode=IPC_NOWAIT); }; //描述:消息队列初始化 void MsgQueInit(void); //描述:消息队列释放 void MsgQueFree(void); //描述:消息队列请求 //参数:@iKey 消息队列键值 //返回:成功返回iKey所属消息队列对象,否则为NULL CMsgQue * MsgQueReq(int iKey); //描述:消息队列发送 //参数:@pCMQ 发送的消息队列对象 // @pMsgBuf 发送的消息队里数据 // @iBlockMode 阻塞模式,IPC_NOWAIT--非阻塞,0--阻塞 //返回:小于0失败,反之为发送的字节数 int MsgQueSend(CMsgQue *pCMQ, const TMsgBuf *pMsgBuf, int iBlock=IPC_NOWAIT); //描述:消息队列接收 //参数:@pCMQ 接收的消息队列对象 // @pMsgBuf 接收的消息队里数据 // @iBlockMode 阻塞模式,IPC_NOWAIT--非阻塞,0--阻塞 //返回:小于0失败,反之为接送的字节数 int MsgQueRecv(CMsgQue *pCMQ, TMsgBuf *pMsgBuf, int iBlock=IPC_NOWAIT); #endif //MSG_QUE_H2. MsgQue.cpp
#include "MsgQue.h" #include <unistd.h> #include <execinfo.h> #include <signal.h> //微应用app所属键值,每个app都需要一个唯一的键值,不能冲突! //键值添加使用规则: //1.宏定义增加 //2.将宏定义的键值添加到g_key[]数组中 //微应用内部使用规则 : //1. MsgQueInit() //2. MsgQueReq(key) //由上面宏定义填充的键值 //3. MsgQueRecv() //4. MsgQueSend() //5. MsgQueFree() #define IPC_KEY_APP0 1 #define IPC_KEY_APP1 2 #define IPC_KEY_APP2 3 static int g_key[] = {IPC_KEY_APP0, IPC_KEY_APP1, IPC_KEY_APP2}; static int g_keyNum = sizeof(g_key)/sizeof(g_key[0]); //描述:IPC消息队列构造函数 //参数:@key IPC键值,4字节16进制表示 // @fDebugInfo 用于调试信息输出 CMsgQue::CMsgQue(key_t key, bool fDebugInfo) { m_key = key; m_pCPrint = new CPrint(); MsgQueCreate(); } //描述:析构函数 CMsgQue::~CMsgQue() { MsgQueDestory(); delete m_pCPrint; } //描述:创建消息队列 //参数:无 //返回:小于0失败,反之成功 int CMsgQue::MsgQueCreate() { if ((m_iMsgId=msgget(m_key, IPC_CREAT)) < 0) { if ((m_iMsgId=msgget(m_key, IPC_CREAT|IPC_EXCL|0666)) < 0) m_pCPrint->PrintStr("CMsgQue::MsgQueCreate:msgget: %s\n", strerror(m_iMsgId)); } if (m_iMsgId > 0) m_pCPrint->PrintStr("CMsgQue::MsgQueCreate:msgget: key=0xx, iMsgId=0xx\n", m_key, m_iMsgId); return m_iMsgId; } //描述:销毁消息队列 //参数:无 //返回:小于0失败,反之成功 int CMsgQue::MsgQueDestory() { int iRet; if((iRet=msgctl(m_iMsgId, IPC_RMID, NULL)) < 0) { perror("CMsgQue::DestoryMsgQue:msgctl"); return -1; } return iRet; } //描述:消息发送 //参数:@pTMsgBuf 发送消息结构体 // @iBlockMode 阻塞模式,IPC_NOWAIT--非阻塞,0--阻塞 //返回:小于0失败,反之为发送的字节数 int CMsgQue::MsgSend(const TMsgBuf *pTMsgBuf, int iBlockMode) { TMsgQue tMsgQue; if ((pTMsgBuf->iLen+4) > MSG_QUE_LEN) { m_pCPrint->PrintStr("IpcMsgQue::MsgSend: MSG_QUE_LEN=%d < iLen=%d over len!!!\n", MSG_QUE_LEN, pTMsgBuf->iLen+4); return -1; } memset((BYTE*)&tMsgQue, 0, sizeof(tMsgQue)); tMsgQue.tMsgBuf = *pTMsgBuf; tMsgQue.iMsgtype = 0x01; return msgsnd(m_iMsgId, (void*)&tMsgQue, sizeof(tMsgQue.tMsgBuf), iBlockMode); //非阻塞模式 } //描述:消息接收 //参数:@pikey 接收到消息的key值 // @pbBuf 待接收的缓冲区 // @iLen pbBuf最大接收缓冲区长度 // @iBlockMode 阻塞模式,IPC_NOWAIT--非阻塞,0--阻塞 //返回:小于0失败,反之为接送的字节数 int CMsgQue::MsgRecv(TMsgBuf *pTMsgBuf, int iBlockMode) { TMsgQue tMsgQue; int iRet; memset((BYTE*)&tMsgQue, 0, sizeof(tMsgQue)); if((iRet=msgrcv(m_iMsgId, (void*)&tMsgQue, sizeof(tMsgQue.tMsgBuf), 0, iBlockMode)) < 0) //非阻塞模式 return iRet; *pTMsgBuf = tMsgQue.tMsgBuf; return pTMsgBuf->iLen; } static CMsgQue **g_ppCMsgQue; //描述:消息队列初始化 void MsgQueInit(void) { int iKeyidx; g_ppCMsgQue = new CMsgQue * [g_keyNum]; if (g_ppCMsgQue != NULL) { for (iKeyidx=0; iKeyidx<g_keyNum; iKeyidx++) g_ppCMsgQue[iKeyidx] = new CMsgQue(g_key[iKeyidx]); } } //描述:消息队列释放 void MsgQueFree(void) { int iKeyidx; for (iKeyidx=0; iKeyidx<g_keyNum; iKeyidx++) delete[] g_ppCMsgQue[iKeyidx]; delete[] g_ppCMsgQue; } //描述:消息队列请求 //参数:@iKey 消息队列键值 //返回:成功返回iKey所属消息队列对象,否则为NULL CMsgQue * MsgQueReq(int iKey) { int iKeyidx; for (iKeyidx=0; iKeyidx<g_keyNum; iKeyidx++) { if (g_key[iKeyidx] == iKey) { //printf("GetMsgQue: iKey=%d\n", iKey); return g_ppCMsgQue[iKeyidx]; } } return NULL; } //描述:消息队列发送 //参数:@pCMQ 发送的消息队列对象 // @pMsgBuf 发送的消息队里数据 // @iBlockMode 阻塞模式,IPC_NOWAIT--非阻塞,0--阻塞 //返回:小于0失败,反之为发送的字节数 int MsgQueSend(CMsgQue *pCMQ, const TMsgBuf *pMsgBuf, int iBlock) { return pCMQ->MsgSend(pMsgBuf, iBlock); } //描述:消息队列接收 //参数:@pCMQ 接收的消息队列对象 // @pMsgBuf 接收的消息队里数据 // @iBlockMode 阻塞模式,IPC_NOWAIT--非阻塞,0--阻塞 //返回:小于0失败,反之为接送的字节数 int MsgQueRecv(CMsgQue *pCMQ, TMsgBuf *pMsgBuf, int iBlock) { return pCMQ->MsgRecv(pMsgBuf, iBlock); }3. main.cpp
#include "MsgQue.h" #include <unistd.h> #include <execinfo.h> #include <signal.h> int main(int argc, char *argv[]) { CMsgQue *pCMQ_Ser, *pCMQ_Cli; char bBuf[1024]; int iKey, iKeyRecv, iRet; char c; TMsgBuf tMsgBuf; if (argc != 2) { printf("argc=2, current argc=%d.\n", argc); printf("Example: ./MsgQue X, X is 0, 1, 2,...\n"); exit(0); } else { printf("iKey = 0xx\n", iKey=atoi(argv[1])); //1. 注册所有微应用key值 MsgQueInit(); //2. 获取当前微应用的key值消息队列对象 if ((pCMQ_Ser=MsgQueReq(iKey)) != NULL) { printf("Press 's' send, 'r' receive!\n"); c = getchar(); printf("Recv char=%c.\n", c); //while (1) { if (c == 'r') { while (1) { memset((BYTE*)&tMsgBuf, 0, sizeof(tMsgBuf)); if (MsgQueRecv(pCMQ_Ser, &tMsgBuf, 0) > 0) { printf("Current key=%d: Recv from key=%d,buf=%s\n", iKey, tMsgBuf.iKey, tMsgBuf.buf); if ((pCMQ_Cli=MsgQueReq(tMsgBuf.iKey)) != NULL) { iKeyRecv = tMsgBuf.iKey; memset((BYTE*)&tMsgBuf, 0, sizeof(tMsgBuf)); tMsgBuf.iKey = iKey; strcpy(tMsgBuf.buf, "hello world!"); tMsgBuf.iLen = strlen(tMsgBuf.buf); printf("Current key=%d: send to key=%d, buf=%s\n", iKey, iKeyRecv, tMsgBuf.buf); if (((iRet=MsgQueSend(pCMQ_Cli, &tMsgBuf, 0))) < 0) printf("Current key=%d: send to key=%d, error=%s\n", iKey, tMsgBuf.iKey, strerror(iRet)); } } } } else if (c == 's') { memset((BYTE*)&tMsgBuf, 0, sizeof(tMsgBuf)); tMsgBuf.iKey = 0x02; //默认要发往的key对象 strcpy(tMsgBuf.buf, "hello world!"); tMsgBuf.iLen = strlen(tMsgBuf.buf); if ((pCMQ_Cli=MsgQueReq(0x01)) != NULL) //获取接收到的消息所属key值对象 { printf("Current key=%d: send to key=%d, buf=%s\n", iKey, tMsgBuf.iKey, tMsgBuf.buf); if (((iRet=MsgQueSend(pCMQ_Cli, &tMsgBuf, 0))) < 0) printf("Current key=%d: send to key=%d, error=%s\n", iKey, tMsgBuf.iKey, strerror(iRet)); } while (1) { memset((BYTE*)&tMsgBuf, 0, sizeof(tMsgBuf)); if (MsgQueRecv(pCMQ_Ser, &tMsgBuf, 0) > 0) { printf("Current key=%d: Recv from key=%d,buf=%s\n", iKey, tMsgBuf.iKey, tMsgBuf.buf); if ((pCMQ_Cli=MsgQueReq(tMsgBuf.iKey)) != NULL) { iKeyRecv = tMsgBuf.iKey; memset((BYTE*)&tMsgBuf, 0, sizeof(tMsgBuf)); tMsgBuf.iKey = iKey; strcpy(tMsgBuf.buf, "hello world!"); tMsgBuf.iLen = strlen(tMsgBuf.buf); printf("Current key=%d: send to key=%d, buf=%s\n", iKey, iKeyRecv, tMsgBuf.buf); if (((iRet=MsgQueSend(pCMQ_Cli, &tMsgBuf, 0))) < 0) printf("Current key=%d: send to key=%d, error=%s\n", iKey, tMsgBuf.iKey, strerror(iRet)); } } } } } } MsgQueFree(); } }4. makefile
arm-linux-gnueabi-g++ MsgQue.cpp -o MsgQueApp
5. 测试(以下a b相互通信,通信流程为:A-->B, B-->A)
a. 控制台1,输入字符‘s’发送
root@NXBB:/mnt/nand/# ./MsgQueApp 2 iKey = 0x00000002 CMsgQue::MsgQueCreate:msgget: key=0x00000001, iMsgId=0x00020000 CMsgQue::MsgQueCreate:msgget: key=0x00000002, iMsgId=0x00028001 CMsgQue::MsgQueCreate:msgget: key=0x00000003, iMsgId=0x00030002 Press 's' send, 'r' receive! ...... Current key=2: send to key=1, buf=hello world! Current key=2: Recv from key=1,buf=hello world! Current key=2: send to key=1, buf=hello world! Current key=2: Recv from key=1,buf=hello world! Current key=2: send to key=1, buf=hello world! Current key=2: Recv from key=1,buf=hello world! Current key=2: send to key=1, buf=hello world! Current key=2: Recv from key=1,buf=hello world! Current key=2: send to key=1, buf=hello world! Current key=2: Recv from key=1,buf=hello world! Current key=2: send to key=1, buf=hello world! ......b. 控制台2,输入字符‘r’接收
root@NXBB:/mnt/nand/# ./MsgQueApp 1 iKey = 0x00000001 CMsgQue::MsgQueCreate:msgget: key=0x00000001, iMsgId=0x00020000 CMsgQue::MsgQueCreate:msgget: key=0x00000002, iMsgId=0x00028001 CMsgQue::MsgQueCreate:msgget: key=0x00000003, iMsgId=0x00030002 Press 's' send, 'r' receive! ...... Current key=1: send to key=2, buf=hello world! Current key=1: Recv from key=2,buf=hello world! Current key=1: send to key=2, buf=hello world! Current key=1: Recv from key=2,buf=hello world! Current key=1: send to key=2, buf=hello world! Current key=1: Recv from key=2,buf=hello world! Current key=1: send to key=2, buf=hello world! Current key=1: Recv from key=2,buf=hello world! Current key=1: send to key=2, buf=hello world! Current key=1: Recv from key=2,buf=hello world! Current key=1: send to key=2, buf=hello world! Current key=1: Recv from key=2,buf=hello world! Current key=1: send to key=2, buf=hello world! ......