MQ(3) | Library Functions Manual | MQ(3) |
But arguably in modern systems there is little difference between the efficiency of the System V message queues, pipes, and UNIX domain sockets (if anything, the AT&T System V UNIX message queues tend to be slower than the rest). The fundamental performance bottleneck is however still there with mq as well: data must be first copied from the sender to the kernel and then from the kernel to the receiver. The bigger the message, the higher the overhead.
For realtime applications, mq offers some advantages:
Message queues are named by character strings that represent (absolute) pathnames. The used interface is analogous to the conventional file concepts. But unlike FIFOs and pipes, neither POSIX nor System V message queues are accessed by using open(2), read(2), or write(2). Instead, equivalents such as mq_open(), mq_close(), and mq_unlink() are used.
The standard does not specify whether POSIX message queues are exposed at the file system level. It can be argued that mq inherited an old problem with the System V message queues. Even if an implementation would have support for it, it is not portable to view message queues by ls(1), remove these with rm(1), or adjust the permissions with chmod(1).
struct mq_attr { long mq_flags; long mq_maxmsg; long mq_msgsize; long mq_curmsgs; };
The members in the structure are: flags set for the message queue (mq_flags), the maximum number of messages in the queue (mq_maxmsg), the maximum size of each message (mq_msgsize), and the number of queued messages (mq_curmsgs).
The overall resource requirements for a particular message queue are given by mq_maxmsg and mq_msgsize. These two can be specified when the queue is created by a call to mq_open(). The constraints are enforced through the lifetime of the queue: an error is returned if a message larger than mq_msgsize is sent, and if the message queue is already full, as determined by mq_maxmsg, the call to queue a message will either block or error out.
Although there are two functions, mq_getattr() and mq_setattr(), to retrieve and set attributes, resource limits cannot be changed once the queue has been created. In NetBSD the super user may however control the global resource limits by using few sysctl(7) variables.
Bear in mind that no notification is sent for an arrival of a message to a non-empty message queue. In other words, mq_notify() does not by itself ensure that a process will be notified every time a message arrives. Thus, after having called mq_notify(), an application may need to repeatedly call mq_receive() until the queue is empty. This requires that the message queue was created with the O_NONBLOCK flag; otherwise mq_receive() blocks until a message is again queued or the call is interrupted by a signal. This may be a limitation for some realtime applications.
The basic rule of thumb with realtime prioritization is that low priority tasks should never unnecessarily delay high priority tasks. Priority inheritance is not however part of the provided API; the receiver process may run at low priority even when receiving high priority messages. To address this limitation and other potential realtime problems, the user may consider other functions from the POSIX Real-time Library (librt, -lrt). The process scheduling interface described in sched(3) can be mentioned as an example.
Function | Description |
mq_open(3) | open a message queue |
mq_close(3) | close a message queue |
mq_unlink(3) | remove a message queue |
mq_send(3) | send a message |
mq_receive(3) | receive a message |
mq_timedsend(3) | send a message with a timeout |
mq_timedreceive(3) | receive a message with a timeout |
mq_getattr(3) | get message queue attributes |
mq_setattr(3) | set message queue attributes |
mq_notify(3) | register asynchronous notify |
Richard W. Stevens, UNIX Network Programming, Volume 2: Interprocess Communications, Prentice Hall, Second Edition, 1998.
July 28, 2010 | NetBSD 6.1 |