消息隊列是在兩個進程之間傳遞二進制數(shù)據(jù)的一種簡單有效的方式。每個數(shù)據(jù)塊都有一個特定的類型,接收方可以根據(jù)類型來有選擇地接受數(shù)據(jù),而不一定像管道和命名管道那樣必須以先進先出的方式接受數(shù)據(jù)。
linux消息隊列的API都定義在sys/msg.h頭文件中,包括4個系統(tǒng)調(diào)用:msgget、msgsnd、msgrcv、msgctl
msgget系統(tǒng)調(diào)用
msgget系統(tǒng)調(diào)用創(chuàng)建一個消息隊列,或者獲取一個已有的消息隊列。定義如下:
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
和semegt系統(tǒng)調(diào)用一下,key參數(shù)是一個鍵值,用來標識一個全局唯一的消息隊列。
msgflg參數(shù)使用的含義與semget系統(tǒng)調(diào)用的sem_flags參數(shù)相同。
(多進程編程 - 信號量)
msgget成功時返回一個正整數(shù)值,它是消息隊列u的標識符。msgget失敗時返回-1,并設置errno。
如果msgget用于創(chuàng)建消息隊列,則與之關聯(lián)的內(nèi)核數(shù)據(jù)結構msqid_ds將被創(chuàng)建并初始化,msqid_ds結構體的定義如下:
sturct msqid_ds
{
struct ipc_perm msg_perm; /*消息隊列的操作權限*/
time_t msg_stime; /*最后一次調(diào)用msgsnd時間*/
time_t msg_rtime; /*最后一次調(diào)用msgrcv時間*/
time_t msg_ctime; /*最后一次被修改的時間*/
unsigned long __msg_cbytes; /*消息隊列中已有的字節(jié)數(shù)*/
msgqnum_t msg_qnum; /*消息隊列中已有的消息數(shù)*/
msglen_t msg_qbytes; /*消息隊列允許的最大字節(jié)數(shù)*/
pid_t msg_lspid; /*最后執(zhí)行msgsnd的進程的PID*/
pid_t msg_lrpid; /*最后執(zhí)行msgrcv的進程的PID*/
};
msgsnd系統(tǒng)調(diào)用
msgsnd系統(tǒng)調(diào)用把一條消息添加到消息隊列中。定義如下:
#include <sys/msg.h>
int msgsnd(int msqid, const void* msg_ptr, size_t msg_sz, int msgflg);
msqid參數(shù)是由msgget調(diào)用返回的消息隊列標識符
msg_ptr參數(shù)指向一個準備發(fā)送的消息,消息必須被定義為如下類型:
struct msgbuf
{
long mtype; //消息類型
char mtext[512]; //消息數(shù)據(jù)
};
其中:
- mtype成員指定消息的類型,它必須是一個正整數(shù)。
- mtext是消息數(shù)據(jù)
msg_sz參數(shù)是消息的數(shù)據(jù)部分(mtext)的長度。這個長度可以為0,表示沒有數(shù)據(jù)。
msgflg參數(shù)空值msgsnd的行為,它通常僅支持IPC_NOWAIT標志,即非阻塞的方式發(fā)送消息。默認情況下,發(fā)送消息時如果消息隊列滿了,則msgsnd將阻塞。
若IPC_NOWAIT標志被指定,則msgsnd將立即返回并設置errno為EAGAIN。
處于阻塞狀態(tài)的msgsnd調(diào)用可能被如下兩種異常情況所中斷:
- 消息隊列被移除。此時msgsnd調(diào)用將立即返回并設置errno為EIDRM
- 程序接收到信號。此時msgsnd調(diào)用將立即返回并設置errno為EINTR
msgsnd成功時返回0,失敗則返回-1,并設置errno。msgsnd成功時將修改內(nèi)核數(shù)據(jù)結構msqid_ds的部分字段,如下所示:
- 將msg_qnum加1
- 將msg_lspid設置為調(diào)用進程的PID
- 將msg_stime設置為當前的時間
msgrcv系統(tǒng)調(diào)用
msgrcv系統(tǒng)調(diào)用從消息隊列中獲取消息,定義如下:
#include <sys/msg.h>
int msgrcv(int msqid, void* msg_ptr, size_t msg_sz,long int msgtype, int msgflg);
msqid參數(shù)是由msgget調(diào)用返回的消息隊列標識符
msg_ptr參數(shù)用于存儲接受的消息,msg_sz參數(shù)指定的是消息數(shù)據(jù)部分的長度
msgtype參數(shù)指定接受何種類型的消息。有如下幾種方式來指定消息類型:
- msgtype等于0。讀取消息中的第一個消息。
- msgtype大于0。讀取消息隊列中第一個類型為msgtype(除非指定了標志MSG_EXCEPT)
- msgtype小于0。讀取消息隊列中第一個類型比msgtype的絕對值小的消息。
參數(shù)msg空值msgrcv函數(shù)的行為。它可以是如下一些標志的按位或:
- IPC_NOWAIT:如果消息隊列中沒有消息,則msgrcv調(diào)用立即返回并設置errno為ENOMSG
- MSG_EXCEPT:如果msgtype大于0,則接受消息隊列中第一個非msgtype類型的消息
- MSG_NOERROR:如果消息數(shù)據(jù)部分的長度超過了msg_sz,就將它設置為EINTR
處于阻塞狀態(tài)的msgrcv調(diào)用還可能被如下兩種異常情況所中斷:
- 消息隊列被移除。此時msgrcv調(diào)用將立即返回并設置errno為EIDRM
- 程序接收到信號。此時msgrcv調(diào)用將立即返回并設置errno為EINTR
msgrcv成功時返回0,失敗則返回-1,并設置errno。msgrcv成功時將修改內(nèi)核數(shù)據(jù)結構msqid_ds的部分字段,如下所示:
- 將msg_qnum減1
- 將msg_lrpid設置為調(diào)用進程的PID
- 將msg_rtime設置為當前的時間
msgctl系統(tǒng)調(diào)用
msgctl系統(tǒng)調(diào)用控制消息隊列的某些屬性,定義如下:
#include <sys/msg.h>
int msgctl(int msqid, int command, struct msqid_ds * buf);
msqid參數(shù)是由msgget調(diào)用返回的共享內(nèi)存標識符。command參數(shù)指定要執(zhí)行的命令。msgctl支持的所有命令如下表:

msgctl成功時的返回值取決于command參數(shù),如上表所示。msgctl函數(shù)失敗時返回-1并設置errno。