POSIX 消息队列函数(mq

您所在的位置:网站首页 mq队列禁止取出信息 POSIX 消息队列函数(mq

POSIX 消息队列函数(mq

2024-07-15 20:44| 来源: 网络整理| 查看: 265

概述

消息队列是Linux IPC中很常用的一种通信方式,它通常用来在不同进程间发送特定格式的消息数据。

消息队列和之前讨论过的管道和FIFO有很大的区别,主要有以下两点:

一个进程向消息队列写入消息之前,并不需要某个进程在该队列上等待该消息的到达,而管道和FIFO是相反的,进程向其中写消息时,管道和FIFO必需已经打开来读,那么内核会产生SIGPIPE信号。IPC的持续性不同。管道和FIFO是随进程的持续性,当管道和FIFO最后一次关闭发生时,仍在管道和FIFO中的数据会被丢弃。消息队列是随内核的持续性,即一个进程向消息队列写入消息后,然后终止,另外一个进程可以在以后某个时刻打开该队列读取消息。只要内核没有重新自举,消息队列没有被删除。

消息队列可以认为是一个链表。进程(线程)可以往里写消息,也可以从里面取出消息。一个进程可以往某个消息队列里写消息,然后终止,另一个进程随时可以从消息队列里取走这些消息。这里也说明了,消息队列具有随内核的持续性,也就是系统不重启,消息队列永久存在。

https://blog.csdn.net/anonymalias/article/details/9799645 https://blog.csdn.net/liuhongxiangm/article/details/8716232

需要注意以下几点:

1、消息队列的名字只能以一个 ‘/‘开头,名字中不能包含其他的’/’ 2、mq_receive() 的第三个参数表示读取消息的长度,不能小于能写入队列中消息的最大大小,即一定要大于等于该队列的 mq_attr 结构中 mq_msgsize 的大小。 3、消息的优先级:它是一个小于 MQ_PRIO_MAX 的数,数值越大,优先级越高。 POSIX 消息队列在调用 mq_receive 时总是返回队列中最高优先级的最早消息。如果消息不需要设定优先级,那么可以在 mq_send 是置 msg_prio 为 0, mq_receive 的 msg_prio 置为 NULL。 4、默认情况下mq_send和mq_receive是阻塞进行调用,可以通过mq_setattr来设置为O_NONBLOCK,如: struct mq_attr new_attr; mq_getattr(mqID, &new_attr);//获取当前属性 new_attr.mq_flags = O_NONBLOCK;//设置为非阻塞 mq_setattr(mqID, &new_attr, NULL)//设置属性

1 POSIX消息队列的创建和关闭

POSIX消息队列的创建,关闭和删除用到以下三个函数接口:

#include mqd_t mq_open(const char *name, int oflag, /* mode_t mode, struct mq_attr *attr */); //成功返回消息队列描述符,失败返回-1 mqd_t mq_close(mqd_t mqdes); mqd_t mq_unlink(const char *name); //成功返回0,失败返回-1

mq_open用于打开或创建一个消息队列。

name:表示消息队列的名字,它符合POSIX IPC的名字规则。oflag:表示打开的方式,和open函数的类似。有必须的选项:O_RDONLY,O_WRONLY,O_RDWR,还有可选的选项:O_NONBLOCK,O_CREAT,O_EXCL。mode:是一个可选参数,在oflag中含有O_CREAT标志且消息队列不存在时,才需要提供该参数。表示默认访问权限。可以参考open。attr:也是一个可选参数,在oflag中含有O_CREAT标志且消息队列不存在时才需要。该参数用于给新队列设定某些属性,如果是空指针,那么就采用默认属性。

mq_open返回值是mqd_t类型的值,被称为消息队列描述符。在Linux 2.6.18中该类型的定义为整型:

#include typedef int mqd_t;

mq_close用于关闭一个消息队列,和文件的close类型,关闭后,消息队列并不从系统中删除。一个进程结束,会自动调用关闭打开着的消息队列。

mq_unlink用于删除一个消息队列。消息队列创建后只有通过调用该函数或者是内核自举才能进行删除。每个消息队列都有一个保存当前打开着描述符数的引用计数器,和文件一样,因此本函数能够实现类似于unlink函数删除一个文件的机制。

POSIX消息队列的名字所创建的真正路径名和具体的系统实现有关,关于具体POSIX IPC的名字规则可以参考《UNIX 网络编程 卷2:进程间通信》的P14。

经过测试,在Linux 2.6.18中,所创建的POSIX消息队列不会在文件系统中创建真正的路径名。且POSIX的名字只能以一个’/’开头,名字中不能包含其他的’/’。

创建示例:

#define TEST_MQ_NAME ("/test_mq") static struct mq_attr test_mq_attr; static mqd_t test_mq; test_mq_attr.mq_maxmsg = LOCK_ALARM_MAX_NUM; test_mq_attr.mq_msgsize = LOCK_ALARM_MAX_SIZE; mq_unlink(TEST_MQ_NAME ); test_mq = mq_open(TEST_MQ_NAME , O_RDWR | O_CREAT | O_EXCL | O_NONBLOCK, 0644, &lock_mq_attr); //后面两个参数为可选参数

mq_open: https://www.cnblogs.com/LubinLew/p/POSIX-mq_open.html

2 POSIX消息队列的属性

POSIX标准规定消息队列属性mq_attr必须要含有以下四个内容:

long mq_flags //消息队列的标志:0或O_NONBLOCK,用来表示是否阻塞 long mq_maxmsg //消息队列的最大消息数 long mq_msgsize //消息队列中每个消息的最大字节数 long mq_curmsgs //消息队列中当前的消息数目

在Linux 2.6.18中mq_attr结构的定义如下:

#include struct mq_attr { long int mq_flags; /* Message queue flags. */ long int mq_maxmsg; /* Maximum number of messages. */ long int mq_msgsize; /* Maximum message size. */ long int mq_curmsgs; /* Number of messages currently queued. */ long int __pad[4]; };

POSIX消息队列的属性设置和获取可以通过下面两个函数实现:

#include mqd_t mq_getattr(mqd_t mqdes, struct mq_attr *attr); mqd_t mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr); //成功返回0,失败返回-1

mq_getattr用于获取当前消息队列的属性,mq_setattr用于设置当前消息队列的属性。其中mq_setattr中的oldattr用于保存修改前的消息队列的属性,可以为空。

mq_setattr可以设置的属性只有mq_flags,用来设置或清除消息队列的非阻塞标志。newattr结构的其他属性被忽略。mq_maxmsg和mq_msgsize属性只能在创建消息队列时通过mq_open来设置。mq_open只会设置该两个属性,忽略另外两个属性。mq_curmsgs属性只能被获取而不能被设置。

下面是测试代码:

#include #include #include #include #include #include using namespace std; int main() { mqd_t mqID; mqID = mq_open("/testmQueue", O_RDWR | O_CREAT, 0666, NULL); if (mqID


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3