[ English | 简体中文 ]
消息队列 API
openvela 提供符合 POSIX 标准的消息队列接口,用于任务间的异步消息传递。消息队列支持优先级排序,高优先级消息优先被接收。
头文件:#include <mqueue.h>
openvela 实现说明
- 中断中发送:
mq_send()可在中断上下文中调用,但行为不同:不检查队列大小,使用预分配消息(数量由PREALLOC_MQ_IRQ_MSGS配置) - 通知行为差异:
mq_notify()即使有任务在等待接收消息,仍会发送通知信号,与 POSIX 规范不完全一致 - 超时时间:
mq_timedsend()和mq_timedreceive()使用基于 Epoch 的绝对时间
队列管理
mq_open
mqd_t mq_open(const char *mqName, int oflags, ...);
在调用任务和消息队列之间建立连接。成功调用后,返回的消息队列描述符可用于后续操作,直到调用 mq_close()。
参数:
mqName消息队列的名称。oflags打开标志位,可以是以下的任意组合:O_RDONLY只读。O_WRONLY只写。O_RDWR读写。O_CREAT如果消息队列不存在则创建。O_EXCL与O_CREAT配合,如果队列已存在则失败。O_NONBLOCK非阻塞模式。
...可选参数,当使用O_CREAT时需要提供:mode(mode_t)文件权限位。当前实现中未使用,但 POSIX 要求提供。attr(struct mq_attr *)队列属性。如果为NULL则使用默认值。mq_maxmsg设置最大消息数,mq_msgsize设置最大消息大小。
返回值:
成功时返回消息队列描述符(mqd_t),失败时返回 -1(ERROR)并设置 errno:
ENOENT未设置O_CREAT且指定的队列不存在。EEXIST同时设置了O_CREAT和O_EXCL,但队列已存在。EINVAL参数无效(如mqName为NULL)。ENOMEM内存不足,无法创建队列。ENFILE系统消息队列数量已达上限。
POSIX 兼容性:兼容 POSIX 同名接口。
mq_close
int mq_close(mqd_t mqdes);
关闭消息队列描述符,释放系统分配给该任务的资源。如果任务在该队列上注册了通知请求,通知会被取消。
参数:
mqdes消息队列描述符。
返回值:
成功时返回 0,失败时返回 -1(ERROR)并设置 errno:
EBADFmqdes不是有效的消息队列描述符。
注意:
- 在
mq_send()或mq_receive()阻塞时调用mq_close()的行为是未定义的。 - 关闭后再次使用同一
mqdes的行为是未定义的。
POSIX 兼容性:兼容 POSIX 同名接口。
mq_unlink
int mq_unlink(const char *mqName);
删除指定名称的消息队列。如果有任务仍然打开了该队列,删除会推迟到所有描述符都关闭后执行。
参数:
mqName消息队列的名称。
返回值:
成功时返回 0,失败时返回 -1(ERROR)并设置 errno:
ENOENT指定名称的队列不存在。EINVALmqName为NULL。
POSIX 兼容性:兼容 POSIX 同名接口。
消息发送
mq_send
int mq_send(mqd_t mqdes, const void *msg, size_t msglen, int prio);
将消息发送到消息队列。消息按优先级排序,高优先级消息排在低优先级之前。prio 不能超过 MQ_PRIO_MAX。
如果队列已满且未设置 O_NONBLOCK,调用阻塞直到有空间可用。如果设置了 O_NONBLOCK,立即返回错误。
参数:
mqdes消息队列描述符。msg要发送的消息。msglen消息的字节长度,不能超过mq_msgsize。prio消息优先级。
返回值:
成功时返回 0,失败时返回 -1(ERROR)并设置 errno:
EAGAIN队列已满且设置了O_NONBLOCK。EINVALmsg或mqdes为NULL,或prio无效。EPERM消息队列未以写模式打开。EMSGSIZEmsglen超过队列的mq_msgsize。EINTR被信号中断。
注意:
mq_send()可在中断上下文中调用,但行为不同:不检查队列大小(总是发送),使用预分配消息(数量由PREALLOC_MQ_IRQ_MSGS配置),不分配新内存。
POSIX 兼容性:兼容 POSIX 同名接口。
mq_timedsend
int mq_timedsend(mqd_t mqdes, const void *msg, size_t msglen, int prio,
const struct timespec *abstime);
带超时的消息发送。行为与 mq_send() 相同,但在队列满时最多阻塞到 abstime 指定的绝对时间。
参数:
mqdes消息队列描述符。msg要发送的消息。msglen消息的字节长度。prio消息优先级。abstime绝对超时时间(基于 Epoch)。
返回值:
成功时返回 0,失败时返回 -1(ERROR)并设置 errno:
EAGAIN队列已满且设置了O_NONBLOCK。EINVALmsg或mqdes为NULL,或prio无效。EPERM消息队列未以写模式打开。EMSGSIZEmsglen超过队列的mq_msgsize。EINTR被信号中断。ETIMEDOUT超时。
POSIX 兼容性:兼容 POSIX 同名接口。
消息接收
mq_receive
ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio);
从消息队列接收优先级最高且最早的消息。msglen 不能小于队列的 mq_msgsize,否则返回错误。
如果队列为空且未设置 O_NONBLOCK,调用阻塞直到有消息可用。多个等待任务中,优先级最高且等待最久的任务优先接收。
参数:
mqdes消息队列描述符。msg接收消息的缓冲区。msglen缓冲区大小(字节)。prio如果非NULL,存储接收到的消息的优先级。
返回值:
成功时返回消息长度(字节),失败时返回 -1(ERROR)并设置 errno:
EAGAIN队列为空且设置了O_NONBLOCK。EPERM消息队列未以读模式打开。EMSGSIZEmsglen小于队列的mq_msgsize。EINTR被信号中断。
POSIX 兼容性:兼容 POSIX 同名接口。
mq_timedreceive
ssize_t mq_timedreceive(mqd_t mqdes, char *msg, size_t msglen,
unsigned int *prio, const struct timespec *abstime);
带超时的消息接收。行为与 mq_receive() 相同,但在队列空时最多阻塞到 abstime 指定的绝对时间。
参数:
mqdes消息队列描述符。msg接收消息的缓冲区。msglen缓冲区大小(字节)。prio如果非NULL,存储接收到的消息的优先级。abstime绝对超时时间(基于 Epoch)。
返回值:
成功时返回消息长度(字节),失败时返回 -1(ERROR)并设置 errno:
EAGAIN队列为空且设置了O_NONBLOCK。EPERM消息队列未以读模式打开。EMSGSIZEmsglen小于队列的mq_msgsize。EINTR被信号中断。ETIMEDOUT超时。
POSIX 兼容性:兼容 POSIX 同名接口。
队列属性
mq_setattr
int mq_setattr(mqd_t mqdes, const struct mq_attr *mqStat, struct mq_attr *oldMqStat);
设置消息队列属性。mq_flags 中只有 O_NONBLOCK 位可以被修改。
参数:
mqdes消息队列描述符。mqStat新属性。oldMqStat如果非NULL,存储修改前的属性。
返回值:
成功时返回 0,失败时返回 -1(ERROR)并设置 errno:
EBADFmqdes不是有效的描述符。EINVALmqStat为NULL。
POSIX 兼容性:兼容 POSIX 同名接口。
mq_getattr
int mq_getattr(mqd_t mqdes, struct mq_attr *mqStat);
获取消息队列的当前属性。
参数:
mqdes消息队列描述符。mqStat返回属性结构体:mq_maxmsg队列中的最大消息数。mq_msgsize最大消息大小(字节)。mq_flags消息队列标志。mq_curmsgs当前队列中的消息数。
返回值:
成功时返回 0,失败时返回 -1(ERROR)并设置 errno:
EBADFmqdes不是有效的描述符。EINVALmqStat为NULL。
POSIX 兼容性:兼容 POSIX 同名接口。
通知
mq_notify
int mq_notify(mqd_t mqdes, const struct sigevent *notification);
注册或取消消息到达通知。当消息到达先前为空的队列时,向注册的任务发送信号通知。
如果 notification 为 NULL,取消当前注册。通知发送后注册自动取消,需要重新注册。
参数:
mqdes消息队列描述符。notification通知配置,包括:sigev_notify通知方式(应为SIGEV_SIGNAL)。sigev_signo通知使用的信号编号。sigev_value随信号传递的值。
返回值:
成功时返回 0,失败时返回 -1(ERROR)并设置 errno:
EBADFmqdes不是有效的描述符。EBUSY另一个任务已注册了该队列的通知。EINVALsigev_notify不是有效值,或信号编号无效。ENOMEM内存不足。
注意:
- 与 POSIX 的行为差异:在 openvela 中,即使有任务正在
mq_receive()上阻塞等待消息,通知信号仍会发送给注册的任务。POSIX 规范要求此时不发送通知(消息直接满足等待的mq_receive())。
POSIX 兼容性:部分兼容 POSIX 同名接口(通知时机与 POSIX 规范有差异)。