5.1 概述

消息队列可以认为是一个链表。有写权限的线程可往消息队列中放置消息,有读权限的线程可以从消息队列中取走消息。

消息队列和管道/FIFO的区别:

(1)消息队列往一个队列中写消息前,并不需要有一个进程/线程在等待消息的到达,管道/FIFO需要。

(2)Posix消息队列是随内核的持续性,管道/FIFO是随进程的。

Posix消息队列和System V消息队列的区别:

(1)Posix消息队列的读总是返回最高优先级(类型)的最早消息;System V消息队列的读可以返回指定优先级(类型)的消息;

(2)Posix消息队列可以产生一个信号,System V消息队列不可以。

5.2 函数

5.2.1 mq_open函数

头文件 #include <mqueue.h>
函数原型 mqd_t mq_open(const char *name, int oflag);
  mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
返回值 成功返回消息队列的描述符,失败返回-1
  name:只能以/开头,且之后不能有/
参数 oflag:O_RDONLY、O_WRONLY、O_RDWR、O_CREAT、O_EXCL、O_NOBLOCK
  mode:0666
说明 1.有2个函数的原因和open函数一样,参数中有...可变参数
  2.第4个参数,有的版本传变量的地址,有的版本传变量

5.2.2 mq_close函数

头文件 #include <mqueue.h>
函数原型 int mq_close(mqd_t mqdes);
返回值 成功返回0,失败返回-1
说明 只是关闭消息队列描述符,但消息队列还在系统中

5.2.3 mq_unlink 函数

头文件 #include <mqueue.h>
函数原型 int mq_unlink(const char *name);
返回值 成功返回0,失败返回-1
说明 删除消息队列

注意:

1.编译时需要加上 -lrt

2.程序编译完成后,如果直接运行程序则提示mq_open失败,提示mq_open permission denied。解决办法是:

mkdir /dev/mqueue
mount -t mqueue none /dev/mqueue

5.2.4 mqcreat 程序

 #include <stdio.h>
 #include <unistd.h>
 #include <mqueue.h>

 // mqcreat -e /mqueue
 int main(int argc, char **argv)
 {
     ;
     int flags = O_RDWR | O_CREAT;
     mqd_t mqd = ;

     )
     {
         switch (c)
         {
             case 'e':
                 flags |= O_EXCL;
                 break;
             default:
                 break;
         }
     }

     )
     {
         printf("usage: mqcreate [-e] <name>\n");
         ;
     }

     // 打开或创建一个消息队列
     mqd = mq_open(argv[optind], flags, , );
     )
     {
         perror("mq_open error");
         ;
     }

     // 关闭消息队列
     mq_close(mqd);

     // 删除消息队列
     //mq_unlink(argv[optind]);

     ;
 }

5.3 消息队列的属性

struct mq_attr {
  long mq_flags; /* Flags: 0 or O_NONBLOCK */
  long mq_maxmsg; /* Max. # of messages on queue */
  long mq_msgsize; /* Max. message size (bytes) */
  long mq_curmsgs; /* # of messages currently in queue */
};

每个消息队列有4个属性:是否阻塞、允许最大的消息数量、允许最大的字节、当前消息数量。

1.如果创建一个新队列,指定了mq_maxmsg、mq_msgsize则忽略其他两个成员。

2.如果设置成非阻塞的,则另外三个参数被忽略。

头文件 #include <mqueue.h>
函数原型 int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
  int mq_setattr(mqd_t mqdes, const struct mq_attr *attr, struct mq_attr *oattr);
返回值 成功返回0,失败返回-1

