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下运行过程以下

        

相关文章
相关标签/搜索