1、什麼是消息隊列
消息隊列提供了一種從一個進程向另外一個進程發送一個數據塊的方法。 每一個數據塊都被認爲含有一個類型,接收進程能夠獨立地接收含有不一樣類型的數據結構。咱們能夠經過發送消息來避免命名管道的同步和阻塞問題。可是消息隊列與命名管道同樣,每一個數據塊都有一個最大長度的限制。數組
Linux用宏MSGMAX和MSGMNB來限制一條消息的最大長度和一個隊列的最大長度。數據結構
2、在Linux中使用消息隊列
Linux提供了一系列消息隊列的函數接口來讓咱們方便地使用它來實現進程間的通訊。消息隊列函數由msgget、msgctl、msgsnd、msgrcv四個函數組成。下面的表格列出了這四個函數的函數原型及其具體說明。函數
msgget(獲得消息隊列標識符或建立一個消息隊列對象)ui |
||
所需頭文件spa |
#include <sys/types.h>對象 #include <sys/ipc.h>接口 #include <sys/msg.h>隊列 |
|
函數說明進程 |
獲得消息隊列標識符或建立一個消息隊列對象並返回消息隊列標識符ip |
|
函數原型 |
int msgget(key_t key, int msgflg) |
|
函數傳入值 |
key |
0(IPC_PRIVATE):會創建新的消息隊列 |
大於0的32位整數:視參數msgflg來肯定操做。一般要求此值來源於ftok返回的IPC鍵值 |
||
msgflg |
0:取消息隊列標識符,若不存在則函數會報錯 |
|
IPC_CREAT:當msgflg&IPC_CREAT爲真時,若是內核中不存在鍵值與key相等的消息隊列,則新建一個消息隊列;若是存在這樣的消息隊列,返回此消息隊列的標識符 |
||
IPC_CREAT|IPC_EXCL:若是內核中不存在鍵值與key相等的消息隊列,則新建一個消息隊列;若是存在這樣的消息隊列則報錯 |
||
函數返回值 |
成功:返回消息隊列的標識符 |
|
出錯:-1,錯誤緣由存於error中 |
||
附加說明 |
上述msgflg參數爲模式標誌參數,使用時須要與IPC對象存取權限(如0600)進行|運算來肯定消息隊列的存取權限 |
|
錯誤代碼 |
EACCES:指定的消息隊列已存在,但調用進程沒有權限訪問它 EEXIST:key指定的消息隊列已存在,而msgflg中同時指定IPC_CREAT和IPC_EXCL標誌 ENOENT:key指定的消息隊列不存在同時msgflg中沒有指定IPC_CREAT標誌 ENOMEM:須要創建消息隊列,但內存不足 ENOSPC:須要創建消息隊列,但已達到系統的限制 |
若是用msgget建立了一個新的消息隊列對象時,則msqid_ds結構成員變量的值設置以下:
msg_qnum、msg_lspid、msg_lrpid、 msg_stime、msg_rtime設置爲0。
msg_ctime設置爲當前時間。
msg_qbytes設成系統的限制值。
msgflg的讀寫權限寫入msg_perm.mode中。
msg_perm結構的uid和cuid成員被設置成當前進程的有效用戶ID,gid和cuid成員被設置成當前進程的有效組ID。
msgctl (獲取和設置消息隊列的屬性) |
||
所需頭文件 |
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> |
|
函數說明 |
獲取和設置消息隊列的屬性 |
|
函數原型 |
int msgctl(int msqid, int cmd, struct msqid_ds *buf) |
|
函數傳入值 |
msqid |
消息隊列標識符 |
cmd
|
IPC_STAT:得到msgid的消息隊列頭數據到buf中 |
|
IPC_SET:設置消息隊列的屬性,要設置的屬性需先存儲在buf中,可設置的屬性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes |
||
buf |
消息隊列管理結構體,請參見消息隊列內核結構說明部分 |
|
函數返回值 |
成功:0 |
|
出錯:-1,錯誤緣由存於error中 |
||
錯誤代碼 |
EACCESS:參數cmd爲IPC_STAT,確無權限讀取該消息隊列 EFAULT:參數buf指向無效的內存地址 EIDRM:標識符爲msqid的消息隊列已被刪除 EINVAL:無效的參數cmd或msqid EPERM:參數cmd爲IPC_SET或IPC_RMID,卻無足夠的權限執行 |
msgsnd (將消息寫入到消息隊列) |
||
所需頭文件 |
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> |
|
函數說明 |
將msgp消息寫入到標識符爲msqid的消息隊列 |
|
函數原型 |
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) |
|
函數傳入值 |
msqid |
消息隊列標識符 |
msgp |
發送給隊列的消息。msgp能夠是任何類型的結構體,但第一個字段必須爲long類型,即代表此發送消息的類型,msgrcv根據此接收消息。msgp定義的參照格式以下: struct s_msg{ /*msgp定義的參照格式*/ |
|
msgsz |
要發送消息的大小,不含消息類型佔用的4個字節,即mtext的長度 |
|
msgflg |
0:當消息隊列滿時,msgsnd將會阻塞,直到消息能寫進消息隊列 |
|
IPC_NOWAIT:當消息隊列已滿的時候,msgsnd函數不等待當即返回 |
||
IPC_NOERROR:若發送的消息大於size字節,則把該消息截斷,截斷部分將被丟棄,且不通知發送進程。 |
||
函數返回值 |
成功:0 |
|
出錯:-1,錯誤緣由存於error中 |
||
錯誤代碼 |
EAGAIN:參數msgflg設爲IPC_NOWAIT,而消息隊列已滿 EIDRM:標識符爲msqid的消息隊列已被刪除 EACCESS:無權限寫入消息隊列 EFAULT:參數msgp指向無效的內存地址 EINTR:隊列已滿而處於等待狀況下被信號中斷 EINVAL:無效的參數msqid、msgsz或參數消息類型type小於0 |
msgsnd()爲阻塞函數,當消息隊列容量滿或消息個數滿會阻塞。消息隊列已被刪除,則返回EIDRM錯誤;被信號中斷返回E_INTR錯誤。
若是設置IPC_NOWAIT消息隊列滿或個數滿時會返回-1,而且置EAGAIN錯誤。
msgsnd()解除阻塞的條件有如下三個條件:
① 不知足消息隊列滿或個數滿兩個條件,即消息隊列中有容納該消息的空間。
② msqid表明的消息隊列被刪除。
③ 調用msgsnd函數的進程被信號中斷。
msgrcv (從消息隊列讀取消息) |
||
所需頭文件 |
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> |
|
函數說明 |
從標識符爲msqid的消息隊列讀取消息並存於msgp中,讀取後把此消息從消息隊列中刪除 |
|
函數原型 |
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); |
|
函數傳入值 |
msqid |
消息隊列標識符 |
msgp |
存放消息的結構體,結構體類型要與msgsnd函數發送的類型相同 |
|
msgsz |
要接收消息的大小,不含消息類型佔用的4個字節 |
|
msgtyp |
0:接收第一個消息 |
|
>0:接收類型等於msgtyp的第一個消息 |
||
<0:接收類型等於或者小於msgtyp絕對值的第一個消息 |
||
msgflg |
0: 阻塞式接收消息,沒有該類型的消息msgrcv函數一直阻塞等待 |
|
IPC_NOWAIT:若是沒有返回條件的消息調用當即返回,此時錯誤碼爲ENOMSG |
||
IPC_EXCEPT:與msgtype配合使用返回隊列中第一個類型不爲msgtype的消息 |
||
IPC_NOERROR:若是隊列中知足條件的消息內容大於所請求的size字節,則把該消息截斷,截斷部分將被丟棄 |
||
函數返回值 |
成功:實際讀取到的消息數據長度 |
|
出錯:-1,錯誤緣由存於error中 |
||
錯誤代碼 |
E2BIG:消息數據長度大於msgsz而msgflag沒有設置IPC_NOERROR EIDRM:標識符爲msqid的消息隊列已被刪除 EACCESS:無權限讀取該消息隊列 EFAULT:參數msgp指向無效的內存地址 ENOMSG:參數msgflg設爲IPC_NOWAIT,而消息隊列中無消息可讀 EINTR:等待讀取隊列內的消息狀況下被信號中斷 |
msgrcv()解除阻塞的條件有如下三個:
① 消息隊列中有了知足條件的消息。
② msqid表明的消息隊列被刪除。
③ 調用msgrcv()的進程被信號中斷。