5.3.1 带属性的mq_creat程序

 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <mqueue.h>

 // mqcreat -e -m 1024 -z 8192 /mqueue
 int main(int argc, char **argv)
 {
     ;
     int flags = O_RDWR | O_CREAT;
     mqd_t mqd = ;
     struct mq_attr attr;
     memset(&attr, , sizeof(attr));

     )
     {
         switch (c)
         {
             case 'e':
                 flags |= O_EXCL;
                 break;
             case 'm':
                 attr.mq_maxmsg = atol(optarg);
                 break;
             case 'z':
                 attr.mq_msgsize = atol(optarg);
                 break;
             default:
                 break;
         }
     }

     )
     {
         printf("usage: mqcreate [-e] <name>\n");
         ;
     }

     // 打开或创建一个消息队列
     mqd = mq_open(argv[optind], flags, , attr);
     )
     {
         perror("mq_open error");
         ;
     }

     // 关闭消息队列
     mq_close(mqd);

     // 删除消息队列
     mq_unlink(argv[optind]);

     ;
 }

5.4 mq_send 和 mq_receive 函数

  mq_send是往消息队列中放消息;mq_receive从消息队列中取消息。每个消息都有一个优先级(类型),它是一个小于MQ_PRIO_MAX的无符号整数,Posxi的上限是32。

  mq_receive总是返回队列中在最高优先级的最早消息。而System V的msgrcv函数可以返回指定优先级的最早消息。

头文件 #include <mqueue.h>
函数原型 int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
返回值 成功返回0,失败返回-1
函数原型 ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
返回值 成功返回字节数,失败返回-1
说明 1.mq_receive的len参数不能小于消息的最大值(mq_attr结构中mq_msgsize成员),如果小于就立即返回EMSGSIZE错误
  2.mq_send的prio参数是待发消息的优先级(类型),其值必须小于32位无符号整数
  3.mq_receive的prio参数如果非空,所返回消息的优先级(类型)就放在这个地址中
  4.如果不需要指定优先级,则mq_send的prio参数为0,mq_receive的prio参数为NULL 

5.4.1 mqsend程序

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <mqueue.h>

 // mqsend /mqueue 100 1
 int main(int argc, char **argv)
 {
     ;
     int flags = O_RDWR | O_CREAT;
     mqd_t mqd = ;
     struct mq_attr attr;
     memset(&attr, , sizeof(attr));

     )
     {
         printf("usage: mqsend <name> <bytes> <priority>\n");
         ;
     }

     // 打开或创建一个消息队列
     mqd = mq_open(argv[], flags, , NULL);
     )
     {
         perror("mq_open error");
         ;
     }

     unsigned ]);
     unsigned ]);
     , len);

     int ret = mq_send(mqd, ptr, len, prio);
     )
     {
         perror("mq_send error");
         ;
     }

     // 关闭消息队列
     mq_close(mqd);

     ;
 }

5.4.2 mqreceive程序

  命令行选项-n指定非阻塞模式,这样消息队列中没有消息,mq_receive就返回一个错误。

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <mqueue.h>

 // mqreceive [-n] /mqueue
 int main(int argc, char **argv)
 {
     ;
     int flag = O_RDWR | O_CREAT;
     mqd_t mqd = ;
     struct mq_attr attr;
     unsigned ;

     )
     {
         switch (c)
         {
             case 'n':
                 flag |= O_NONBLOCK;
                 break;
             default:
                 break;
         }
     }

     )
     {
         printf("usage: mareceive [-n] <name>\n");
         ;
     }

     // 打开消息队列
     mqd = mq_open(argv[optind], flag, , );
     )
     {
         perror("mq_open error");
         ;
     }

     // 获取消息队列中消息的最大字节数
     mq_getattr(mqd, &attr);

     );

     int n = mq_receive(mqd, buff, attr.mq_msgsize, &prio);
     printf("read %d bytes, prio:%d\n", n, prio);

     ;
 }

5.5 消息队列限制

  mq_maxmsg  队列中的最大消息数,没有限制

  mq_msgsize  消息的最大字节数,没有限制

  MQ_OPEN_MAX  一个进程能同时打开消息队列的最大数目,有限制,查询方法是:sysconf(_SC_MQ_OPEN_MAX);

  MQ_PRIO_MAX  消息的优先级要小于这个值,有限制,查询方法是:sysconf(_SC_MQ_PRIO_MAX);

5.5.1 mqsysconf 程序

