|     本文關鍵字: 消息隊列,linux 消息隊列     顧名思義,消(xiao)息隊列(lie)(lie)就(jiu)是一些消(xiao)息的(de)列(lie)(lie)表,用戶可以在(zai)消(xiao)息隊列(lie)(lie)中添加(jia)消(xiao)息和讀(du)取(qu)消(xiao)息等。從(cong)這(zhe)點上看,消(xiao)息隊列(lie)(lie)具(ju)有一定的(de)FIFO特性,但是它(ta)可以實現消(xiao)息的(de)隨(sui)機查(cha)詢,比FIFO具(ju)有更大的(de)優勢。同時,這(zhe)些消(xiao)息又是存在(zai)于內核中的(de),由“隊列(lie)(lie)ID”來標(biao)識(shi)。     消(xiao)(xiao)(xiao)息(xi)(xi)(xi)隊(dui)(dui)列的(de)(de)(de)實現包括創建或打開(kai)(kai)消(xiao)(xiao)(xiao)息(xi)(xi)(xi)隊(dui)(dui)列、添加消(xiao)(xiao)(xiao)息(xi)(xi)(xi)、讀取消(xiao)(xiao)(xiao)息(xi)(xi)(xi)和控制(zhi)消(xiao)(xiao)(xiao)息(xi)(xi)(xi)隊(dui)(dui)列4種操(cao)作,其中創建或打開(kai)(kai)消(xiao)(xiao)(xiao)息(xi)(xi)(xi)隊(dui)(dui)列使(shi)用(yong)的(de)(de)(de)函(han)數(shu)是(shi)(shi)msgget(),這(zhe)里創建的(de)(de)(de)消(xiao)(xiao)(xiao)息(xi)(xi)(xi)隊(dui)(dui)列的(de)(de)(de)數(shu)量(liang)(liang)會(hui)受到系統消(xiao)(xiao)(xiao)息(xi)(xi)(xi)隊(dui)(dui)列數(shu)量(liang)(liang)的(de)(de)(de)限(xian)制(zhi);添加消(xiao)(xiao)(xiao)息(xi)(xi)(xi)使(shi)用(yong)的(de)(de)(de)函(han)數(shu)是(shi)(shi)msgsnd(),它(ta)(ta)(ta)把消(xiao)(xiao)(xiao)息(xi)(xi)(xi)添加到已打開(kai)(kai)的(de)(de)(de)消(xiao)(xiao)(xiao)息(xi)(xi)(xi)隊(dui)(dui)列末尾;讀取消(xiao)(xiao)(xiao)息(xi)(xi)(xi)使(shi)用(yong)的(de)(de)(de)函(han)數(shu)是(shi)(shi)msgrcv(),它(ta)(ta)(ta)把消(xiao)(xiao)(xiao)息(xi)(xi)(xi)從消(xiao)(xiao)(xiao)息(xi)(xi)(xi)隊(dui)(dui)列中取走(zou),與FIFO不同(tong)的(de)(de)(de)是(shi)(shi),這(zhe)里可(ke)以取走(zou)指定(ding)的(de)(de)(de)某一條消(xiao)(xiao)(xiao)息(xi)(xi)(xi);控制(zhi)消(xiao)(xiao)(xiao)息(xi)(xi)(xi)隊(dui)(dui)列使(shi)用(yong)的(de)(de)(de)函(han)數(shu)是(shi)(shi)msgctl(),它(ta)(ta)(ta)可(ke)以完(wan)成多項功能。     表(biao)1列舉了msgget()函(han)數的語法要點。 表1  msgget()函數語法要(yao)點 
    
    | 所需頭文件 | #include <sys/types.h> #include <sys/ipc.h>
 #include <sys/shm.h>
 |  
    | 函數原型 | int msgget(key_t key, int msgflg) |  
    | 函數傳入值 | key:消息隊列的鍵值,多個進程可以通過它訪問同一個消息隊列,其中有個特殊值IPC_PRIVATE,用于創建當前進程的私有消息隊列 |  
    | msgflg:權限標志位 |  
    | 函數返回值 | 成功:消息隊列ID |  
    | 出錯:-1 |      表2列(lie)舉了msgsnd()函(han)數的(de)語法要點。 表2  msgsnd()函(han)數語法要點 
    
    | 所需頭文件 | #include <sys/types.h> #include <sys/ipc.h>
 #include <sys/shm.h>
 |  
    | 函數原型 | int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) |  
    | 函數傳入值 | msqid:消息隊列的隊列ID |  
    | msgp:指向消息結構的指針,該消息結構msgbuf通常如下。 struct msgbuf
 {
 long mtype;     /* 消息類型,該結構必須從這個域開始 */
 char mtext[1];   /* 消息正文 */
 }
 |  
    | msgsz:消息正文的字節數(不包括消息類型指針變量) |  
    | msgflg | IPC_NOWAIT:若消息無法立即發送(如當前消息隊列已滿),函數會立即返回 |  
    | 0:msgsnd調用阻塞直到發送成功為止 |  
    | 函數返回值 | 成功:0 |  
    | 出錯:-1 |      表3列舉了msgrcv()函(han)數的語法(fa)要點。 表3  msgrcv()函數(shu)語法(fa)要點(dian) 
    
    | 所需頭文件 | #include <sys/types.h> #include <sys/ipc.h>
 #include <sys/shm.h>
 |  
    | 函數原型 | int msgrcv(int msgid, void *msgp, size_t msgsz, long int msgtyp, int msgflg) |  
    | 函數傳入值 | msqid:消息隊列的隊列ID |  
    | msgp:消息緩沖區,同msgsnd()函數的msgp |  
    | msgsz:消息正文的字節數(不包括消息類型指針變量) |  
    | msgtyp | 0:接收消息隊列中第一個消息 |  
    | 大于0:接收消息隊列中第一個類型為msgtyp的消息 |  
    | 函數傳入值 | 小于0:接收消息隊列中第一個類型值不小于msgtyp絕對值且類型值小的消息 |  
    | msgflg | MSG_NOERROR:若返回的消息比msgsz字節多,則消息就會截短到msgsz字節,且不通知消息發送進程 |  
    | IPC_NOWAIT:若在消息隊列中并沒有相應類型的消息可以接收,則函數立即返回 |  
    | 0:msgsnd()調用阻塞直到接收一條相應類型的消息為止 |  
    | 函數返回值 | 成功:0 |  
    | 出錯:-1 |      表4列(lie)舉了(le)msgctl()函數(shu)的語法要點。 表(biao)4  msgctl()函數語法(fa)要點 
    
    | 所需頭文件 | #include <sys/types.h> #include <sys/ipc.h>
 #include <sys/shm.h>
 |  
    | 函數原型 | int msgctl (int msgqid, int cmd, struct msqid_ds *buf ) |  
    | 函數傳入值 | msqid:消息隊列的隊列ID |  
    | cmd:命令參數 | IPC_STAT:讀取消息隊列的數據結構msqid_ds,并將其存儲在buf指定的地址中 |  
    | IPC_SET:設置消息隊列的數據結構msqid_ds中的ipc_perm域(IPC操作權限描述結構)值,這個值取自buf參數 |  
    | IPC_RMID:從系統內核中刪除消息隊列 |  
    | buf:描述消息隊列的msqid_ds結構類型變量 |  
    | 函數返回值 | 成功:0 |  
    | 出錯:-1 |      下面的(de)實例體現了如(ru)何使(shi)用消息(xi)隊(dui)列(lie)進行兩個進程(發送端和接收(shou)端)之間的(de)通(tong)信,包(bao)括消息(xi)隊(dui)列(lie)的(de)創建、消息(xi)發送與讀取、消息(xi)隊(dui)列(lie)的(de)撤銷和刪除等多(duo)種操(cao)作(zuo)。     消息(xi)發(fa)(fa)送(song)端進程(cheng)(cheng)和消息(xi)接收端進程(cheng)(cheng)間不需(xu)要額外實(shi)(shi)現進程(cheng)(cheng)間的同(tong)(tong)步。在該(gai)(gai)實(shi)(shi)例中,發(fa)(fa)送(song)端發(fa)(fa)送(song)的消息(xi)類型(xing)設置為該(gai)(gai)進程(cheng)(cheng)的進程(cheng)(cheng)號(可以(yi)取其他值),因此接收端根據消息(xi)類型(xing)來確定消息(xi)發(fa)(fa)送(song)者的進程(cheng)(cheng)號。注意這里使用(yong)了fotk()函數,它可以(yi)根據不同(tong)(tong)的路徑和關(guan)鍵字(zi)產(chan)生標準(zhun)的key。消息(xi)隊列發(fa)(fa)送(song)端的代(dai)碼如(ru)下:     /* msgsnd.c */#include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #define  BUFFER_SIZE		512
 
 
 struct message
 {
 long msg_type;
 char msg_text[BUFFER_SIZE];
 };
 int main()
 {
 int qid;
 key_t key;
 struct message msg;
 
 /* 根據不同的路徑和關鍵字產生標準的key */
 if ((key = ftok(".", 'a')) == -1)
 {
 perror("ftok");
 exit(1);
 }
 /* 創建消息隊列 */
 if ((qid = msgget(key, IPC_CREAT|0666)) == -1)
 {
 perror("msgget");
 exit(1);
 }
 printf("Open queue %d\n",qid);
 while(1)
 {
 printf("Enter some message to the queue:");
 if ((fgets(msg.msg_text, BUFFER_SIZE, stdin)) == NULL)
 {
 puts("no message");
 exit(1);
 }
 
 msg.msg_type = getpid();
 /* 添加消息到消息隊列 */
 if ((msgsnd(qid, &msg, strlen(msg.msg_text), 0)) < 0)
 {
 perror("message posted");
 exit(1);
 }
 if (strncmp(msg.msg_text, "quit", 4) == 0)
 {
 break;
 }
 }
 exit(0);
 }
     消息隊列(lie)接(jie)收端的代碼如下:     /* msgrcv.c */#include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #define  BUFFER_SIZE		512
 
 struct message
 {
 long msg_type;
 char msg_text[BUFFER_SIZE];
 };
 int main()
 {
 int qid;
 key_t key;
 struct message msg;
 
 /* 根據不同的路徑和關鍵字產生標準的key */
 if ((key = ftok(".", 'a')) == -1)
 {
 perror("ftok");
 exit(1);
 }
 /* 創建消息隊列 */
 if ((qid = msgget(key, IPC_CREAT|0666)) == -1)
 {
 perror("msgget");
 exit(1);
 }
 printf("Open queue %d\n", qid);
 do
 {
 /* 讀取消息隊列 */
 memset(msg.msg_text, 0, BUFFER_SIZE);
 if (msgrcv(qid, (void*)&msg, BUFFER_SIZE, 0, 0) < 0)
 {
 perror("msgrcv");
 exit(1);
 }
 printf("The message from process %d : %s", msg.msg_type, msg.msg_text);
 
 } while(strncmp(msg.msg_text, "quit", 4));
 /* 從系統內核中移走消息隊列 */
 if ((msgctl(qid, IPC_RMID, NULL)) < 0)
 {
 perror("msgctl");
 exit(1);
 }
 exit(0);
 }
     以下是程序(xu)的運(yun)行結果,輸入“quit”則兩(liang)個進(jin)程都將結束。     $ ./msgsnd   Open queue 327680
 Enter some message to the queue:first message
 Enter some message to the queue:second message
 Enter some message to the queue:quit
 $ ./msgrcv
 Open queue 327680
 The message from process 6072 : first message
 The message from process 6072 : second message
 The message from process 6072 : quit
     本文選自華清遠見嵌入式培訓教材《從實踐中學嵌入式Linux應用程序開發》    熱點(dian)鏈接: 
         1、linux 共享內存2、linux下的信號量
 3、linux下的信號處理實例
 4、信號處理函數signal()和信號集函數組
 5、信號捕捉函數alarm()和pause()
 
 更多新聞>>  |