各位看官們,大家好,上一回中咱們說的是使用共享內存進行進程間通信的例子,這一回咱們說的例子是:使用消息隊列進行進程間通信。閒話休提,言歸正轉。讓我們一起talk C栗子吧!
消息隊列是SystemV IPC結構這種抽象概念的一種具體對象,這點和共享內存一樣。消息隊列提供了一個隊列供不同的進程使用,進程之間可以通過該隊列傳遞數據,進而實現進程間的通信。
在介紹消息隊列的使用方法之前,我們先介紹幾個函數,這些函數都是用來操作消息隊列的。
int msgget(key_t key,int msgflag)
該函數用來創建一個新的消息隊列或者獲取已經存在的消息隊列。
第一個參數是鍵值,通過它來操作IPC在內核中的結構,也就是消息隊列在內核中的結構;(前面章回中介紹過) 第二個參數是消息隊列的權限標記,該權限和文件權限一樣; 該函數運行成功時返回消息隊列標識符,否則返回-1;我們可以通過該標識符使用消息隊列;
int msgsnd(int msg_id, const void *msg_ptr,size_t msg_sz,int msgflg)
該函數用來把消息添加到消息隊列中,這樣進程就可以從消息隊列中獲取消息了;
在使用該函數的時候,我們需要自己定義一個消息的類型,並且計算出該類型的內存空間。消息的類型可以依據程序需要來定義,常見的是定義一個結構體類型。不過類型中的第一個成員必須是一個long int類型的成員,該成員用來確定消息的類型。
第一個參數是消息隊列的標識符,通過msgget函數可以獲得; 第二個參數是一個指針,該指針指向准備添加到消息隊列中消息; 第三個參數是一個int類型的值,表示准備添加到消息隊列中消息的大小; 第四個參數是一個位標記,該標記用來控制消息隊列已滿或者達到系統限制時的動作。 該函數運行成功時返回0,否則返回-1;在使用該函數的時候,第四個參數通常為IPC_NOWAIT,表示消息隊列已滿後函數不發消息到消息隊列中,並且立刻返回-1.如果沒有設置該標記,那麼消息隊列已滿後先把以送消息的進程掛起,直到消息到消息隊列中有空間了,它再發送消息到消息隊列中。
int msgrcv(int msgid,void *msg_ptr,size_t msg_sz,long int msgtype,int msgflg)
該函數用來從消息隊列中獲取消息或者說接收消息;
第一個參數是消息隊列的標識符,通過msgget函數可以獲得; 第二個參數是一個指針,該指針指向准備從消息隊列中獲取的消息; 第三個參數是一個int類型的值,表示獲取消息的大小; 第四個參數是一個long int類型的值,表示接收消息的優先級; 第五個參數是一個位標記,該標記用來控制消息隊列中沒有消息供接收時的動作。 該函數運行成功時返回接收到消息的字節數,否則返回-1;在使用該函數數,第五個參數的值和msgsnd函數中第四個參數的值一樣,而且函數的動作也類似,只不過從發送消息轉換為接收消息。該函數的第四個參數通常為0,表示按照消息的發送順序接收消息;
如果它的值為n(n>0),表示接收類型值為n的這一類消息;
如果它的值為-n(n>0),表示接收類型值為等於或者小於n的這一類消息;
這裡說的類型值就是我們定義消息類型中的第一個成員。
int msgctl(int msg_id, int cmd,struct msgid_ds *buf)
該函數用來對消息隊列進行相關操作,常用的操作是刪除消息隊列;
第一個參數是消息隊列的標識符,通過msgget函數可以獲得; 第二個參數是一個命令,表示對消息隊列的操作,只有三個命令供使用:IPC_STAT,IPC_SET和IPC_RMID; 第三個參數是一個結構體指針,該結構體中有消息隊列的權限和所有者等信息; 該函數運行成功時返回0,否則返回-1;我們通常使用該函數刪除消息隊列,這時候需要給第二個參數賦值為IPC_RMID,表示刪除消息隊列,第三參數可以為空指針。第二個參數的另外兩個命令:IPC_STAT表示把第三個參數中的內容和消息隊列關聯起來;IPC_SET表示把第三個參數中的內容設置為消息隊列的值。第三個參數的類型,我們在前面章回中提起過,它和SystemV IPC的結構類似,除了必須有的成員外,它還有自己特有的成員。
該函數的用法和咱們在前面章回中介紹過的shmctl函數用法類似,大家可以進行對比。
我從源代碼中找到了第三個參數的類型,詳細的定義如下:(位於linux-4.0.3/include/linux/msg.h文件中)
struct msg_queue {
struct kern_ipc_perm q_perm;
time_t q_stime; /* last msgsnd time */
time_t q_rtime; /* last msgrcv time */
time_t q_ctime; /* last change time */
unsigned long q_cbytes; /* current number of bytes on queue */
unsigned long q_qnum; /* number of messages in queue */
unsigned long q_qbytes; /* max number of bytes on queue */
pid_t q_lspid; /* pid of last msgsnd */
pid_t q_lrpid; /* last receive pid */
struct list_head q_messages;
struct list_head q_receivers;
struct list_head q_senders;
};
各位看官,關於使用消息隊列進行進程間通信的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。