[ English | 简体中文 ]
Message Queue API
openvela provides POSIX-compliant message queue interfaces for asynchronous message passing between tasks. Message queues support priority ordering, where higher-priority messages are received first.
Header file: #include <mqueue.h>
openvela Implementation Notes
- Sending from interrupts:
mq_send()can be called from interrupt context, but behaves differently: it does not check queue size, uses pre-allocated messages (quantity configured byPREALLOC_MQ_IRQ_MSGS) - Notification behavior difference:
mq_notify()sends the notification signal even when a task is waiting to receive a message, which is not fully consistent with the POSIX specification - Timeout values:
mq_timedsend()andmq_timedreceive()use Epoch-based absolute time
Queue Management
mq_open
mqd_t mq_open(const char *mqName, int oflags, ...);
Establishes a connection between the calling task and a message queue. After a successful call, the returned message queue descriptor can be used for subsequent operations until mq_close() is called.
Parameters:
mqNameName of the message queue.oflagsOpen flags, which can be any combination of:O_RDONLYRead-only.O_WRONLYWrite-only.O_RDWRRead-write.O_CREATCreate the message queue if it does not exist.O_EXCLUsed withO_CREAT, fails if the queue already exists.O_NONBLOCKNon-blocking mode.
...Optional arguments required whenO_CREATis used:mode(mode_t) File permission bits. Not used in the current implementation, but required by POSIX.attr(struct mq_attr *) Queue attributes. IfNULL, default values are used.mq_maxmsgsets the maximum number of messages,mq_msgsizesets the maximum message size.
Returns:
Returns a message queue descriptor (mqd_t) on success, or -1 (ERROR) on failure and sets errno:
ENOENTO_CREATwas not set and the specified queue does not exist.EEXISTBothO_CREATandO_EXCLwere set, but the queue already exists.EINVALInvalid argument (e.g.,mqNameisNULL).ENOMEMInsufficient memory to create the queue.ENFILESystem message queue limit reached.
POSIX Compatibility: Compatible with the POSIX interface of the same name.
mq_close
int mq_close(mqd_t mqdes);
Closes a message queue descriptor, releasing system resources allocated to the task. If the task has registered a notification request on this queue, the notification is cancelled.
Parameters:
mqdesMessage queue descriptor.
Returns:
Returns 0 on success, or -1 (ERROR) on failure and sets errno:
EBADFmqdesis not a valid message queue descriptor.
Notes:
- Calling
mq_close()whilemq_send()ormq_receive()is blocked is undefined behavior. - Using the same
mqdesafter closing is undefined behavior.
POSIX Compatibility: Compatible with the POSIX interface of the same name.
mq_unlink
int mq_unlink(const char *mqName);
Removes the named message queue. If any tasks still have the queue open, the removal is deferred until all descriptors are closed.
Parameters:
mqNameName of the message queue.
Returns:
Returns 0 on success, or -1 (ERROR) on failure and sets errno:
ENOENTThe specified queue does not exist.EINVALmqNameisNULL.
POSIX Compatibility: Compatible with the POSIX interface of the same name.
Sending Messages
mq_send
int mq_send(mqd_t mqdes, const void *msg, size_t msglen, int prio);
Sends a message to a message queue. Messages are ordered by priority, with higher-priority messages placed before lower-priority ones. prio must not exceed MQ_PRIO_MAX.
If the queue is full and O_NONBLOCK is not set, the call blocks until space becomes available. If O_NONBLOCK is set, it returns an error immediately.
Parameters:
mqdesMessage queue descriptor.msgMessage to send.msglenLength of the message in bytes, must not exceedmq_msgsize.prioMessage priority.
Returns:
Returns 0 on success, or -1 (ERROR) on failure and sets errno:
EAGAINQueue is full andO_NONBLOCKis set.EINVALmsgormqdesisNULL, orpriois invalid.EPERMMessage queue was not opened for writing.EMSGSIZEmsglenexceeds the queue'smq_msgsize.EINTRInterrupted by a signal.
Notes:
mq_send()can be called from interrupt context, but behaves differently: it does not check queue size (always sends), uses pre-allocated messages (quantity configured byPREALLOC_MQ_IRQ_MSGS), and does not allocate new memory.
POSIX Compatibility: Compatible with the POSIX interface of the same name.
mq_timedsend
int mq_timedsend(mqd_t mqdes, const void *msg, size_t msglen, int prio,
const struct timespec *abstime);
Sends a message with a timeout. Behaves the same as mq_send(), but when the queue is full, blocks at most until the absolute time specified by abstime.
Parameters:
mqdesMessage queue descriptor.msgMessage to send.msglenLength of the message in bytes.prioMessage priority.abstimeAbsolute timeout (Epoch-based).
Returns:
Returns 0 on success, or -1 (ERROR) on failure and sets errno:
EAGAINQueue is full andO_NONBLOCKis set.EINVALmsgormqdesisNULL, orpriois invalid.EPERMMessage queue was not opened for writing.EMSGSIZEmsglenexceeds the queue'smq_msgsize.EINTRInterrupted by a signal.ETIMEDOUTTimed out.
POSIX Compatibility: Compatible with the POSIX interface of the same name.
Receiving Messages
mq_receive
ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio);
Receives the oldest message with the highest priority from the message queue. msglen must not be less than the queue's mq_msgsize, otherwise an error is returned.
If the queue is empty and O_NONBLOCK is not set, the call blocks until a message is available. Among multiple waiting tasks, the one with the highest priority and longest wait time receives first.
Parameters:
mqdesMessage queue descriptor.msgBuffer to receive the message.msglenBuffer size in bytes.prioIf notNULL, stores the priority of the received message.
Returns:
Returns the message length in bytes on success, or -1 (ERROR) on failure and sets errno:
EAGAINQueue is empty andO_NONBLOCKis set.EPERMMessage queue was not opened for reading.EMSGSIZEmsglenis less than the queue'smq_msgsize.EINTRInterrupted by a signal.
POSIX Compatibility: Compatible with the POSIX interface of the same name.
mq_timedreceive
ssize_t mq_timedreceive(mqd_t mqdes, char *msg, size_t msglen,
unsigned int *prio, const struct timespec *abstime);
Receives a message with a timeout. Behaves the same as mq_receive(), but when the queue is empty, blocks at most until the absolute time specified by abstime.
Parameters:
mqdesMessage queue descriptor.msgBuffer to receive the message.msglenBuffer size in bytes.prioIf notNULL, stores the priority of the received message.abstimeAbsolute timeout (Epoch-based).
Returns:
Returns the message length in bytes on success, or -1 (ERROR) on failure and sets errno:
EAGAINQueue is empty andO_NONBLOCKis set.EPERMMessage queue was not opened for reading.EMSGSIZEmsglenis less than the queue'smq_msgsize.EINTRInterrupted by a signal.ETIMEDOUTTimed out.
POSIX Compatibility: Compatible with the POSIX interface of the same name.
Queue Attributes
mq_setattr
int mq_setattr(mqd_t mqdes, const struct mq_attr *mqStat, struct mq_attr *oldMqStat);
Sets message queue attributes. Only the O_NONBLOCK bit in mq_flags can be modified.
Parameters:
mqdesMessage queue descriptor.mqStatNew attributes.oldMqStatIf notNULL, stores the attributes before modification.
Returns:
Returns 0 on success, or -1 (ERROR) on failure and sets errno:
EBADFmqdesis not a valid descriptor.EINVALmqStatisNULL.
POSIX Compatibility: Compatible with the POSIX interface of the same name.
mq_getattr
int mq_getattr(mqd_t mqdes, struct mq_attr *mqStat);
Gets the current attributes of a message queue.
Parameters:
mqdesMessage queue descriptor.mqStatReturns the attribute structure:mq_maxmsgMaximum number of messages in the queue.mq_msgsizeMaximum message size in bytes.mq_flagsMessage queue flags.mq_curmsgsCurrent number of messages in the queue.
Returns:
Returns 0 on success, or -1 (ERROR) on failure and sets errno:
EBADFmqdesis not a valid descriptor.EINVALmqStatisNULL.
POSIX Compatibility: Compatible with the POSIX interface of the same name.
Notification
mq_notify
int mq_notify(mqd_t mqdes, const struct sigevent *notification);
Registers or cancels message arrival notification. When a message arrives at a previously empty queue, a signal notification is sent to the registered task.
If notification is NULL, the current registration is cancelled. The registration is automatically cancelled after the notification is sent and must be re-registered.
Parameters:
mqdesMessage queue descriptor.notificationNotification configuration, including:sigev_notifyNotification method (should beSIGEV_SIGNAL).sigev_signoSignal number for notification.sigev_valueValue passed with the signal.
Returns:
Returns 0 on success, or -1 (ERROR) on failure and sets errno:
EBADFmqdesis not a valid descriptor.EBUSYAnother task has already registered notification for this queue.EINVALsigev_notifyis not a valid value, or the signal number is invalid.ENOMEMInsufficient memory.
Notes:
- Behavior difference from POSIX: In openvela, the notification signal is still sent to the registered task even when a task is blocked on
mq_receive()waiting for a message. The POSIX specification requires that no notification be sent in this case (the message directly satisfies the waitingmq_receive()).
POSIX Compatibility: Partially compatible with the POSIX interface of the same name (notification timing differs from the POSIX specification).