第5章 Posix 消息队列的更多相关文章

  1. 第三十四章 POSIX消息队列

    POSIX消息队列相关函数 mq_open 功能: 用来创建和访问一个消息队列 原型: mqd_t mq_open(const char *name, int oflag); //只能用来打开消息队列 ...

  2. Linux IPC POSIX 消息队列

    模型: #include<mqueue.h> #include <sys/stat.h> #include <fcntl.h> mq_open() //创建/获取消 ...

  3. Posix消息队列

    转载于:http://blog.csdn.net/zx714311728/article/details/53197196 1.消息队列 消息队列可以认为是一个消息链表,消息队列是随内核持续的.队列中 ...

  4. posix 消息队列

    注意 在涉及到posix消息的函数时, gcc 编译时要加-lrt参数, 如 gcc -lrt unpipc.c mqpack.c send.c -o send gcc -lrt unpipc.c m ...

  5. Posix消息队列实现机制

    本文是对<Unix 网络编程 卷2:进程通信>的笔记. 引言 消息队列是进程间通信的一种方式,可是如果不理解他的实现原理,会有众多不理解之处,下面就结合本书中的例子,对posix消息队列来 ...

  6. POSIX 消息队列相关问题

    一.查看和删除消息队列要想看到创建的posix消息队列,需要在root用户下执行以下操作:# mkdir /dev/mqueue# mount -t mqueue none /dev/mqueue删除 ...

  7. Linux IPC实践(7) --Posix消息队列

    1. 创建/获取一个消息队列 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For m ...

  8. 进程间通信--POSIX消息队列

    相关函数: mqd_t mq_open(const char *name, int oflag); mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, si ...

  9. POSIX 消息队列 之 概述 链接方式

    NAMEmq_overview —— POSIX消息队列概述 DESCRIPTIONPOSIX消息队列允许进程以消息的形式交换数据.此API与System V消息队列(msgget(2),msgsnd ...

随机推荐

  1. linux包-下载-curl与wget

    [root@localhost ~]# rpm -qa|grep curllibcurl-7.19.7-37.el6_4.x86_64python-pycurl-7.19.0-8.el6.x86_64 ...

  2. windows知识点

    https://technet.microsoft.com/zh-cn/windows/dd641430  win7相关资源 23. Remtoe FX是微软WIN2008 R2的SP1新功能首先您需 ...

  3. angular模板加载 ----ng-template

    Angularjs作为mvc(或者说mvvm)框架,同样具备模板这一基本概念. NG加载模板的顺序为 内存加载---AJAX加载. 如果排版乱掉,请查阅https://www.zybuluo.com/ ...

  4. es6新特性

    变量-------------------------- let, const:必须直接给一个变量赋值.注意,对象的属性或数组成员还是可以改变的. const MY_OBJECT = {some: 1 ...

  5. SVN的分支、主干合并的使用说明

    EBAPP代码SVN服务器地址:http://scm.jrj.cn/webapp/ 使用右键菜单中SVN的二级菜单Repo-Broswer查看SVN服务器目录结构 目录结构如下: 名称及功能说明: T ...

  6. Zabbix 教程

    Zabbix 教程http://blog.csdn.net/linuxlsq/article/details/52606086 MySQL在以下几种情况会创建临时表:1.UNION查询:2.用到TEM ...

  7. EditText使用详解-包含很多教程上看不到的功能演示

    写道 标题有点大,说是详解,其实就是对EditText的一些常用功能的介绍,包括密码框,电话框,空白提示文字等等的讲解,尽量的介绍详细一点,也就是所谓的详解了..呵呵 广告一下我的应用“我团”,最新1 ...

  8. OpenSSL进行SSL通讯的一些问题

    这两个星期真是被OpenSSL给烦透了,几个很简单基本的问题(如果没人告诉你真的很难测出来)把我搞的..哎,有时候真是不知道自己该不该搞技术,发现自己头脑真是蠢得很... 直接上正题. 第一个问题: ...

  9. TextArea限制输入长度

    cs文件中添加文本框属性this.TextBox.Attributes.Add("MaxLength", "200"); $(document).ready(f ...

  10. 解决tableView分割线左边不到边的情况

    //解决tableView分割线左边不到边的情况//    if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {//  ...