1.消息隊列(queue)

版權聲明:本文爲博主原創文章,未經博主容許不得轉載。https://www.cnblogs.com/Dana-gx/p/9724545.htmlhtml

1、基本概念數據結構

  IPC:Linux下的進程通訊。包括6種:信號(signal)、管道(pipe)和命名管道(FIFO)、消息隊列(msq)、共享內存(shm)、信號量、套接字(socke)
    POSIX進程間通訊包括:posix消息隊列、posix信號燈、posix共享內存
    接下來主要講解的時SYSTEM V消息隊列:
          消息隊列:提供了一種從一個進程向另外一個進程發送一個數據塊的方法。每一個數據塊都被認爲含有一個類型,接收進程能夠獨立地接收含有不一樣類型的數據結構
2、 爲何用消息隊列?與管道的區別?
  相同:
      1> 通訊的進程能夠是不相關的進程(不一樣進程)
      2> 都是經過發送和接收的方式來傳遞數據的
      3> 對每一個數據都有一個最大長度的限制

  區別:   函數

      1> 避免命名管道的同步和阻塞問題
      2> 接收程序能夠經過消息類型有選擇地接收數據,而不是像命名管道中那樣,只能順序地接收(msgtype,肯定收發數據類型)
      3> 消息隊列也能夠獨立於發送和接收進程而存在,從而消除了在同步命名管道的打開和關閉時可能產生的困難
3、 消息隊列和共享內存查看方法:ipcs

                            

共享內存每列詳解:ui

  第一列就是共享內存的key;        第二列是共享內存的編號shmid;
    第三列就是建立的用戶owner;      第四列就是權限perms;
    第五列爲建立的大小bytes;             第六列爲鏈接到共享內存的進程數nattach;
    第七列是共享內存的狀態status。其中顯示「dest」表示 共享內存段已經被刪除,可是還有用戶在使用 當該段內存的mode字段設置爲SHM_DEST時
       就會顯示「dest」。當用戶調用shmctl的IPC_RMID時,內存先查看多少個進程與這個內存關聯着,若是關聯數爲0,就會銷燬這段共享內存,否者設置
       這段內存的mod的mode位爲SHM_DEST,若是全部進程都不用則刪除這段共享內存。
 
4、 消息隊列結構模型:

           

5、system v下的消息隊列接口函數:建立、發送、接受和刪除spa

  int msgget (key_t key, int msgflg);指針

  msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,long msg_typ, int msgflg);code

  msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);htm

  int msgctl (int msqid, int cmd, struct msqid_ds *buf);blog

  5.1 msgget函數 用來建立和訪問一個消息隊列 函數原型以下:接口

     int msgget (key_t key, int msgflg);

     key: 某個特定消息隊列的鍵值
             msgflg:由九個權限標誌構成,它們的用法和建立文件時使用的mode模式標誌是同樣的,IPC_CREAT 時,key 不存在建立,存在忽略。
       若是操做成功,msgget將返回一個非負整數,即該 消息隊列的標識碼 ;若是失敗,則返回「-1」
 
  5.2 msgsnd函數  把消息添加到消息隊列中 函數原型以下:

   int  msgsnd (int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);

 

           msgid: 由msgget函數返回的消息隊列標識碼
      msg_ptr:是一個指針,指針指向準備發送的消息,可是消息的數據結構卻有必定的要求,指針msg_ptr所指向的消息結構必定要是以一個 長整型成員變量開始的 結構                               體接收函數將用這個成員來肯定消息的類型:

        struct my_message{

                  long message_type; /* The data you wish to transfer*/

                  char text[size]; /*the data*/

                 };

          msg_sz:是msg_ptr指向的消息長度,這個長度不能保存消息類型的那個「long int」長整型計算在內
          msgflg:控制着當前消息隊列滿或到達系統上限時將要發生的事情。msgflg=IPC_NOWAIT表示隊列滿不等待,返回EAGAIN錯誤
         「0」,若是失敗,則返回「-1」

  5.3 msgrcv函數  函數原型以下:

      int  msgrcv(int msgid, void *msg_ptr, size_t msgsz, long int msgtype,int msgflg);    
    msgid: 由msgget函數返回的消息隊列標識碼;
    msg_ptr:是一個指針,指針指向準備接收的消息;
      msgsz:是msg_ptr指向的消息長度,這個長度不能保存消息類型的那個「long int」長整型計算在內;
    msgtype:可實現簡單的接收優先級;若是msgtype爲0,就獲取隊列中的第一個消息。若是它的值大於零,將獲取具備相同消息類型的第一個信息。
        若是它小於零,就獲取類型等於或小於msgtype的絕對值的第一個消息;
    msgflg:控制着隊列中沒有相應類型的消息可供接收時將要發生的事;
    操做成功,返回接受字符個數,若是失敗,則返回「-1」;

  5.4 msgctl函數 控制消息隊列,與共享內存shmctl類似  函數原型以下:

     int  msgctl(int msqid, int command, strcut msqid_ds *buf); 

    msqid: 由msgget函數返回的消息隊列標識碼
     command:是將要採起的動做,(有三個可取值)
    若是操做成功,返回「0」;若是失敗,則返回「-1」
    其中command是將要採起的動做,它能夠取3個值,
      IPC_STAT:把msgid_ds結構中的數據設置爲消息隊列的當前關聯值,即用消息隊列的當前關聯值覆蓋msgid_ds的值。
      IPC_SET:若是進程有足夠的權限,就把消息列隊的當前關聯值設置爲       msgid_ds結構中給出的值
      IPC_RMID:刪除消息隊列
    其中buf是指向msgid_ds結構的指針,它指向消息隊列模式和訪問權限的結構。

      struct msgid_ds {

                uid_t shm_perm.uid;

                uid_t shm_perm.gid;

                mode_t shm_perm.mode;

              };

 

