無論發送進程還是接收進程,都需要在進程空間中用消息緩衝區來暫存消息。該消息緩衝區的結構定義如下
struct msgbuf { long mtype; /* 消息的類型 */ char mtext[1]; /* 消息正文 */};
通過msgget創建消息隊列
函數原型如下
#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgget(key_t key, int msgflg);
參數:
IPC_CREAT 如果消息隊列對象不存在,則創建之,否則則進行打開操作IPC_EXCL 如果消息對象不存在則創建之,否則產生一個錯誤並返回
返回值:
那麼如何獲取key值?
向消息隊列中添加數據,使用到的是msgsnd()函數
函數原型如下
int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
參數:
返回值:
從消息隊列中讀取消息,我們使用msgrcv()函數,
函數原型如下
int msgrcv(int msgid, void *msg_ptr, size_t msgsz, long int msgtype, int msgflg);
參數:
msgtype>0且msgflg=MSC_EXCEPT,接收類型不等於msgtype的第一條消息
返回值:
函數原型
int msgctl(int msqid, int command, strcut msqid_ds *buf);
參數:
注意:若選擇刪除隊列,第三個參數傳NULL
返回值:
如果操作成功,返回「0」;如果失敗,則返回「-1」
舉一個例子,父進程寫消息(先寫發送的數據類型,再寫數據),子進程收消息類型為1的消息
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <errno.h>#define MSGKEY 123//消息的數據結構是以一個長整型成員變量開始的結構體struct msgstru{ long msgtype; char msgtext[2048];};int main(){ struct msgstru msgs; char str[256]; int msg_type; int ret_value; int msqid; int pid; //檢查消息隊列是否存在 msqid = msgget(MSGKEY, IPC_EXCL);//(鍵名,權限) if (msqid < 0) { //創建消息隊列 msqid = msgget(MSGKEY, IPC_CREAT | 0666); if (msqid <0) { printf("failed to create msq | errno=%d [%s]\n", errno, strerror(errno)); exit(-1); } } pid = fork();//創建子進程 if (pid > 0) { //父進程 while (1) { printf("input message type:\n");//輸入消息類型 scanf("%d", &msg_type); if (msg_type == 0) break; printf("input message to be sent:\n");//輸入消息信息 scanf("%s", str); msgs.msgtype = msg_type; strcpy(msgs.msgtext, str); //發送消息隊列(sizeof消息的長度,而不是整個結構體的長度) ret_value = msgsnd(msqid, &msgs, sizeof(msgs.msgtext), IPC_NOWAIT); if (ret_value < 0) { printf("msgsnd() write msg failed,errno=%d[%s]\n", errno, strerror(errno)); exit(-1); } } } else if (pid == 0) { //子進程 while (1) { msg_type = 1;//接收的消息類型為1 msgs.msgtype = msg_type; //發送消息隊列(sizeof消息的長度,而不是整個結構體的長度) ret_value = msgrcv(msqid, &msgs, sizeof(msgs.msgtext), msgs.msgtype, IPC_NOWAIT); if (ret_value > 0) { printf("read msg:%s\n", msgs.msgtext); } } } else { printf("fork error\n"); //刪除消息隊列 msgctl(msqid, IPC_RMID, 0); exit(1); } return 0;}
運行結果