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






