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. shell之here文档

    http://www.cnblogs.com/xiangzi888/archive/2012/03/24/2415077.html在shell脚本程序中,向一条命令传递输入的一种特殊方法是使用here ...

  2. vs2010设置 "行号显示"

    Microsoft Visual Studio 2010 默认情况下是不显示代码的行号的.在编译出错时,可点击下面输出窗口中的错误提示进行定位. 但是这样操作起来你有没有感觉到不方便呢. 不显示行号时 ...

  3. Why we made vorlon.js and how to use it to debug your JavaScript remotely

    Vorlon.js is powered by node.JS, socket.io, and late-night coffee. I would like to share with you wh ...

  4. HTML5之Canvas绘图实例——饼状图

    实现饼状分布画图(如下):调试环境:Firefox

  5. python input() 与 raw_input()

    使用input和raw_input都可以读取控制台的输入,但是input和raw_input在处理数字时是有区别的 当输入为纯数字时: input返回的是数值类型,如int,floatraw_inpo ...

  6. Maven最佳实践:版本管理

    什么是版本管理 首先,这里说的版本管理(version management)不是指版本控制(version control),但是本文假设你拥有基本的版本控制的知识,了解subversion的基本用 ...

  7. JDBC Driver

    Infomix Driver: com.informix.jdbc.IfxDriver JDBC URL : jdbc:informix-sqli://<host>:<port> ...

  8. 51nod 1056

    n<=10000000000 然后欧拉函数的前缀和可以用莫比乌斯函数的前缀和快速求,注意各种取模 #include<cstdio> typedef long long i64; ,P ...

  9. 重复ID的记录,只显示其中1条

    --重复ID的记录,只显示其中1条 --生成原始表 select * into #tempTable from ( select '1' as id ,'a' as name union all se ...

  10. ResultSet的getInt(),getString()方法

     数据库tt的examstudent数据表如下:   在MySQL中执行查询语句如下: ResultSet rs = null; String sql="SELECT flow_id,Typ ...