FreeRTOS+POSIX之消息队列API详解

FreeRTOS+POSIX概述

可移植操作系统接口(Portable Operating System Interface,缩写为POSIX)是IEEE为要在各种UNIX操作系统上运行软件,而定义API的一系列互相关联的标准的总称,其正式称呼为IEEE Std 1003,而国际标准名称为ISO/IEC 9945。它基本上是Portable Operating System Interface(可移植操作系统接口)的缩写,而X则表明其对Unix API的传承。FreeRTOS + POSIX实现了POSIX线程 API 的子集。借助FreeRTOS + POSIX,可以轻松将现有的POSIX兼容应用程序移植到FreeRTOS生态系统。FreeRTOS + POSIX部分实现了IEEE Std 1003.1-2017 Edition The Open Group Technical Standard Base Specification,Issue 7。

FreeRTOS + POSIX主要实现了任务管理、互斥量、条件变量、消息队列和时钟/定时器等POSIX接口功能。

FreeRTOS+POSIX之消息队列API详解

FreeRTOS+POSIX消息队列

消息队列提供一种任务间通信机制。消息队列支持异步或者同步的消息通信,支持阻塞、非阻塞的消息发送和接收。提供创建、删除、打开、关闭消息队列以及发送、接受消息、限时发送、限时接受消息、获取消息队列属性等应用编程接口。

mqd_t mq_open(const char * name,int oflag,mode_t mode,struct mq_attr * attr )

打开命名消息队列

mq_open()用于创建一个新的命名消息队列,或打开一个已存在的命名消息队列。该接口的返回值称为消息队列描述符,其他接口可以用这个描述符来指定消息队列。如果其他任务以同样的名字调用该接口,那么任务打开的消息队列描述符将指向同一个消息队列。

参数:

name:消息队列名,其长度限制为 NAME_MAX,如果 name 不是已存在的消息队列的名字, 并且 oflag 参数中没有包含 O_CREAT 标志,那么该接口将失败。

oflag:消息队列选项,用来指定对消息队列的接收和/或发送访问权限。其值可以是O_RDWR, O_CREAT, O_EXCL, and O_NONBLOCK。

mode 该参数FreeRTOS系统不支持。

attr 参数用于指定消息队列的属性,如果 attr 为空,那就使用缺省属性。

返回值:

执行成功返回消息队列描述符;

(mqd_t)-1函数执行失败,并设定 errno 指出错误。

int mq_close(mqd_t mqdes) 关闭命名消息队列

mq_close()用于关闭一个命名的消息队列。 该接口的功能与关闭一个已打开文件的 close函数类似,会解除消息队列描述符 mqdes 和它的消息队列间的关联关系,调用任务关闭消息队列后,将不能再使用该消息队列描述符,但其消息队列并不会从系统中删除,除非已经有任务调用 mq_unlink()删除了该消息队列,并且当前对 mq_close()的调用关闭的是最后一个对消息队列 mqdes 的引用。

参数

mqdes消息队列描述符。

返回值:

0 函数执行成功;

-1 函数执行失败,并设定 errno 指出错误。

int mq_unlink(const char * name) 删除消息队列

mq_unlink ()该接口用于删除 name 指定的消息队列。在成功调用 mq_unlink()后,如果在没有设置oflag 中的 O_CREAT 标志的情况下以 name 调用 mq_open(), 调用会失败。在消息队列没有真正删除前,以 name 调用 mq_open()重新创建消息队列会返回新的消息队列描述符。如果在调用 mq_unlink()时,有一个或多个任务打开了消息队列,那么消息队列的删除操作会推迟,直到所有对该消息队列的引用都被关闭(即最后一个 mq_close()被调用), mq_unlink()调用会在删除消息队列名字后立即返回,不需要阻塞。

参数:

name 消息队列名。

返回值:

0 函数执行成功;

-1 函数执行失败,不会改变消息队列,设定 errno 指出错误。

ssize_t mq_receive(mqd_t mqdes,char * msg_ptr,size_t msg_len,unsigned int * msg_prio )

接收消息

mq_receive()用来会从 mqdes 指定的消息队列中接收最高优先级消息中最早的消息。如果由参数msg_len 指定的缓存区大小小于消息队列属性 mq_msgsize,调用会失败并返回错误,否则,选定的消息会从队列中删除,并复制到 msg_ptr 指向的缓存区中。如果指定的消息队列为空,且消息队列描述符 mqdes 没有设置 O_NONBLOCK 标志位mq_receive()会阻塞,直到一个消息加入到队列中或接口调用被信号中断。如果有多个任务在等待接收消息,当消息到达时,等待的任务会按照消息队列的属性 mq_waitqtype 的设置来解除任务的阻塞。如果指定的消息队列为空,且消息队列描述符 mqdes 设置了 O_NONBLOCK 标志位,则返回错误。

参数:

mqdes 消息队列描述符;

msg_ptr 存放消息的缓存地址;

msg_len 存放消息的缓存区的长度;

msg_prio 消息的优先级,该参数FreeRTOS不支持。

