進程間通訊IPC-消息隊列

前言:數據結構

   消息隊列就是一個消息的鏈表。能夠把消息看做一個記錄,具備特定的格式以及特定的優先級。對消息隊列有寫權限的進程能夠向其中按照必定的規則添加新消息;對消息隊列有讀權限的進程則能夠從消息隊列中讀走消息函數

函數:spa

1.建立新消息隊列或取得已存在消息隊列指針

原型:code

1 int msgget(key_t key, int msgflg);

參數:blog

     key:能夠認爲是一個端口號,也能夠由函數ftok生成。隊列

     msgflg:IPC_CREAT值,若沒有該隊列,則建立一個並返回新標識符;若已存在,則返回原標識符。進程

                 IPC_EXCL值,若沒有該隊列,則返回-1;若已存在,則返回0。ip

2.向隊列讀/寫消息get

原型:

msgrcv從隊列中取用消息:

1 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msgsnd將數據放到消息隊列中:

1 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

參數:

     msqid:消息隊列的標識碼

     msgp:指向消息緩衝區的指針,此位置用來暫時存儲發送和接收的消息,是一個用戶可定義的通用結構,形態以下: 

1 struct msgstru{
2     long mtype; //大於0
3     char mtext[512];
4 };

    msgsz:消息的大小。

    msgtyp:從消息隊列內讀取的消息形態。若是值爲零,則表示消息隊列中的全部消息都會被讀取。

  msgflg:用來指明核心程序在隊列沒有數據的狀況下所應採起的行動。若是msgflg和常數IPC_NOWAIT合用,則在msgsnd()執行時如果消息隊列已滿,則msgsnd()將不會阻塞,而會當即返回-1,若是執行的是msgrcv(),則在消息隊列呈空時,不作等待立刻返回-1,並設定錯誤碼爲ENOMSG。當msgflg爲0時,msgsnd()及msgrcv()在隊列呈滿或呈空的情形時,採起阻塞等待的處理模式。

3.設置消息隊列屬性

原型:

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 標識的消息隊列。

實例:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/types.h>
 4 #include <sys/ipc.h>
 5 #include <sys/msg.h>
 6 #include <errno.h>
 7 
 8 #define MSGKEY 1234
 9 
10 int main(int agrc, char* agrv[])
11 {
12   struct msgstru
13   {
14         long msgtype;
15         char msgtext[2048];
16   } msgs;
17   int msg_type;
18   char str[256];
19   int ret_value;
20 
21   int msqid=msgget(MSGKEY,IPC_EXCL);  /*檢查消息隊列是否存在*/
22   if(msqid < 0)
23   {
24     msqid = msgget(MSGKEY,IPC_CREAT|0666);/*建立消息隊列*/
25     if(msqid <0)
26         {
27                 perror("msgget");
28                 exit(EXIT_FAILURE);
29     }
30   }
31 
32   pid_t pid = fork();
33   if (pid < 0)
34           exit(EXIT_FAILURE);
35   else if (pid > 0)
36   {
37         while(1)
38         {
39                 msqid = msgget(MSGKEY,IPC_EXCL );/*檢查消息隊列是否存在 */
40                 if (msqid < 0)
41                 {
42                         perror("msgget");
43                         break;
44                 }
45                 /*接收消息隊列*/
46                 ret_value = msgrcv(msqid,&msgs,sizeof(struct msgstru),0,0);
47                 printf("text=[%s] pid=[%d]\n",msgs.msgtext,getpid());
48         }
49   }
50   else
51   {
52         while (1)
53         {
54                 printf("input message type(end:0):");
55                 scanf("%d",&msg_type);
56                 if (msg_type == 0)
57                         break;
58                 printf("input message to be sent:");
59                 scanf ("%s",str);
60                 msgs.msgtype = msg_type;
61                 strcpy(msgs.msgtext, str);
62                 /* 發送消息隊列 */
63                 ret_value = msgsnd(msqid,&msgs,sizeof(struct msgstru),IPC_NOWAIT);
64                 if ( ret_value < 0 )
65                 {
66                         perror("msgsend");
67                         exit(EXIT_FAILURE);
68                 }
69         }
70   }
71   msgctl(msqid,IPC_RMID,0); //刪除消息隊列
72   return 0;
73 }
總結:各類通訊方式大同小易,原理都差很少,都是由系統提供支持的通訊方式。
相關文章
相關標籤/搜索