参数1 msgid: 是由msgget函数所返回的消息队列标识符。
参数2 msg_ptr:是一个指向要发送消息的指针,正如前面所描述的,这个消息必须以long int类型开始。
参数3 msg_sz: 是由msg_ptr所指向的消息的尺寸。这个尺寸必须不包含long int消息类型。
参数4 msgflg: 控制如果当前消息队列已满或是达到了队列消息的系统限制时如何处理。如果msgflg标记清除了IPC_NOWAIT标记,发送进程就会被挂起,等待队列中有可用的空间。
如果msgflg为0时,msgsnd()及msgrcv()在队列呈满或呈空的情形时,采取阻塞等待的处理模式
参数1 msqid: 是由msgget函数所返回的消息队列标记符。
参数2 msg_ptr:是一个指向将要接收消息的指针,正如在msgsnd函数中所描述的,这个消息必须以long int类型开始。
参数3 msg_sz: 是由msg_ptr所指向的消息的尺寸,并不包含long int消息类型。
参数4 msgtype:是一个long int类型,允许一个接收优先级形式的实现。
如果msgtype的值为0,队列中第一个可用的消息就会被接收。如果msgflg标记中消除了IPC_NOWAIT位,进程就会被挂起,等待一个合适类型的消息到来。
如果msgflg为0时,msgsnd()及msgrcv()在队列呈满或呈空的情形时,采取阻塞等待的处理模式
IPC_NOWAIT 如果没有满足条件的消息,调用立即返回,此时,errno=ENOMSG IPC_EXCEPT 与msgtyp>0配合使用,返回队列中第一个类型不为msgtyp的消息 IPC_NOERROR 如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将丢失。如果成功,msgrcv会返回放入接收缓冲区中的字节数,消息会被拷贝到由msg_ptr所指向的用户分配缓冲区中,而数据就会由消息队列中删除。如果失败则会返回-1。
msqid_ds结构至少包含下列成员: struct msqid_ds { uid_t msg_perm.uid; uid_t msg_perm.gid mode_t msg_perm.mode;}
参数1 msqid: 是由msgget函数所返回的标记符。
参数2 command: 是要执行的动作。
他可以取下面三个值:
命令 描述
IPC_STAT 设置msqid_ds结构中的数据来反射与消息队列相关联的值。
IPC_SET 如果进程有权限这样做,这个命令会设置与msqid_ds数据结构中所提供的消息队列相关联的值。
IPC_RMID 删除消息队列。 返回值:如果成功则会返回0,如果失败则会返回-1。
当进程正在msgsnd或是msgrcv函数中等待时如果消息队列被删除,发送或接收函数就会失败。
消息队列发送:
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_TEXT 512
struct my_msg_st
{
long int my_msg_type;
char some_text[MAX_TEXT];
};
int main()
{
int running = 1;
struct my_msg_st some_data;
int msgid;
char buffer[BUFSIZ];
msgid = msgget((key_t)1234, 0666|IPC_CREAT);
if(msgid==-1)
{
fprintf(stderr,"msgget failed with errno: %d\n", errno);
exit(EXIT_FAILURE);
}
while(running)
{
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
some_data.my_msg_type = 1;
strcpy(some_data.some_text, buffer);
if(msgsnd(msgid, (void *)&some_data, MAX_TEXT, IPC_NOWAIT)==-1)
{
fprintf(stderr, "msgsnd failed\n");
perror("sendmsg");
exit(EXIT_FAILURE);
}
if(strncmp(buffer, "end", 3) == 0)
{
running = 0;
}
}
exit(EXIT_SUCCESS);
}
消息队列接受:
#include
#include
#include
#include
#include
#include
#include
#include
struct my_msg_st
{
long int my_msg_type;
char some_text[BUFSIZ];
};
int main()
{
int running = 1;
int msgid;
struct my_msg_st some_data;
long int msg_to_receive = 0;
msgid = msgget((key_t)1234,0666|IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr,"msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
while(running)
{
if(msgrcv(msgid, (void *)&some_data, BUFSIZ, msg_to_receive, 0) == -1)
{
fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("You wrote: %s", some_data.some_text);
if(strncmp(some_data.some_text, "end", 3)==0)
{
running = 0;
}
}
if(msgctl(msgid, IPC_RMID, 0)==-1)
{
fprintf(stderr, "msgctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
/**
* @brief Linux消息队列封装
* @filename Msgqueue.h
* @author Lihailong
*/
#include "msgqueue.h"
#include
#include
MsgQueue::MsgQueue()
{
m_MsgId = -1;
m_bOpen = false;
m_nCurByteSizeOfMsgQueue = 0;
m_nCurMsgCntOfMsgQueue = 0;
m_nMaxByteSizeOfMsgQueue = 0;
m_nTimeOfLastMsgChange = 0;
m_nTimeOfLastMsgRcv = 0;
m_nTimeOfLastMsgSnd = 0;
m_nPidOfLastMsgRcv = 0;
m_nPidOfLastMsgSnd = 0;
m_nUidOfMsg = 0;
m_nGidOfMsg = 0;
}
MsgQueue::~MsgQueue()
{
CloseMsgQueue();
}
bool MsgQueue::OpenMsgQueue(int nKey, int nMode)
{
int nRet;
nRet = msgget((key_t)nKey, nMode);
if ( -1 == nRet)
{
perror("OpenMsgQueue_msgget");
return false;
}
m_MsgId = nRet;
m_bOpen = true;
GetMsgQueueSatus();
return true;
}
bool MsgQueue::OpenMsgQueue(std::string strQueueName, int nMode)
{
std::string strFile = "/tmp/";
strFile += strQueueName;
std::string strCmd = "touch ";
strCmd += strFile;
system(strCmd.c_str());
key_t mqkey = ftok(strFile.c_str(), 11);
if(mqkey == -1)
{
perror("OpenMsgQueue_ftok");
return false;
}
int nRet;
nRet = msgget(mqkey, nMode);
if ( -1 == nRet)
{
perror("OpenMsgQueue_msgget");
return false;
}
m_MsgId = nRet;
m_bOpen = true;
GetMsgQueueSatus();
return true;
}
bool MsgQueue::IsOpen()
{
return m_bOpen;
}
bool MsgQueue::CloseMsgQueue()
{
if (m_bOpen)
{
if ( msgctl(m_MsgId, IPC_RMID, NULL) == -1 )
{
return false;
}
else
{
m_bOpen = false;
return true;
}
}
return false;
}
bool MsgQueue::SendMsg(long nType, void *pData, int nMsgLen, int nMode)
{
if (nType < 0 || NULL == pData || nMsgLen <= 0 || nMsgLen > MAX_MSG_LEN ) return false;
int nFlags;
if (nMode == 0) nFlags = 0;
else if (nMode == 1) nFlags = IPC_NOWAIT;
else nFlags = 0;
int nRet;
msg sndMsg;
memset(&sndMsg, 0, sizeof(sndMsg));
sndMsg.nType = nType;
memcpy(sndMsg.data, pData, nMsgLen);
nRet = msgsnd(m_MsgId, (void*)&sndMsg, nMsgLen, nFlags);
if ( -1 == nRet)
{
perror("SendMsg");
return false;
}
GetMsgQueueSatus();
return true;
}
bool MsgQueue::SendMsgTimeOut(long nType, void *pData, int nMsgLen, int nTimeout)
{
time_t startTime = time(NULL);
if (nType < 0 || NULL == pData || nMsgLen <= 0 || nMsgLen > MAX_MSG_LEN ) return false;
int nFlags = IPC_NOWAIT;
msg sndMsg;
memset(&sndMsg, 0, sizeof(sndMsg));
sndMsg.nType = nType;
memcpy(sndMsg.data, pData, nMsgLen);
while(true)
{
int nRet = 0;
nRet = msgsnd(m_MsgId, (void*)&sndMsg, nMsgLen, nFlags);
if (0 == nRet)
{
GetMsgQueueSatus();
return true;
}
else
{
if (errno == EAGAIN)
{
if (time(NULL) - startTime < nTimeout)
{
usleep(30);
continue;
}
}
perror("msgsnd");
return false;
}
}
}
bool MsgQueue::RecvMsg(long nMsgType, void *pData, int nMsgLen, int nMode)
{
if (NULL == pData || nMsgLen <= 0 || nMsgLen > MAX_MSG_LEN) return false;
int nFlags;
if ( 0 == nMode) nFlags = 0;
else if (1 == nMode) nFlags = IPC_NOWAIT;
else nFlags = 0;
int nRet;
msg rcvMsg;
memset(&rcvMsg, 0, sizeof(rcvMsg));
nRet = msgrcv(m_MsgId, (void*)&rcvMsg, nMsgLen, nMsgType, nFlags);
if (-1 == nRet)
{
perror("RecvMsg");
return false;
}
memcpy(pData, rcvMsg.data, nMsgLen);
GetMsgQueueSatus();
return true;
}
bool MsgQueue::RecvMsgTimeOut(long nMsgType, void *pData, int nMsgLen, int nTimeout)
{
time_t startTime = time(NULL);
if (NULL == pData || nMsgLen <= 0 || nMsgLen > MAX_MSG_LEN) return false;
int nFlags = IPC_NOWAIT;
msg rcvMsg;
memset(&rcvMsg, 0, sizeof(rcvMsg));
while(true)
{
int nRet;
nRet = msgrcv(m_MsgId, (void*)&rcvMsg, nMsgLen, nMsgType, nFlags);
if (0 < nRet)
{
memcpy(pData, rcvMsg.data, nMsgLen);
GetMsgQueueSatus();
return true;
}
else
{
if (errno == ENOMSG || 0 == nRet)
{
if (time(NULL) - startTime < nTimeout)
{
usleep(30);
continue;
}
}
perror("msgrcv");
return false;
}
}
}
int MsgQueue::GetCurByteOfMsgQueue()
{
return m_nCurByteSizeOfMsgQueue;
}
int MsgQueue::GetMaxByteOfMsgQueue()
{
return m_nMaxByteSizeOfMsgQueue;
}
int MsgQueue::GetCurMsgNumOfMsgQueue()
{
return m_nCurMsgCntOfMsgQueue;
}
int MsgQueue::GetPidOfLastMsgSend()
{
return m_nPidOfLastMsgSnd;
}
int MsgQueue::GetPidOfLastMsgRcv()
{
return m_nPidOfLastMsgRcv;
}
int MsgQueue::GetTimeOfLastMsgSnd()
{
return 0;
}
int MsgQueue::GetTimeOfLastMsgRcv()
{
return 0;
}
int MsgQueue::GetTimeOfLasetMsgChg()
{
return 0;
}
int MsgQueue::GetUid()
{
return m_nUidOfMsg;
}
int MsgQueue::GetGid()
{
return m_nGidOfMsg;
}
int MsgQueue::GetMsgId()
{
return m_MsgId;
}
void MsgQueue::GetMsgQueueSatus()
{
if (!m_bOpen) return;
struct msqid_ds msgInfo;
int nRet;
nRet = msgctl(m_MsgId, IPC_STAT, &msgInfo);
if ( -1 == nRet)
{
perror("GetMsgQueueSatus");
return;
}
m_nCurByteSizeOfMsgQueue = msgInfo.msg_cbytes;
m_nCurMsgCntOfMsgQueue = msgInfo.msg_qnum;
m_nMaxByteSizeOfMsgQueue = msgInfo.msg_qbytes;
m_nPidOfLastMsgSnd = msgInfo.msg_lspid;
m_nPidOfLastMsgRcv = msgInfo.msg_lrpid;
m_nUidOfMsg = msgInfo.msg_perm.uid;
m_nGidOfMsg = msgInfo.msg_perm.gid;
}
///调用实例
int main()
{
msbuf d,a;
d.time = 3333;
d.data = 4444;
d.s = 4560.232;
MsgQueue msg;
msg.OpenMsgQueue("Test");
msg.Send(10, &d, sizeof(d));
printf("idss:%d\n",msg.GetMsgId());
memset(&a, 0, sizeof(a));
msg.RecvMsg(10, &a, sizeof(a));
printf("time:%d\n", a.time);
printf("data:%d\n", a.data);
printf("double:%lf\n", a.s);
// msg.CloseMsgQueue();
}