歷程代碼: 分爲四個部分,建立消息隊列、不一樣進程接收發和刪除消息隊列

1.建立key爲0x1000的消息隊列: msgget.c文件

 1 #include<stdio.h>
 2 #include<sys/types.h>
 3 #include<sys/ipc.h>
 4 #include<sys/msg.h>
 5 #include<stdlib.h>
 6 
 7 
 8 int main(int argc, char *argv[])  9 { 10     int ret = msgget((key_t)0x1000, IPC_CREAT | IPC_EXCL | 0666); 11     if(ret == -1) 12  { 13         perror("msgget"); 14  exit(EXIT_FAILURE); 15  } 16     printf("Message id = %d \n",ret); 17     return 0; 18 }

2.往0x1000消息隊列寫數據: msgsnd.c文件

 1 #include<stdio.h>
 2 #include<sys/types.h>
 3 #include<sys/ipc.h>
 4 #include<sys/msg.h>
 5 #include<string.h>
 6 #include<stdlib.h>
 7 #include<getopt.h>
 8 
 9 typedef struct msgbuf 10 { 11     long mtype; 12     char mtext[1024]; 13 }msgbuf_t; 14 int main(int argc, char* argv[]) 15 { 16     int msgid = msgget((key_t)0x1000, 0); 17     if(msgid == -1) 18  { 19         perror("msgget"); 20  exit(EXIT_FAILURE); 21  } 22     char c; 23     msgbuf_t msg= {-1,0}; 24     while((c = getopt(argc, argv, "t:m:")) != -1) 25  { 26         switch(c) 27  { 28             case 't': 29                 msg.mtype = atoi(optarg); 30             break; 31             case 'm': 32  strcpy(msg.mtext, optarg); 33             break; 34             default: 35                 fprintf(stderr, "error option! \n"); 36                 printf("%s -t msgttpe -m message \n",argv[0]); 37             break; 38  } 39  } 40     if(msg.mtype > 0 && msg.mtext[0] != 0) 41  { 42         if(msgsnd(msgid, &msg, strlen(msg.mtext), 0) == -1) 43  { 44             perror("msgsnd"); 45  exit(EXIT_FAILURE); 46  } 47  } 48     return 0; 49 }

3.從0x1000消息隊列讀數據: msgrcv.c文件

 1 #include<stdio.h>
 2 #include<sys/types.h>
 3 #include<sys/ipc.h>
 4 #include<sys/msg.h>
 5 #include<string.h>
 6 #include<stdlib.h>
 7 #include<getopt.h>
 8 
 9 typedef struct msgbuf 10 { 11     long mtype; 12     char mtext[1024]; 13 }msgbuf_t; 14 
15 int main(int argc, char* argv[]) 16 { 17     int msgid = msgget((key_t)0x1000, 0); 18     if(msgid == -1) 19  { 20         perror("msgget"); 21  exit(EXIT_FAILURE); 22  } 23 
24     char c; 25     msgbuf_t msg= {-1,0}; 26     while((c = getopt(argc, argv, "t:m:")) != -1) 27  { 28         switch(c) 29  { 30             case 't': 31                 msg.mtype = atoi(optarg); 32             break; 33             default: 34                 fprintf(stderr, "error option! \n"); 35                 printf("%s -t msgttpe -m message \n",argv[0]); 36             break; 37  } 38  } 39     if(msg.mtype > 0 ) 40  { 41      if(msgrcv(msgid, &msg, sizeof(msg)-5, msg.mtype, IPC_NOWAIT) == -1) 42  { 43             perror("msgsnd"); 44  exit(EXIT_FAILURE); 45  } 46         printf("msgtype = %ld, msg = %s \n",msg.mtype,msg.mtext); 47  } 48     return 0; 49 }

4.刪除消息隊列: msgctl.c文件

 1 #include<stdio.h>
 2 #include<sys/types.h>
 3 #include<sys/ipc.h>
 4 #include<sys/msg.h>
 5 #include<stdlib.h>
 6 #include<string.h>
 7 
 8 int main(int argc, char* argv[])  9 { 10     int msgid = msgget((key_t)0x1000, 0); 11     if(msgid == -1) 12  { 13         perror("msgget"); 14  exit(EXIT_FAILURE); 15  } 16     if(msgctl(msgid, IPC_RMID, NULL) == -1) 17  { 18         perror("msgctl"); 19  exit(EXIT_FAILURE); 20  } 21     return 0; 22 }

Linux下運行過程以下

        

相關文章
相關標籤/搜索