linux 消息隊列

linux消息隊列

消息隊列的實現包括創建或打開消息隊列、添加消息、讀取消息和控制消息隊列這四種操作。


其中創建或打開消息隊列使用的函數是msgget,這裏創建的消息隊列的數量會受到系統消息隊列數量的限制;


添加消息使用的函數是msgsnd函數,它把消息添加到已打開的消息隊列末尾;


讀取消息使用的函數是msgrcv,它把消息從消息隊列中取走,與FIFO不同的是,這裏可以指定取走某一條消息;

最後控制消息隊列使用的函數是msgctl,它可以完成多功能。


函數介紹:


1.msgget函數:


msgget- get a message queue identifier


頭文件:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>


函數原型: intmsgget(key_t key, int msgflg);

msgget()要麼返回一個新創建的消息隊列的標識符,要麼返回具有相同關鍵字值的>隊列的標識符。

key:是一個全系統唯一的關鍵字,標識要獲取或創建的消息隊列,其他想要與這個隊列連接的進程也必須使用相同的關鍵字

msg_flag:創建一個隊列時,這個標誌是IPC_CREATE與權限標誌的邏輯或(權限標誌和標準文件權限標誌相同--讀、寫和執行,消息隊列的用戶號和組號由創建它的進程決定)。

例子:

msgid= msgget(KEY,IPC_CREAT|0777))

返回值:

成功:消息隊列ID

出錯:-1


key:可以用ftok來建立,也可以用戶自定義。注意,兩個進程的key相同最終msgget才能返回一個相同的msgqid。如果key不相同,生成的msgqid自然不相等,那麼這兩個進程之間無法通信。

/*ftok - convert a pathname and a project identifier to a System VIPC

key

key_tftok(const char *pathname, int proj_id);

#include<sys/types.h>

#include<sys/ipc.h>


*/

2.msgsnd函數


頭文件:

#include<sys/types.h>
#include <sys/ipc.h>
#include<sys/msg.h>


函數原型:intmsgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);


發送消息給消息隊列


msgb參數是結構體的指針:

structmsgbuf {

longmtype; /* message type, must be > 0 */

charmtext[1]; /* message data */

};

mtext的大小是由 msgsz指定的。

msqid:消息隊列IDmsgget返回)

msgflag:

IPC_NOWAIT:若消息並沒有立即發送而調用進程會立即返回。

0msgsnd調用阻塞直到條件滿足爲止。

返回值:

0成功

-1失敗

例子:

mtext是一個消息內容可以爲任意格式,例如:

Structprivate_msgbuf {

long mtype;

char name[30];

char gender;

unsigned int age;

char cell[20];

};

Key_t key;

Intmsqid;

structprivate_msgbuf pmb = {2, “Yuhui”, ‘M’, 30, “13810933881”};

msqid= msgget(8888, IPC_CREAT | 0666);

Msgsnd(msqid,(struct msgbuf *) &pmb, sizeof(pmb), 0);


實例:

先定義結構體和宏

structmsq_command {


unsignedint msq_main_cmd;

unsignedint msq_sub_cmd;

unsignedint msq_res;

charmsq_data[1];

};

這是消息的具體內容

structmsq_buffer {

longm_type;

charm_text[LENGTH_MEDIUM];

};

intmsgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

函數中的msgp參數




#defineMSQ_REQUEST_SND_ID 19790416

#defineMSQ_RESPONSE_RCV_ID 19790416


#defineMSQ_REQUEST_RCV_ID 20091105

#defineMSQ_RESPONSE_SND_ID 20091105


#defineMSQ_CMD_GET 1

#defineMSQ_CMD_SET 2


#defineGUARDIAN_USER 0

#defineROOT_USER 1

#defineCOMMON_USER 2

#defineWEB_USER 3

#defineSNMP_USER 4

發送端:

intrcv_size;

intmsq_request_snd_id;//獲得消息隊列id

intmsq_request_rcv_id;


structmsq_buffer rcv_data;//接受數據

structmsq_buffer snd_data;//發送數據

structmsq_command * msq_snd;//發送數據消息正文

structmsq_command * msq_rcv;//接受消息正文

//int msgget(key_t key, int msgflg);

msq_request_snd_id= msgget(MSQ_REQUEST_SND_ID, IPC_CREAT | 0600);

msq_request_rcv_id= msgget(MSQ_REQUEST_RCV_ID, IPC_CREAT | 0600);

msq_snd= (struct msq_command *) snd_data.m_text;//強制類型轉換.共享內存,指針指向同一個位置

snd_data.m_type= COMMON_USER;

msq_snd->msq_main_cmd= MSQ_CMD_GET;

msq_snd->msq_sub_cmd= CMD_ID_GET_SYS_VERSION;

msq_snd->msq_res= 0;

