Some sample source
Heres a little test program that fully demonstrates the POSIX message queue API. Be sure to see
the descriptions of each of the calls to understand fully what's going on:
#include <mqueue.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define MSG_SIZE 4096
// This handler will be called when the queue
// becomes non-empty.
void handler (int sig_num) {
printf ("Received sig %d.\n", sig_num);
}
void main () {
struct mq_attr attr, old_attr; // To store queue attributes
struct sigevent sigevent; // For notification
mqd_t mqdes, mqdes2; // Message queue descriptors
char buf[MSG_SIZE]; // A good-sized buffer
unsigned int prio; // Priority
// First we need to set up the attribute structure
attr.mq_maxmsg = 300;
attr.mq_msgsize = MSG_SIZE;
attr.mq_flags = 0;
// Open a queue with the attribute structure
mqdes = mq_open ("sideshow-bob", O_RDWR | O_CREAT,
0664, &attr);
// Now open a queue with the default attribute structure
mqdes2 = mq_open ("troy-mcclure", O_RDWR | O_CREAT,
0664, 0);
// This will now be a temporary queue...as soon as it's closed,
// it will be removed
mq_unlink ("troy-mcclure");
// Get the attributes for Sideshow Bob
mq_getattr (mqdes, &attr);
printf ("%d messages are currently on the queue.\n",
attr.mq_curmsgs);
if (attr.mq_curmsgs != 0) {
// There are some messages on this queue....eat em
// First set the queue to not block any calls
attr.mq_flags = MQ_NONBLOCK;
mq_setattr (mqdes, &attr, &old_attr);
// Now eat all of the messages
while (mq_receive (mqdes, &buf[0], MSG_SIZE, &prio) != -1)
printf ("Received a message with priority %d.\n", prio);
// The call failed. Make sure errno is EAGAIN
if (errno != EAGAIN) {
perror ("mq_receive()");
_exit (EXIT_FAILURE);
}
// Now restore the attributes
mq_setattr (mqdes, &old_attr, 0);
}
// We want to be notified when something is there
signal (SIGUSR1, handler);
sigevent.sigev_signo = SIGUSR1;
if (mq_notify (mqdes, &sigevent) == -1) {
if (errno == EBUSY)
printf (
"Another process has registered for notification.\n");
_exit (EXIT_FAILURE);
}
for (prio = 0; prio <= MQ_PRIO_MAX; prio += 8) {
printf ("Writing a message with priority %d.\n", prio);
if (mq_send (mqdes, "I8-)", 4, prio) == -1)
perror ("mq_send()");
}
// Close all open message queue descriptors
mq_close (mqdes);
mq_close (mqdes2);
The first time the example program is run, the output should be as follows:
$ mq_test
0 messages are currently on the queue.
Writing a message with priority 0.
Received sig 16.
Writing a message with priority 8.
Writing a message with priority 16.
Writing a message with priority 24.
Writing a message with priority 32.
After the program wrote to the empty queue, it was signalled that the queue had made the
transition from empty to nonempty. The second time the example program is run, the following
should be produced:
$ mq_test
5 messages are currently on the queue.
Received a message with priority 32.
Received a message with priority 24.
Received a message with priority 16.
Received a message with priority 8.
Received a message with priority 0.
Writing a message with priority 0.
Received sig 16.
Writing a message with priority 8.
Writing a message with priority 16.
Writing a message with priority 24.
Writing a message with priority 32.
Note that the first message received was the message with the highest priority, with all of the
other priorities following in suit.
End-users perspective
Because all message queues exist in the pathname space, it's very easy for end users to determine
the status of a queue. From the shell, the user must first change directories to the prefix owned by
Mqueue:
$ cd /dev/mqueue
A simple ls may reveal the following:
/dev/mqueue $ ls
homer ned marge otto
This tells us that there are currently four message queues in the system. To get more detailed
information, try ls with the "long listing" option:
/dev/mqueue $ ls -l
total 0
nrw-rw-r-- 1 bryan techies 0 Jun 30 13:47 homer
nrw-rw-r-- 1 bryan techies 0 Jun 30 13:29 marge
nrw-rw-r-- 1 bryan techies 0 Jun 30 13:46 ned
nrw-rw-r-- 1 bryan techies 0 Jun 30 13:29 otto
This is a little more useful. Starting from the left, the n in the first column of each entry says that
this is a special named file. This is so something like vi knows that it shouldn't attempt to edit it.
Following the n, each entry has its permissions. These are identical to file permissions. In this
case:
the user can read and write
the group can read and write
the rest of the world can only read
Following this we have a 1, which is meaningless. If you can think of a useful stat to go there
(it's the st_status field) let QSSL know. Following the 1, we have the owner, the group, the
number of messages currently on the queue (right now all of these queues are empty), the time of
creation, and finally the name.
If you want a little more information, try the little-used ls -i (this specifies the "inode" option,
and is useful for filesystems):
/dev/mqueue $ ls -i
1024 homer 1024 ned
1024 marge 1024 otto
Now we know the capacity of each of these queues (in this case, 1024 messages). Lets try
sending something to our good friend Ned Flanders:
/dev/mqueue $ echo Hidelee-ho, Neighbor >> ned
Now if we do an ls -il we should see the following:
/dev/mqueue $ ls -il
total 1
1024 nrw-rw-r-- 1 bryan techies 0 Jun 30 13:47 homer
1024 nrw-rw-r-- 1 bryan techies 0 Jun 30 13:29 marge
1024 nrw-rw-r-- 1 bryan techies 1 Jun 30 13:46 ned
1024 nrw-rw-r-- 1 bryan techies 0 Jun 30 13:29 otto
There's a message on ned, so lets extract it:
/dev/mqueue $ cat < ned
Hidelee-ho, Neighbor
^C