消息隊列就是一個消息的鏈表。可以把消息看作一個記錄,具有特定的格式以及特定的優先級。對消息隊列有寫權限的進程可以向其中按照一定的規則添加新消息;對消息隊列有讀權限的進程則可以從消息隊列中讀走消息
原型:
int msgget(key_t key, int msgflg);
參數:
key:可以認為是一個端口號,也可以由函數ftok生成。
msgflg:IPC_CREAT值,若沒有該隊列,則創建一個並返回新標識符;若已存在,則返回原標識符。
IPC_EXCL值,若沒有該隊列,則返回-1;若已存在,則返回0。
原型:
msgrcv從隊列中取用消息:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
msgsnd將數據放到消息隊列中:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
參數:
msqid:消息隊列的標識碼
msgp:指向消息緩沖區的指針,此位置用來暫時存儲發送和接收的消息,是一個用戶可定義的通用結構,形態如下:
struct msgstru{ long mtype; //大於0 char mtext[512]; };
msgsz:消息的大小。
msgtyp:從消息隊列內讀取的消息形態。如果值為零,則表示消息隊列中的所有消息都會被讀取。
msgflg:用來指明核心程序在隊列沒有數據的情況下所應采取的行動。如果msgflg和常數IPC_NOWAIT合用,則在msgsnd()執行時若是消息隊列已滿,則msgsnd()將不會阻塞,而會立即返回-1,如果執行的是msgrcv(),則在消息隊列呈空時,不做等待馬上返回-1,並設定錯誤碼為ENOMSG。當msgflg為0時,msgsnd()及msgrcv()在隊列呈滿或呈空的情形時,采取阻塞等待的處理模式。
原型:
int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
參數:msgctl 系統調用對 msgqid 標識的消息隊列執行 cmd 操作,系統定義了 3 種 cmd 操作: IPC_STAT , IPC_SET , IPC_RMID
IPC_STAT : 該命令用來獲取消息隊列對應的 msqid_ds 數據結構,並將其保存到 buf 指定的地址空間。
IPC_SET : 該命令用來設置消息隊列的屬性,要設置的屬性存儲在buf中。
IPC_RMID : 從內核中刪除 msqid 標識的消息隊列。
消息發送端:send.c
/*send.c*/ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #define MSGKEY 1024 struct msgstru { long msgtype; char msgtext[2048]; }; main() { struct msgstru msgs; int msg_type; char str[256]; int ret_value; int msqid; 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); } } while (1){ printf("input message type(end:0):"); scanf("%d",&msg_type); if (msg_type == 0) break; printf("input message to be sent:"); scanf ("%s",str); msgs.msgtype = msg_type; strcpy(msgs.msgtext, str); /* 發送消息隊列 */ ret_value = msgsnd(msqid,&msgs,sizeof(struct msgstru),IPC_NOWAIT); if ( ret_value < 0 ) { printf("msgsnd() write msg failed,errno=%d[%s]\n",errno,strerror(errno)); exit(-1); } } msgctl(msqid,IPC_RMID,0); //刪除消息隊列 }
消息接收端 receive.c
/*receive.c */ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #define MSGKEY 1024 struct msgstru { long msgtype; char msgtext[2048]; }; /*子進程,監聽消息隊列*/ void childproc(){ struct msgstru msgs; int msgid,ret_value; char str[512]; while(1){ msgid = msgget(MSGKEY,IPC_EXCL );/*檢查消息隊列是否存在 */ if(msgid < 0){ printf("msq not existed! errno=%d [%s]\n",errno,strerror(errno)); sleep(2); continue; } /*接收消息隊列*/ ret_value = msgrcv(msgid,&msgs,sizeof(struct msgstru),0,0); printf("text=[%s] pid=[%d]\n",msgs.msgtext,getpid()); } return; } void main() { int i,cpid; /* create 5 child process */ for (i=0;i<5;i++){ cpid = fork(); if (cpid < 0) printf("fork failed\n"); else if (cpid ==0) /*child process*/ childproc(); } }