消息隊列簡記
消息隊列簡記
在了解了信號量和共享內存之後,消息隊列自然就比較容易理解了。
之前提到共享內存的操作不是原子的, 那麼便可以結合信號量來進行控製。
消息隊列是另外一種進程間通信的手段, 使用以下幾個函數調用。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>//一般上述兩個頭文件都被此文件包含
int msgget(key_t key, int msgflg);
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
由此可見幾種IPC機製都是類似的。
msgget(key, msgflg);
同樣的道理,該函數創建或獲取一個和key相關的消息隊列,一般使用 0666 | IPC_CREAT作為msgflg的值。看到0666很容易想到777(關於chmod),很容易可以知道是設置權限。
操作的是低9位, 666就是110110110。從高到低對應著u(用戶),g(組別), o(其他)的讀、寫和執行權限。比如最高三位110表示u有讀和寫權限,但沒有執行權限。
函數返回一個msgid,供其它相關函數使用。
msgsnd(msgid, msgp, msgsz, msgflg);
一般來說,消息隊列中的消息成員都是一個結構體,該結構體至少包含兩個成員: 一個是消息類型,另一個是消息數據。
比如:
#define MSGSIZ 1024
struct msg_st {
long msg_type;
char msg_text[MSGSIZ];
};
而msgp就是指向要傳送的消息的指針。
msgsz是消息的大小,不包含消息類型。
msgflg一般置0。
msgrcv(msgid, msgp, msgsz, msgtyp, msgflg);
與msgsnd類似,不同的是第4個參數msgtyp。
msgtyp指定了要接收的消息類型, 一共有3種情況。
1. msgtyp為0, 表示按順序接收消息隊列中的成員。
2. msgtyp為某正數,表示接收類型為該正數的消息,類型由消息結構體中的msg_type指定。
3. msgtyp為某負數,表示接收類型小於等於該負數絕對值的類型消息。
msgctl一般用來撤銷消息隊列,形如 msgctl(msgid, IPC_RMID, 0)。
下麵是個小實驗:
用於發送消息的msg1.c:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/msg.h> #include "msg_st.h" int main(){ int i; int msg_id; char buf[MSGSIZ]; struct msg_st msg_ptr; msg_id = msgget((key_t)1234, 0666 |IPC_CREAT); for(i=0; i<3; i++){ printf("請輸入第%d條要發送的消息:", i); scanf("%s", buf); msg_ptr.msg_type = i; strcpy(msg_ptr.msg_text, buf); msgsnd(msg_id, (void *)&msg_ptr, 512, 0); } printf("已發送完消息./n"); return 0; }
用於接收消息的msg2.c(指定接收數據類型為1的消息):
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/msg.h> #include "msg_st.h" int main(int argc, char *argv[]){ int msg_id; struct msg_st msg_ptr; msg_ptr.msg_type = 1; msg_id = msgget((key_t)1234, 0666 | IPC_CREAT); printf("要接收的消息類型為%ld/n", msg_ptr.msg_type); msgrcv(msg_id, (void *)&msg_ptr, 512, msg_ptr.msg_type, 0); printf("接收到的消息為:%s/n", msg_ptr.msg_text); msgctl(msg_id, IPC_RMID, 0); return 0; }
Jason Lee
2009-11-16 p.m
最後更新:2017-04-02 04:01:43