返回值:

>0 函数执行成功,从队列中删除选定的消息,返回选定消息的字节长度;

-1 函数执行失败,不删除消息,设定 errno 指出错误。

int mq_send(mqd_t mqdes,const char * msg_ptr,size_t msg_len,unsigned msg_prio )

发送消息

mq_send ()用来将 msg_ptr 指向的消息添加到 mqdes 指定的消息队列中。如果消息队列已满,且消息队列描述符 mqdes 中没有设置 O_NONBLOCK 标志,那么调用任务会阻塞,直到消息队列空间可用或者调用被信号中断;如果设置了 O_NONBLOCK 标志,调用任务就不会阻塞,直接返回错误。如果有多个任务在等待发送,那么在消息队列空间可用时,等待的任务会按照消 息 队 列 的 属 性 mq_waitqtype 的 设 置 来 解 除 任 务 的 阻 塞 。 如 果 mq_waitqtype 设 置 为PTHREAD_WAITQ_PRIO , 则 按 照 优 先 级 策 略 解 除 任 务 的 阻 塞 ; 如 果 mq_waitqtype 设 置 为PTHREAD_WAITQ_FIFO,则按照 FIFO 的策略解除任务的阻塞。

参数:

mqdes 消息队列描述符;

msg_ptr 存放消息的缓存地址;

msg_len 消息长度,其取值应小于等于消息队列的 msg_msgsize 属性,否则调用会失败;

msg_prio 消息的优先级,该参数FreeRTOS不支持。

返回值:

0 函数执行成功;

-1 函数执行失败,消息不会入队,设定 errno 指出错误。

int mq_getattr(mqd_t mqdes,struct mq_attr * mqstat )获取消息队列属性

该接口用来获取消息队列的属性和状态信息,结果会返回到参数 mqstat 引用的数据结构 mq_attr 中。接口调用成功后,结构变量 mqstat 的成员 mq_flags 被设置为打开消息队列时设置的值; mq_maxmsg 和 mq_msgsize 被设置为打开消息队列时所设置的值; mq_curmsgs 则被设置为消息队列的当前状态,标示当前队列上的消息数。

参数:

mqdes 消息队列描述符;

mqstat 存放消息队列属性的缓存地址。

返回值:

0 函数执行成功;

-1 函数执行失败,设定 errno 指出错误。

ssize_tmq_timedreceive(mqd_tmqdes,char * msg_ptr,size_t msg_len,unsigned * msg_prio,const structtimespec* abstime )

限时接收消息

mq_timedreceive()的功能与 mq_receive()类似, 从 mqdes 指定的消息队列中接收最高优先级消息最早的消息,但是如果任务在通过 mq_open()打开消息队列时没有设置O_NONBLOCK 标志,且队列中没有适合接收的消息,那么经过指定时间后会终止等待消息。如果设置了 O_NONBLOCK 标志,那么该接口等同于 mq_receive()。当调用任务阻塞等待超过了 abs_timeout 指定的绝对时间,或者调用该接口时已经过了 abs_timeout 指定的绝对时间,就会发生超时。如果任务调用该接口时可以立即从消息队列中接收消息,就不会发生超时错误,并且不必检查参数 abs_timeout 的合法性。

参数:

mqdes 消息队列描述符;

msg_ptr 存放消息的缓存地址;

msg_len 存放消息的缓存区的长度;

msg_prio 消息的优先级,该参数FreeRTOS不支持。

abs_timeout 等待时间。

返回值:

>0 函数执行成功,从队列中删除选定的消息,并返回消息的字节长度;

-1 函数执行失败,不删除消息,设定 errno 指出错误。

int mq_timedsend(mqd_t mqdes,const char * msg_ptr,size_t msg_len,unsigned msg_prio,const struct timespec * abstime )

限时发送消息

mq_timedsend()的功能与 mq_send()类似,用来向 mqdes 指定的消息队列中添加一个消息,但是如果指定消息队列已满,并且消息队列描述符 mqdes 中没有设置 O_NONBLOCK 标志,那么在超时到期时会终止任务的阻塞。如果消息队列设置了 O_NONBLOCK 标志,该接口等价于 mq_send()。当调用任务阻塞等待超过了 abs_timeout 指定的绝对时间,或者调用该接口时已经过了 abs_timeout指定的绝对时间,就会发生超时。如果接口调用时消息队列中有足够的空间使得消息可以立即添加到队列中,那么该接口将不会发生超时错误,并且不必检查参数 abs_timeout 的合法性。

参数:

mqdes 消息队列描述符;

msg_ptr 存放消息的缓存地址;

msg_len 消息长度;

msg_prio 消息的优先级,该参数FreeRTOS不支持;

abs_timeout 等待时间。

返回值:

0 函数执行成功, mq_send()和 mq_timedsend() 函数返回 0;

-1 函数执行失败,消息不会入队,设定 errno 指出错误。

消息队列用例可参考FreeRTOS_plus_POSIX_demo.zip压缩包中posix_demo.c文件。


分享到:


相關文章: