1. 程式人生 > >linux程序通訊:使用posix訊息佇列mq進行執行緒或程序間的通訊

linux程序通訊:使用posix訊息佇列mq進行執行緒或程序間的通訊

POSIX訊息佇列允許程序以訊息的形式交換資料。此API與System V訊息佇列(msgget(2),msgsnd(2),msgrcv(2)等)有明顯不同,但做的事情差不多。

在linux多執行緒程式設計中,如果兩個執行緒沒用共同的資料區,則需要使用訊息佇列從一個執行緒往另一個執行緒傳送訊息(同樣可以應用在程序間通訊)

訊息佇列通過mq_open()建立和開啟,此函式返回一個訊息佇列描述符mqd_t,它用於之後的呼叫中引用開啟的訊息佇列。每個訊息佇列由一個名字標識,兩個程序可以操作同一個佇列。

訊息通過呼叫mq_send()和mq_receive()傳遞。當一個程序結束使用該佇列,則它呼叫mq_close(),當一個佇列不再需要了,則可以呼叫mq_unlink()刪除。佇列屬性可以呼叫mq_getattr()/mq_setattr()獲取/修改。一個程序可以在一個空佇列上呼叫mq_notify請求訊息到達的非同步通知。

訊息佇列描述符引用到一個開啟的訊息佇列(類比open(2))。fock(2)之後,子程序繼承父程序佇列描述符的拷貝,兩個描述符都引用到父程序的那個描述符。兩個程序持有的描述符共享與訊息佇列描述符相關聯的標記(mq_flags)。

下面以一個例項說明:

 建立並接收資料執行緒:

#include<mqueue.h>
#define WAIT_FOREVER -1

typedef struct{
    UINT32 start;
    char name[32] = {0};  
}MQ_SEND_MSG;                               //接收的訊息結構體

char nameMsg[32] = {0};
UINT32 memAvail;        
char chName;
MQ_SEND_MSG recvMsg;
extern mqd_t memAvailMsgQ;

struct mq_addr mqa;
mqa.mq_maxmsg = 20;
mqa.mq_msgsize = sizeof(MQ_SEND_MSG);
strcpy(nameMsg, "/memAvailMsgQ");
mqUnlink(nameMsg);                                                                                                                                                              

memAvailMsgQ = mq_open(nameMsg, O_CREAT|O_RDWR|O_EXCL, DEFAULT_MSG_MODE, &mqa);  //建立一個mq訊息
if(memAvailMsgQ == -1)
{
    return error;    
}                      

FOREVER                                                 //迴圈等待另一個執行緒傳送訊息     
{
    retval = mq_receive(memAvailMsgQ, (char *)&recvSendMsg, sizeof(MQ_SEND_MSG), WAIT_FOREVER, NULL);  
    if(retval == sizeof(MQ_SEND_MSG))                   //mqReceive返回接收到的資料的長度,以此判斷有沒有成功接收訊息
    {
        memAvail = recvSendMsg.start;
        chName = recvSendMsg.name;
    }
}   
傳送資料執行緒:
#include<mqueue.h>

typedef struct{
    UINT32 start;
    char name[32] = {0};  
}MQ_SEND_MSG;                                //mq訊息結構體

mqd_t memAvailMsgQ;                         //mq訊息控制代碼

MQ_SEND_MSG mqSendMsg;
mqSendMsg.start = memAvail;                     //傳送的訊息結構體成員
strcpy(mqSendMsg.chName, "come on baby!");        //傳送的訊息結構體成員

mq_send(memAvailMsgQ, (char *)&mqSendMsg, sizeof(MQ_SEND_MSG), 200,  0);   //傳送資料