版权声明:本文为博主原创文章,未经博主允许不得转载。https://www.cnblogs.com/Dana-gx/p/9724545.html

一、基本概念

  IPC:Linux下的进程通信。包括6种:信号(signal)、管道(pipe)和命名管道(FIFO)、消息队列(msq)、共享内存(shm)、信号量、套接字(socke)
    POSIX进程间通信包括:posix消息队列、posix信号灯、posix共享内存
    接下来主要讲解的时SYSTEM V消息队列:
          消息队列:提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构
二、为什么用消息队列?与管道的区别?
  相同:
      1> 通信的进程可以是不相关的进程(不同进程)
      2> 都是通过发送和接收的方式来传递数据的
      3> 对每个数据都有一个最大长度的限制

  区别:

      1> 避免命名管道的同步和阻塞问题

      2> 接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能顺序地接收(msgtype,确定收发数据类型)
      3> 消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难
三、消息队列和共享内存查看方法:ipcs

                            

共享内存每列详解:

  第一列就是共享内存的key;        第二列是共享内存的编号shmid;

    第三列就是创建的用户owner;      第四列就是权限perms;
    第五列为创建的大小bytes;             第六列为连接到共享内存的进程数nattach;
    第七列是共享内存的状态status。其中显示“dest”表示共享内存段已经被删除,但是还有用户在使用,当该段内存的mode字段设置为SHM_DEST时
       就会显示“dest”。当用户调用shmctl的IPC_RMID时,内存先查看多少个进程与这个内存关联着,如果关联数为0,就会销毁这段共享内存,否者设置
       这段内存的mod的mode位为SHM_DEST,如果所有进程都不用则删除这段共享内存。
 
四、消息队列结构模型:

           

五、system v下的消息队列接口函数:创建、发送、接受和删除

  int msgget (key_t key, int msgflg);

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

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

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

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

2.往0x1000消息队列写数据: msgsnd.c文件

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

3.从0x1000消息队列读数据: msgrcv.c文件

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

4.删除消息队列: msgctl.c文件

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

Linux下运行过程如下

        

    
 

1.消息队列(queue)的更多相关文章

  1. Python进阶【第二篇】多线程、消息队列queue

    1.Python多线程.多进程 目的提高并发 1.一个应用程序,可以有多进程和多线程 2.默认:单进程,单线程 3.单进程,多线程 IO操作,不占用CPU python的多线程:IO操作,多线程提供并 ...

  2. 消息队列Queue大全

    消息队列Queue大全 (http://queues.io/) 作业队列,消息队列和其他队列.几乎所有你能想到的都在这. 关于 那里有很多排队系统.他们每个人都不同,是为解决某些问题而创建的.这个页面 ...

  3. 消息队列queue

    一.queue 在多线程编程中,程序的解耦往往是一个麻烦的问题,以及在socket网络编程中也会有这样的问题.recv 和send之间,如果服务端有消息,问题需要发送给客户端,而那边的recv 被主程 ...

  4. python消息队列Queue

    实例1:消息队列Queue,不要将文件命名为"queue.py",否则会报异常"ImportError: cannot import name 'Queue'" ...

  5. python多进程之间的通信:消息队列Queue

    python中进程的通信:消息队列. 我们知道进程是互相独立的,各自运行在自己独立的内存空间. 所以进程之间不共享任何变量. 我们要想进程之间互相通信,传送一些东西怎么办? 需要用到消息队列!! 进程 ...

  6. 【c#】队列(Queue)和MSMQ(消息队列)的基础使用

    首先我们知道队列是先进先出的机制,所以在处理并发是个不错的选择.然后就写两个队列的简单应用. Queue 命名空间 命名空间:System.Collections,不在这里做过多的理论解释,这个东西非 ...

  7. day43-python消息队列二-queue模块

    Python提供了Queue模块来专门实现消息队列Queue对象 Queue对象实现一个fifo队列(其他的还有lifo.priority队列,这里不再介绍).queue只有maxsize一个构造参数 ...

  8. 队列Queue:任务间的消息读写,安排起来~

    摘要:本文通过分析鸿蒙轻内核队列模块的源码,掌握队列使用上的差异. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列十三 消息队列Queue>,作者:zhushy . 队列(Queue)是 ...

  9. Java消息队列--ActiveMq 实战

    1.下载安装ActiveMQ ActiveMQ官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Un ...

  10. Android消息队列和Looper

    1. 什么是消息队列 消息队列在android中对应MessageQueue这个类,顾名思义,消息队列中存放了大量的消息(Message) 2.什么是消息 消息(Message)代表一个行为(what ...

随机推荐

  1. CSS 文字装饰 text-decoration & text-emphasis

    在 CSS 中,文字算是我们天天会打交道的一大类了,有了文字,则必不可少一些文字装饰. 本文将讲讲两个比较新的文字装饰的概念 text-decoration 与 text-emphasis,在最后,还 ...

  2. [图论]最短网络:kruskal

    最短网络 目录 最短网络 Description Input Output Sample Input Sample Output 解析 代码 Description 农民约翰被选为他们镇的镇长!他其中 ...

  3. Img2Latex 临时方法

    Img2Latex 临时方法 博客园Markdown编辑器中公式需采用Latex编写,然鹅现在并不想学习Latex 毕竟工科生,写论文也免不了的各种公式 (终极解决方案当然是学会Latex) 1.工具 ...

  4. python基础(二):数据类型

    数据类型 学习Python时,一定要注意Python中数据类型和数据结构的学习,这对于你是否能够学好Python其中很重要的作用. 什么是数据类型? 人类有思想,很容易区分汉字和数字的区别,例如,你知 ...

  5. 详解DNS重绑定攻击

    0x00 前言 DNS重绑定攻击的用法有很多种,这篇文章主要理解DNS重绑定攻击的原理,并介绍如何通过DNS重绑定来攻击内网设备.为了更好的理解DNS重绑定攻击,我们先从Web浏览器的同源策略开始介绍 ...

  6. 自动化kolla-ansible部署ubuntu20.04+openstack-victoria单机

    自动化kolla-ansible部署ubuntu20.04+openstack-victoria单机 欢迎加QQ群:1026880196 进行交流学习 一. 环境信息 1. 硬件信息 型号:Dell ...

  7. java 用枚举替换多if-else

    1.定义抽象类 package com.polaris.design; /** * @author :shi * @date :Created in 2020/8/18 20:15 * @descri ...

  8. Day11_49_HashTable

    HashTable * HashTable是较早期的使用Hash算法的一种容器结构,现在基本已被淘汰,单线程多使用HashMap,多线程使用ConcurrentHashMap. * HashTable ...

  9. Insertion Sort and Merge Sort

    Insertion Sort(插入排序) 思路:for 循环遍历数组中的每一个数 用while将每次遍历到的数于左侧的数进行对比,将小的排到左边 void InsertionSort(int*A, i ...

  10. ReentrantLock理解

    原文出处:http://www.yund.tech/zdetail.html?type=1&id=ef94715a2838f06ab03b8621c23d1613 作者:jstarseven ...