376 lines
17 KiB
ReStructuredText
376 lines
17 KiB
ReStructuredText
|
==============================
|
||
|
Named Message Queue Interfaces
|
||
|
==============================
|
||
|
|
||
|
NuttX supports POSIX named message queues for inter-task communication.
|
||
|
Any task may send or receive messages on named message queues. Interrupt
|
||
|
handlers may send messages via named message queues.
|
||
|
|
||
|
- :c:func:`mq_open`
|
||
|
- :c:func:`mq_close`
|
||
|
- :c:func:`mq_unlink`
|
||
|
- :c:func:`mq_send`
|
||
|
- :c:func:`mq_timedsend`
|
||
|
- :c:func:`mq_receive`
|
||
|
- :c:func:`mq_timedreceive`
|
||
|
- :c:func:`mq_notify`
|
||
|
- :c:func:`mq_setattr`
|
||
|
- :c:func:`mq_getattr`
|
||
|
|
||
|
.. c:function:: mqd_t mq_open(const char *mqName, int oflags, ...)
|
||
|
|
||
|
Establishes a connection between a named
|
||
|
message queue and the calling task. After a successful call of
|
||
|
mq_open(), the task can reference the message queue using the address
|
||
|
returned by the call. The message queue remains usable until it is
|
||
|
closed by a successful call to mq_close().
|
||
|
|
||
|
:param mqName: Name of the queue to open
|
||
|
:param oflags: Open flags. These may be any combination of:
|
||
|
|
||
|
- ``O_RDONLY``. Open for read access.
|
||
|
- ``O_WRONLY``. Open for write access.
|
||
|
- ``O_RDWR``. Open for both read & write access.
|
||
|
- ``O_CREAT``. Create message queue if it does not already exist.
|
||
|
- ``O_EXCL``. Name must not exist when opened.
|
||
|
- ``O_NONBLOCK``. Don't wait for data.
|
||
|
|
||
|
:param ``...``: **Optional parameters**. When the O_CREAT flag is specified,
|
||
|
POSIX requires that a third and fourth parameter be supplied:
|
||
|
|
||
|
- ``mode``. The mode parameter is of type mode_t. In the POSIX
|
||
|
specification, this mode value provides file permission bits for
|
||
|
the message queue. This parameter is required but not used in the
|
||
|
present implementation.
|
||
|
- ``attr``. A pointer to an mq_attr that is provided to initialize.
|
||
|
the message queue. If attr is NULL, then the messages queue is
|
||
|
created with implementation-defined default message queue
|
||
|
attributes. If attr is non-NULL, then the message queue mq_maxmsg
|
||
|
attribute is set to the corresponding value when the queue is
|
||
|
created. The mq_maxmsg attribute determines the maximum number of
|
||
|
messages that can be queued before addition attempts to send
|
||
|
messages on the message queue fail or cause the sender to block;
|
||
|
the mq_msgsize attribute determines the maximum size of a message
|
||
|
that can be sent or received. Other elements of attr are ignored
|
||
|
(i.e, set to default message queue attributes).
|
||
|
|
||
|
:return: A message queue descriptor or -1 (``ERROR``)
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name. Differences from the full POSIX implementation include:
|
||
|
|
||
|
- The mq_msgsize attributes determines the maximum size of a message
|
||
|
that may be sent or received. In the present implementation, this
|
||
|
maximum message size is limited at 22 bytes.
|
||
|
|
||
|
.. c:function:: int mq_close(mqd_t mqdes)
|
||
|
|
||
|
Used to indicate that the calling task
|
||
|
is finished with the specified message queued mqdes. The mq_close()
|
||
|
deallocates any system resources allocated by the system for use by this
|
||
|
task for its message queue.
|
||
|
|
||
|
If the calling task has attached a notification request to the message
|
||
|
queue via this ``mqdes`` (see ``mq_notify()``), this attachment will be
|
||
|
removed and the message queue is available for another task to attach
|
||
|
for notification.
|
||
|
|
||
|
:param mqdes: Message queue descriptor.
|
||
|
|
||
|
:return: 0 (``OK``) if the message queue is closed successfully, otherwise, -1
|
||
|
(``ERROR``).
|
||
|
|
||
|
**Assumptions/Limitations:**
|
||
|
|
||
|
- The behavior of a task that is blocked on either a ``mq_send()`` or
|
||
|
``mq_receive()`` is undefined when ``mq_close()`` is called.
|
||
|
- The result of using this message queue descriptor after successful
|
||
|
return from ``mq_close()`` is undefined.
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name.
|
||
|
|
||
|
.. c:function:: int mq_unlink(const char *mqName)
|
||
|
|
||
|
Removes the message queue named by
|
||
|
"mqName." If one or more tasks have the message queue open when
|
||
|
``mq_unlink()`` is called, removal of the message queue is postponed
|
||
|
until all references to the message queue have been closed.
|
||
|
|
||
|
:param mqName: Name of the message queue
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name.
|
||
|
|
||
|
.. c:function:: int mq_send(mqd_t mqdes, const void *msg, size_t msglen, int prio)
|
||
|
|
||
|
Adds the specified message, ``msg``, to
|
||
|
the message queue, ``mqdes``. The ``msglen`` parameter specifies the
|
||
|
length of the message in bytes pointed to by ``msg``. This length must
|
||
|
not exceed the maximum message length from the ``mq_getattr()``.
|
||
|
|
||
|
If the message queue is not full, ``mq_send()`` will place the ``msg``
|
||
|
in the message queue at the position indicated by the ``prio`` argument.
|
||
|
Messages with higher priority will be inserted before lower priority
|
||
|
messages The value of ``prio`` must not exceed ``MQ_PRIO_MAX``.
|
||
|
|
||
|
If the specified message queue is full and ``O_NONBLOCK`` is not set in
|
||
|
the message queue, then ``mq_send()`` will block until space becomes
|
||
|
available to the queue the message.
|
||
|
|
||
|
If the message queue is full and ``NON_BLOCK`` is set, the message is
|
||
|
not queued and ``ERROR`` is returned.
|
||
|
|
||
|
**NOTE**: ``mq_send()`` may be called from an interrupt handler.
|
||
|
However, it behaves differently when called from the interrupt level:
|
||
|
|
||
|
- It does not check the size of the queue. It will always post the
|
||
|
message, even if there is already too many messages in queue. This is
|
||
|
because the interrupt handler does not have the option of waiting for
|
||
|
the message queue to become non-full.
|
||
|
- It doesn't allocate new memory (because you cannot allocate memory
|
||
|
from an interrupt handler). Instead, there are are pool of
|
||
|
pre-allocated message structures that may be used just for sending
|
||
|
messages from interrupt handlers. The number of such pre-allocated
|
||
|
messages is a configuration parameter.
|
||
|
|
||
|
:param mqdes: Message queue descriptor.
|
||
|
:param msg: Message to send.
|
||
|
:param msglen: The length of the message in bytes.
|
||
|
:param prio: The priority of the message.
|
||
|
:return: On success, ``mq_send()`` returns 0 (``OK``); on
|
||
|
error, -1 (``ERROR``) is returned, with ```errno`` <#ErrnoAccess>`__ set
|
||
|
to indicate the error:
|
||
|
|
||
|
- ``EAGAIN``. The queue was empty, and the ``O_NONBLOCK`` flag was set
|
||
|
for the message queue description referred to by ``mqdes``.
|
||
|
- ``EINVAL``. Either ``msg`` or ``mqdes`` is ``NULL`` or the value of
|
||
|
``prio`` is invalid.
|
||
|
- ``EPERM``. Message queue opened not opened for writing.
|
||
|
- ``EMSGSIZE``. ``msglen`` was greater than the ``maxmsgsize``
|
||
|
attribute of the message queue.
|
||
|
- ``EINTR``. The call was interrupted by a signal handler.
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name.
|
||
|
|
||
|
.. c:function:: int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio, \
|
||
|
const struct timespec *abstime);
|
||
|
|
||
|
Adds the specified message, ``msg``, to
|
||
|
the message queue, ``mqdes``. The ``msglen`` parameter specifies the
|
||
|
length of the message in bytes pointed to by ``msg``. This length must
|
||
|
not exceed the maximum message length from the ``mq_getattr()``.
|
||
|
|
||
|
If the message queue is not full, ``mq_timedsend()`` will place the
|
||
|
``msg`` in the message queue at the position indicated by the ``prio``
|
||
|
argument. Messages with higher priority will be inserted before lower
|
||
|
priority messages The value of ``prio`` must not exceed ``MQ_PRIO_MAX``.
|
||
|
|
||
|
If the specified message queue is full and ``O_NONBLOCK`` is not set in
|
||
|
the message queue, then ``mq_send()`` will block until space becomes
|
||
|
available to the queue the message or until a timeout occurs.
|
||
|
|
||
|
``mq_timedsend()`` behaves just like ``mq_send()``, except that if the
|
||
|
queue is full and the ``O_NONBLOCK`` flag is not enabled for the message
|
||
|
queue description, then ``abstime`` points to a structure which
|
||
|
specifies a ceiling on the time for which the call will block. This
|
||
|
ceiling is an absolute timeout in seconds and nanoseconds since the
|
||
|
Epoch (midnight on the morning of 1 January 1970).
|
||
|
|
||
|
If the message queue is full, and the timeout has already expired by the
|
||
|
time of the call, ``mq_timedsend()`` returns immediately.
|
||
|
|
||
|
:param mqdes: Message queue descriptor.
|
||
|
:param msg: Message to send.
|
||
|
:param msglen: The length of the message in bytes.
|
||
|
:param prio: The priority of the message.
|
||
|
:return: On success, ``mq_send()`` returns 0 (``OK``); on
|
||
|
error, -1 (``ERROR``) is returned, with ```errno`` <#ErrnoAccess>`__ set
|
||
|
to indicate the error:
|
||
|
|
||
|
- ``EAGAIN``. The queue was empty, and the ``O_NONBLOCK`` flag was set
|
||
|
for the message queue description referred to by ``mqdes``.
|
||
|
- ``EINVAL``. Either ``msg`` or ``mqdes`` is ``NULL`` or the value of
|
||
|
``prio`` is invalid.
|
||
|
- ``EPERM``. Message queue opened not opened for writing.
|
||
|
- ``EMSGSIZE``. ``msglen`` was greater than the ``maxmsgsize``
|
||
|
attribute of the message queue.
|
||
|
- ``EINTR``. The call was interrupted by a signal handler.
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name.
|
||
|
|
||
|
.. c:function:: ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio)
|
||
|
|
||
|
Receives the oldest of the highest
|
||
|
priority messages from the message queue specified by ``mqdes``. If the
|
||
|
size of the buffer in bytes, ``msgLen``, is less than the ``mq_msgsize``
|
||
|
attribute of the message queue, ``mq_receive()`` will return an error.
|
||
|
Otherwise, the selected message is removed from the queue and copied to
|
||
|
``msg``.
|
||
|
|
||
|
If the message queue is empty and ``O_NONBLOCK`` was not set,
|
||
|
``mq_receive()`` will block until a message is added to the message
|
||
|
queue. If more than one task is waiting to receive a message, only the
|
||
|
task with the highest priority that has waited the longest will be
|
||
|
unblocked.
|
||
|
|
||
|
If the queue is empty and ``O_NONBLOCK`` is set, ``ERROR`` will be
|
||
|
returned.
|
||
|
|
||
|
:param mqdes: Message Queue Descriptor.
|
||
|
:param msg: Buffer to receive the message.
|
||
|
:param msglen: Size of the buffer in bytes.
|
||
|
:param prio: If not NULL, the location to store message priority.
|
||
|
:return: One success, the length of the selected message in
|
||
|
bytes is returned. On failure, -1 (``ERROR``) is returned and the
|
||
|
```errno`` <#ErrnoAccess>`__ is set appropriately:
|
||
|
|
||
|
- ``EAGAIN`` The queue was empty and the ``O_NONBLOCK`` flag was set
|
||
|
for the message queue description referred to by ``mqdes``.
|
||
|
- ``EPERM`` Message queue opened not opened for reading.
|
||
|
- ``EMSGSIZE`` ``msglen`` was less than the ``maxmsgsize`` attribute of
|
||
|
the message queue.
|
||
|
- ``EINTR`` The call was interrupted by a signal handler.
|
||
|
- ``EINVAL`` Invalid ``msg`` or ``mqdes``
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name.
|
||
|
|
||
|
.. c:function:: ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen, \
|
||
|
int *prio, const struct timespec *abstime);
|
||
|
|
||
|
Receives the oldest of the highest
|
||
|
priority messages from the message queue specified by ``mqdes``. If the
|
||
|
size of the buffer in bytes, ``msgLen``, is less than the ``mq_msgsize``
|
||
|
attribute of the message queue, ``mq_timedreceive()`` will return an
|
||
|
error. Otherwise, the selected message is removed from the queue and
|
||
|
copied to ``msg``.
|
||
|
|
||
|
If the message queue is empty and ``O_NONBLOCK`` was not set,
|
||
|
``mq_timedreceive()`` will block until a message is added to the message
|
||
|
queue (or until a timeout occurs). If more than one task is waiting to
|
||
|
receive a message, only the task with the highest priority that has
|
||
|
waited the longest will be unblocked.
|
||
|
|
||
|
``mq_timedreceive()`` behaves just like ``mq_receive()``, except that if
|
||
|
the queue is empty and the ``O_NONBLOCK`` flag is not enabled for the
|
||
|
message queue description, then ``abstime`` points to a structure which
|
||
|
specifies a ceiling on the time for which the call will block. This
|
||
|
ceiling is an absolute timeout in seconds and nanoseconds since the
|
||
|
Epoch (midnight on the morning of 1 January 1970).
|
||
|
|
||
|
If no message is available, and the timeout has already expired by the
|
||
|
time of the call, ``mq_timedreceive()`` returns immediately.
|
||
|
|
||
|
:param mqdes: Message Queue Descriptor.
|
||
|
:param msg: Buffer to receive the message.
|
||
|
:param msglen: Size of the buffer in bytes.
|
||
|
:param prio: If not NULL, the location to store message priority.
|
||
|
:param abstime: The absolute time to wait until a timeout is declared.
|
||
|
|
||
|
:return: One success, the length of the selected message in
|
||
|
bytes is returned. On failure, -1 (``ERROR``) is returned and the
|
||
|
```errno`` <#ErrnoAccess>`__ is set appropriately:
|
||
|
|
||
|
- ``EAGAIN``: The queue was empty and the ``O_NONBLOCK`` flag was set
|
||
|
for the message queue description referred to by ``mqdes``.
|
||
|
- ``EPERM``: Message queue opened not opened for reading.
|
||
|
- ``EMSGSIZE``: ``msglen`` was less than the ``maxmsgsize`` attribute
|
||
|
of the message queue.
|
||
|
- ``EINTR``: The call was interrupted by a signal handler.
|
||
|
- ``EINVAL``: Invalid ``msg`` or ``mqdes`` or ``abstime``
|
||
|
- ``ETIMEDOUT``: The call timed out before a message could be
|
||
|
transferred.
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name.
|
||
|
|
||
|
.. c:function:: int mq_notify(mqd_t mqdes, FAR const struct sigevent *notification)
|
||
|
|
||
|
If the ``notification`` input parameter is not
|
||
|
``NULL``, this function connects the task with the message queue such
|
||
|
that the specified signal will be sent to the task whenever the message
|
||
|
changes from empty to non-empty. One notification can be attached to a
|
||
|
message queue.
|
||
|
|
||
|
If ``notification``; is ``NULL``, the attached notification is detached
|
||
|
(if it was held by the calling task) and the queue is available to
|
||
|
attach another notification.
|
||
|
|
||
|
When the notification is sent to the registered task, its registration
|
||
|
will be removed. The message queue will then be available for
|
||
|
registration.
|
||
|
|
||
|
:param mqdes: Message queue descriptor
|
||
|
:param notification: Real-time signal structure containing:
|
||
|
|
||
|
- ``sigev_notify``. Should be SIGEV_SIGNAL (but actually ignored)
|
||
|
- ``sigev_signo``. The signo to use for the notification
|
||
|
- ``sigev_value``. Value associated with the signal
|
||
|
|
||
|
:return: On success ``mq_notify()`` returns 0; on error, -1
|
||
|
is returned, with ``errno`` set to indicate the error:
|
||
|
|
||
|
- ``EBADF``. The descriptor specified in ``mqdes`` is invalid.
|
||
|
- ``EBUSY``. Another process has already registered to receive
|
||
|
notification for this message queue.
|
||
|
- ``EINVAL``. ``sevp->sigev_notify`` is not one of the permitted
|
||
|
values; or ``sevp->sigev_notify`` is ``SIGEV_SIGNAL`` and
|
||
|
``sevp->sigev_signo`` is not a valid signal number.
|
||
|
- ``ENOMEM``. Insufficient memory.
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name. Differences from the full POSIX implementation include:
|
||
|
|
||
|
- The notification signal will be sent to the registered task even if
|
||
|
another task is waiting for the message queue to become non-empty.
|
||
|
This is inconsistent with the POSIX specification which states, "If a
|
||
|
process has registered for notification of message arrival at a
|
||
|
message queue and some process is blocked in ``mq_receive`` waiting
|
||
|
to receive a message when a message arrives at the queue, the
|
||
|
arriving message will satisfy the appropriate ``mq_receive()`` ...
|
||
|
The resulting behavior is as if the message queue remains empty, and
|
||
|
no notification will be sent."
|
||
|
|
||
|
.. c:function:: int mq_setattr(mqd_t mqdes, const struct mq_attr *mqStat, \
|
||
|
struct mq_attr *oldMqStat);
|
||
|
|
||
|
Sets the attributes associated with the
|
||
|
specified message queue "mqdes." Only the "O_NONBLOCK" bit of the
|
||
|
"mq_flags" can be changed.
|
||
|
|
||
|
If ``oldMqStat`` is non-null, mq_setattr() will store the previous message
|
||
|
queue attributes at that location (just as would have been returned by
|
||
|
mq_getattr()).
|
||
|
|
||
|
:param mqdes: Message queue descriptor
|
||
|
:param mqStat: New attributes
|
||
|
:param oldMqState: Old attributes
|
||
|
|
||
|
:return: 0 (``OK``) if attributes are set successfully, otherwise -1
|
||
|
(``ERROR``).
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name.
|
||
|
|
||
|
.. c:function:: int mq_getattr(mqd_t mqdes, struct mq_attr *mqStat)
|
||
|
|
||
|
Gets status information and attributes
|
||
|
associated with the specified message queue.
|
||
|
|
||
|
:param mqdes: Message queue descriptor
|
||
|
:param mqStat: Buffer in which to return attributes. The returned
|
||
|
attributes include:
|
||
|
|
||
|
- ``mq_maxmsg``. Max number of messages in queue.
|
||
|
- ``mq_msgsize``. Max message size.
|
||
|
- ``mq_flags``. Queue flags.
|
||
|
- ``mq_curmsgs``. Number of messages currently in queue.
|
||
|
|
||
|
:return: 0 (``OK``) if attributes provided, -1 (``ERROR``) otherwise.
|
||
|
|
||
|
**POSIX Compatibility:** Comparable to the POSIX interface of the same
|
||
|
name.
|