概念: 進程彼此之間能夠經過IPC消息進行通訊。進程產生的每條消息都被髮送到一個IPC消息隊列中,這條消息一直存放在隊列中,直到另外一個進程將其讀走爲止。函數
優勢:能夠經過發送消息來幾乎徹底避免命名管道的同步和阻塞問題;消息隊列提供了一種從一個進程向另外一個進程發送一個數據塊的方法。並且,每一個數據塊被認爲含有一個類型,接收進程能夠獨立地接收含有不一樣類型值的數據塊。spa
缺點:每一個數據塊有一個最大長度的限制;系統中全部消息隊列所包含的所有數據塊的總長度也有一個上限。code
基本原理: 消息是由固定大小的首部和可變長度的正文組成的;可使用一個整數值標識消息,這就容許進程有選擇的從消息隊列中獲取消息。只要進程從IPC消息隊列中讀出一條消息,內核就把這條消息刪除;所以,一個進程只能接收一條給定的消息。當消息隊列滿時,則試圖讓新消息入隊的進程可能被阻塞。當消息隊列爲空時,則接收進程甚至會被阻塞。blog
代碼示例:隊列
發送信息的程序的源文件msgsend.c的源代碼爲:進程
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/msg.h> #include <errno.h> #define MAX_TEXT 512 struct msg_st { long int msg_type; char text[MAX_TEXT]; }; int main() { int running = 1; struct msg_st data; char buffer[BUFSIZ]; int msgid = -1; //創建消息隊列 msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } //向消息隊列中寫消息,直到寫入end while(running) { //輸入數據 printf("Enter some text: "); fgets(buffer, BUFSIZ, stdin); data.msg_type = 1; //注意2, 用來設置發送的信息的信息類型,即其發送的信息的類型爲1 strcpy(data.text, buffer); //向隊列發送數據 if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1) { fprintf(stderr, "msgsnd failed\n"); exit(EXIT_FAILURE); } //輸入end結束輸入 if(strncmp(buffer, "end", 3) == 0) running = 0; sleep(1); } exit(EXIT_SUCCESS); }
接收信息的程序源文件爲msgreceive.c的源代碼爲:get
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/msg.h> struct msg_st { long int msg_type; char text[BUFSIZ]; }; int main() { int running = 1; int msgid = -1; struct msg_st data; long int msgtype = 0; //注意1,值爲0表示獲取隊列中第一個可用的消息 //創建消息隊列 msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } //從隊列中獲取消息,直到遇到end消息爲止 while(running) { if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1) { fprintf(stderr, "msgrcv failed with errno: %d\n", errno); exit(EXIT_FAILURE); } printf("You wrote: %s\n",data.text); //遇到end結束 if(strncmp(data.text, "end", 3) == 0) running = 0; } //刪除消息隊列 if(msgctl(msgid, IPC_RMID, 0) == -1) { fprintf(stderr, "msgctl(IPC_RMID) failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
若是把注意1,即msgreceive.c文件main函數中的語句由long int msgtype = 0;改變爲long int msgtype = 2;會發生什麼狀況,msgreceive將不能接收到程序msgsend發送的信息。由於在調用msgrcv函數時,若是msgtype(第四個參數)大於零,則將只獲取具備相同消息類型的第一個消息,修改後獲取的消息類型爲2,而msgsend發送的消息類型爲1,因此不能被msgreceive程序接收。
msgreceive若是沒有接收到信息和輸出,並且當msgsend輸入end結束後,msgreceive也不會結束,經過jobs命令咱們能夠看到它還在後臺運行着。同步