//int msgsnd(int msqid, const void *msgp, size_t msgsz,int msgflg);

if(0 != msgsnd(msq_request_snd_id, &snd_data, LENGTH_MEDIUM, 0))

printf("msggeterror: %s.\n", strerror(errno));


printf("--- send finished.\n");

printf("--- waiting for response.\n");

//接受返回消息

rcv_size= msgrcv(msq_request_rcv_id, &rcv_data, LENGTH_MEDIUM, 0, 0);


if(rcv_size > 0)

perror("msgrcv");


msq_rcv= (struct msq_command *)rcv_data.m_text;


printf("msq_main_cmdis: %d.\n", msq_rcv->msq_main_cmd);

printf("msq_sub_cmdis: %d.\n", msq_rcv->msq_sub_cmd);

printf("msq_resis: %d.\n", msq_rcv->msq_res);

printf("msq_data is: %s.\n", msq_rcv->msq_data);

這是發送消息:



接受消息:





接受端:

首先,我們先初始化我們的服務端,接收命令處理端。代碼如下:


intinit_msq_command_response (void)

{

pid_tpid;

volatileunsigned int i = 0;


printf("--- in init.\n");

//建立子進程

if((pid = fork()) < 0) {

printf("FatalError! Can not fork: %s.\n.", strerror(errno));

return-1;

}

elseif (0 == pid) {

i++;

if(1 == i)

printf("messagequeue process is running.\n");

//子進程執行函數

msq_command_response();

}


return0;

}


接下來,是我們的消息隊列的處理端,代碼如下:


intmsq_command_response (void)

{

intmsq_response_rcv_id, msq_response_snd_id;

intrcv_size;

structmsq_buffer rcv_data;

structmsq_buffer snd_data;

structmsq_command * msq_cmd;

structmsq_command * msq_res;

//得到消息隊列id

msq_response_rcv_id= msgget(MSQ_RESPONSE_RCV_ID, IPC_CREAT | 0600);

msq_response_snd_id= msgget(MSQ_RESPONSE_SND_ID, IPC_CREAT | 0600);


if((-1 == msq_response_snd_id) || (-1 == msq_response_rcv_id)) {

printf("FatalError! Can not create Message Queue: %s.\n.", strerror(errno));

return-1;

}

//等待消息的到來

while(1) {

rcv_size= msgrcv (msq_response_rcv_id, &rcv_data, LENGTH_MEDIUM, 0, 0);

//接受消息

if(-1 == rcv_size)

continue;//如果沒有接受到消息則退出再次接受

//接受到了消息

msq_cmd= (struct msq_command *) rcv_data.m_text;//指向同一塊位置

/*snd_data.m_type= COMMON_USER;

msq_snd->msq_main_cmd= MSQ_CMD_GET;

msq_snd->msq_sub_cmd= CMD_ID_GET_SYS_VERSION;

msq_snd->msq_res= 0;

發送端發送的消息

*/

/*Fill message back parameters */

snd_data.m_type= rcv_data.m_type;

msq_res= (struct msq_command *) snd_data.m_text;

msq_res->msq_main_cmd= msq_cmd->msq_main_cmd;

msq_res->msq_sub_cmd= msq_cmd->msq_sub_cmd;

msq_res->msq_res= msq_cmd->msq_res;


printf("Gotmessage, msq_cmd->msq_main_cmd is: %d.\n",msq_cmd->msq_main_cmd);

printf("Gotmessage, msq_cmd->msq_sub_cmd is: %d.\n",msq_cmd->msq_sub_cmd);

printf("Gotmessage, msq_cmd->msq_res is: %d.\n", msq_cmd->msq_res);


if(MSQ_CMD_SET == msq_cmd->msq_main_cmd) {

printf("MessageQueue, receive SET function.\n ");

}else if (MSQ_CMD_GET == msq_cmd->msq_main_cmd) {

switch(msq_cmd->msq_sub_cmd)

{

caseCMD_ID_GET_SYS_VERSION:

strcpy(msq_res->msq_data,"0.0.4");

//返回處理消息

if(0 != msgsnd(msq_response_snd_id, &snd_data, LENGTH_MEDIUM, 0))

printf("msggeterror: %s.\n", strerror(errno));

printf("--- msq_command_response send message finished.\n");


break;

caseCMD_ID_GET_SYS_NAME:

break;

caseCMD_ID_SET_SYS_NAME:

break;

caseCMD_ID_GET_SYS_CONTACT:

break;

caseCMD_ID_SET_SYS_CONTACT:

break;

caseCMD_ID_GET_SERIAL_TAG:

break;

caseCMD_ID_GET_SERVICE_TAG:

break;

default:

break;


}

}

}


return0;

}


發佈了50 篇原創文章 · 獲贊 7 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章