unix早期通信機制中的信号能夠傳送的資訊量有限,管道則隻能傳送無格式位元組流,這遠遠是不夠的。
消息隊列(也叫封包隊列)客服了這些缺點:
消息隊列就是一個消息的連結清單。
可以把消息看作一個記錄,具有特定的格式。
程序可以按照一定的規則向消息隊列中添加新消息;另一些程序可以從消息隊列中讀走消息。
消息隊列是随核心持續的,隻有核心重新開機或人工删除時,該消息隊列才會被删除。
system V消息隊列使用消息隊列辨別符辨別。具有足夠特權的任何程序都可以往一個給定隊列放置一個消息,具有足夠特權的任何程序都可以從一個給定隊列讀出一個消息。
消息隊列具有一定的FIFO特性,但是它可以實作消息的随機查詢,比FIFO具有更大的優勢。同時這些消息又存在于核心中,由“隊列”ID來辨別消息隊列的實作包括建立或打開消息隊列,添加消息,讀取消息和控制消息隊列這四種操作。
對于系統中的每個消息隊列,核心維護一個定義在<sys/msg.h>頭檔案中的資訊結構。
我們可以将核心中的某個特定的消息隊列畫為一個消息連結清單,如圖假設有一個具有三個消息的隊列,消息長度分别為1位元組,2位元組和3位元組,而且這些消息就是以這樣的順序寫入該隊列的。再假設這三個消息的類型分别為100,200,300.

1.msgget函數
msgget函數用于建立一個新的消息隊列或通路一個已存在的消息隊列。
傳回值是一個整數辨別符,其他三個msg函數就用它來指代該隊列。它是基于指定的key産生的,而key即可以是ftok的傳回值,也可以是常值IPC_PRIVATE。
oflag是讀寫權限值得組合。它還可以與IPC_CREAT或IPC_CREAT | IPC_EXCL按位或,IPC_NOWAIT --- 讀寫消息隊列要求無法得到滿足時,不阻塞。
當建立一個新消息隊列時,msqid_ds結構的如下成員被初始化。
(1)msg_perm結構的uid和cuid成員被設定成目前程序的有效使用者ID,gid和cgid成員被設定成目前程序的有效組ID。
(2)oflag中的讀寫權限位存放在msg_perm.mode中。
(3)msg_qnum,msg_lspid,msg_lrpid,msg_stime和msg_rtime被置為0.
(4)msg_ctime被設定成目前時間。
(5)msg_qbytes被設定成系統限制值。
2.msgsnd函數
使用msgget函數打開一個消息隊列後,我們使用msgsnd往其上放置一個消息。
其中msqid是由msgget傳回的辨別符。ptr是一個結構指針,該結構具有如下模闆,它定義在<sys/msg.h>中。
msgsnd的length參數以位元組為機關指定待發送消息的長度。這是位于長整數消息類型之後的使用者自定義資料的長度(注意:不包括消息類型)。該長度可以是0.
flag參數既可以是0,也可以是IPC_NUWAIT。IPC_NOWAIT标志使得msgsnd調用非阻塞:如果沒有存放新消息的可用空間(即消息隊列已滿),該函數馬上傳回。這個條件發生的情形包括:
(1)在指定的隊列中已有太多的位元組(對于該隊列的msqid_ds結構中的msg_qbytes值);
(2)在系統範圍存在太多的消息。
如果這兩個條件中有一個存在,而且IPC_NUWAIT标志已指定,msgsnd就傳回一個EAGAIN錯誤。如果這兩個條件有一個存在,但是IPC_NUWAIT标志未指定,那麼調用線程被投入睡眠直到:
(1)具備存放新消息的空間;
(2)由msqid标志的消息隊列從系統中删除(這種情況下傳回一個EIDRM錯誤);
(3)調用線程被某個捕獲的信号所中斷(這種情況下傳回一個EINTR錯誤)。
3.msgrcv函數
使用msgrcv函數從某個消息隊列中讀取一個消息。
其中ptr參數指定所接收消息的存放位置。跟msgsnd一樣,該指針指向緊挨在真正的消息資料之前傳回的長整數類型字段。
length指定了由ptr指向的緩沖區中資料部分的大小。這是該函數能傳回的最大資料量。該長度不包括長整數類型字段。
type指定希望從所給定的隊列中讀出什麼樣的消息。
(1)如果type為0,那就傳回該隊列中的第一個消息,既然每個消息隊列都是作為一個FIFO連結清單維護的,是以type為0指定傳回該隊列中最早的消息。
(2)如果type大于0,那就傳回其類型值為type的第一個消息。
(3)如果type小于0,那就傳回其類型小于或等于type參數的絕對值的消息中類型值最小的第一個消息。
msgrcv的flag參數指定所請求類型的消息不在所指定的隊列中時該做何處理。在沒有消息可得的情況下,如果設定了flag中的IPC_NOWAIT位,msgrcv函數就立即傳回一個ENOMSG錯誤。否則,設定了flag為0,調用者被阻塞到下列某個事件發生為止:
(1)有一個所請求類型的消息可擷取;
flag參數中另有一位可以指定:MSG_NOERROR。當所接收消息的真正資料部分大于length參數時,如果設定了該位,msgrcv函數就隻是截短資料部分,而不傳回錯誤。否則,ms_grcv傳回一個E2BIC錯誤。
成功傳回時,msgrcv傳回的是所接收消息中資料的位元組數。它不包括也通過ptr參數傳回的長整數消息類型所需的幾個位元組。
4.msgctl函數
msgctl函數提供在一個消息隊列上的各種控制操作。
msgctl函數提供3個指令。
IPC_RMID 從系統中删除由msqid指定的消息隊列。目前在該隊列上的任何消息都被丢棄。對于該指令而言,msgctl函數的第三個參數被忽略。
IPC_SET 給所指定的消息隊列設定其msgid_ds結構的以下4個成員:msg_perm.uid,msg_perm.gid,msg_perm.mode和msg_qbytes。他們的值來自buff參數指向的結構中的相應的成員。
IPC_STAT 讀取消息隊列的屬性,并将其儲存在buf指向的緩沖區中。
msgrcv.c用于接收消息,msgsend.c用于發送消息:
msgrcv.c
msgsend.c
運作結果: