TOC PREV NEXT INDEX

POSIX 1.b Migration Guide


Message Queues

The message queue interface has changed extensively. A number of Draft 9 features are completely eliminated in favor of performance improvements and ease of use in POSIX.1b. The following is a list of Draft 9 functions with no equivalent in POSIX.1b; applications that depend on these functions may not migrate easily to POSIX.1b:

Some of the functions above may be partially simulated by other functions in POSIX.1b. For example, mqgetpid() can be simulated by encoding the pid of the process in the message itself. The mqpurge() function can be simulated with mq_receive() in a while loop until it fails. The mqputevt() and mqgetevt() functions can be simulated with the sigqueue() and sigwaitinfo() functions from POSIX.1b, respectively. The msgalloc() and msgfree() functions have no corresponding functionality.

Three other features are no longer supported: asynchronous message sending and receiving; using the MSG_MOVE and MSG_USE flags; and selective removing messages from somewhere other than the head of the queue.

There are other important changes; Draft 9 and POSIX.1b differ with respect to persistence and how the names for message queues are implemented. This is similar to the differences for named semaphores as described in Chapter 7, "Semaphores" on page 67.

A comparison of the various message queue features is provided later in
this chapter.

Creating Message Queues

POSIX.1b message queues are created with the mq_open() function and the O_CREAT flag as opposed to the mkmq() function from Draft 9, as per the following example:

Draft 9 Code

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mqueue.h>

main()
{
int mq;
:
mkmq("message_queue", MQ_PERSIST | 0666);
mq = open("message_queue", O_RDWR | O_NONBLOCK,
MQ_PERSIST | 0666);
:
close(mq);
unlink("message_queue");
:
}

Equivalent POSIX.1b Code

#include <mqueue.h>

main()
{
mqd_t mq;
:
mq = mq_open("message_queue", O_CREAT | O_RDWR |
O_NONBLOCK, 0666, NULL);
:
mq_close(mq);
mq_unlink("message_queue");
:
}

Data Structure Changes

The two data structures, msgcb and mqstatus, from Draft 9 were combined into a single data structure, mq_attr, in POSIX.1b. Also, a number of entries from both of these structures were eliminated. For example, the time stamp and event fields from msgcb have no equivalent in POSIX.1b.

The message length and message data fields from msgcb are now separate arguments for the message sending and receiving functions. A comparison of data structures is provided later in this chapter in "Data Structures".

Getting and Setting Message Queue Attributes

The following example illustrates the comparison of the interfaces to get and set message queue attributes. The mq_maxmsg and mq_msgsize attributes for a POSIX.1b message queue may only be set at creation time. "Changes from Draft 9 to POSIX.1b" tabulates the restrictions on setting attributes for a POSIX.1b message queue.

The default Message Queue attributes are as follows:

Draft 9 Code

#include <sys/mqueue.h>

#define SIZE 1024

main()
{
int mq;
struct mqstatus mqstat;
:
mkmq("message_queue", MQ_PERSIST | 0666);
mq = open("message_queue", O_RDWR | O_NONBLOCK,
MQ_PERSIST | 0666);
:
mqstat.mqmaxmsg = 200;
mqstat.mqrsvmsg = 200;
mqstat.mqmaxbytes = SIZE;
mqstat.mqrsvbytes = SIZE;
mqstat.mqwrap = MQNOWRAP;
mqstat.mqmaxarcv = 20;
mqsetattr(mq, &mqstat);
:
mqgetattr(mq, &mqstat);
printf("mqmaxmsg: %d\n", mqstat.mqmaxmsg);
printf("mqrsvmsg: %d\n", mqstat.mqrsvmsg);
printf("mqmaxbytes: %d\n", mqstat.mqmaxbytes);
printf("mqrsvbytes: %d\n", mqstat.mqrsvbytes);
printf("mqcurmsgs : %d\n", mqstat.mqcurmsgs);
printf("mqsendwait: %d\n", mqstat.mqsendwait);
printf("mqrcvwait : %d\n", mqstat.mqrcvwait);
printf("mqmaxarcv : %d\n", mqstat.mqmaxarcv);
printf("mqwrap: %s\n",
(mqstat.mqwrap==MQWRAP)?"MQWRAP":"MQNOWRAP");
:
close(mq);
unlink("message_queue");
:
}

Equivalent POSIX.1b Code

#include <mqueue.h>

#define SIZE 1024

main()
{
msg_t mq;
struct mq_attr mqattr;
:
mqattr.mq_maxmsg = 200;
mqattr.mq_msgsize = SIZE;
mq = mq_open("message_queue", O_CREAT | O_RDWR,
0666, &mqattr);
:
mqattr.mq_flags = O_NONBLOCK;
mq_setattr(mq, &mqattr, NULL);
:
mq_getattr(mq, &mqattr);
printf("mq_flags : %s\n",
(mqattr.mq_flags & O_NONBLOCK == O_NONBLOCK)
? "Non-Blocking" : "Blocking");
printf("mq_maxmsg : %ld\n", mqattr.mq_maxmsg);
printf("mq_msgsize : %ld\n", mqattr.mq_msgsize);
printf("mq_curmsgs : %ld\n", mqattr.mq_curmsgs);
printf("mq_sendwait: %ld\n", mqattr.mq_sendwait);
printf("mq_rcvwait : %ld\n", mqattr.mq_rcvwait);
:
mq_close(mq);
mq_unlink("message_queue");
:
}

Sending and Receiving Messages

The following example compares the sending and receiving of messages between message queue facilities. The fork() call is only relevant to illustrate how messages may be sent and received between two processes.

Draft 9 Code

#include <sys/mqueue.h>

#define SIZE 1024

main()
{
int mq;
char buffer[SIZE];
struct msgcb msgcbp;
:
mkmq("message_queue", MQ_PERSIST | 0666);
mq = open("message_queue", O_RDWR,MQ_PERSIST | 0666);
:
switch(fork()) {
case 0:
:
msgcbp.msg_flags = 0;
msgcbp.msg_bufsize = SIZE;
msgcbp.msg_data = buffer;
msgcbp.msg_type = 0;
mqreceive(mq, &msgcbp);
:
default:
:
msgcbp.msg_flags = MSG_COPY;
msgcbp.msg_length = SIZE;
msgcbp.msg_bufsize = SIZE;
msgcbp.msg_data = buffer;
msgcbp.msg_type = 0;
mqsend(mq, &msgcbp);
:
}
:
close(mq);
unlink("message_queue");
:
}

Equivalent POSIX.1b Code

#include <mqueue.h>

#define SIZE 1024

main()
{
msg_t mq;
char buffer[SIZE];
:
mq = mq_open("message_queue", O_CREAT | O_RDWR,0666, NULL);
:
switch(fork()) {
case 0:
:
mq_receive(mq, buffer, SIZE, NULL);
:
default:
:
mq_send(mq, buffer, SIZE, MQ_PRIO_MAX-1);
:
}
:
mq_close(mq);
mq_unlink("message_queue");
:
}

Notification of Message Availability

The new mq_notify() function in POSIX.1b is used to notify a process that a message is available on a message queue. This is done by sending a signal to the process when the message queue changes from empty to non-empty as illustrated in the following example.

When a notification request is attached to a message queue, another process may be blocked in mq_receive() waiting to receive a message. If a message arrives at the queue, mq_receive() is completed and the notification request remains pending. If there is no process blocked in mq_receive(), the specified signal handler is called.

The next example uses the flag no_msg to ensure that the notification request is satisfied, and that the same message is received with an mq_receive() call: The sa_flags flag is set to SA_SIGINFO, and the sigev_notify field is set to SIGEV_SIGNAL to ensure the use of a real-time signal:

#include <mqueue.h>
#include <signal.h>

#define SIZE 1024

void signal_handler(int signo, siginfo_t *info, void *context);
volatile int no_msg;

main()
{
mqd_t mq;
char buffer[SIZE];
struct mq_attr mqattr;
struct sigevent notification;
struct sigaction sa;

mqattr.mq_flags = 0;
mqattr.mq_maxmsg = 200;
mqattr.mq_msgsize = SIZE;
mq = mq_open("message_queue", O_CREAT | O_RDWR,
0666, &mqattr);
:
switch(fork()) {
case 0:
:
notification.sigev_signo = SIGRTMIN;
notification.sigev_value.sival_int = 0;
notification.sigev_value.sigev_notify =
SIGEV_SIGNAL;
:
sa.sa_sigaction = signal_handler;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);

sigaction(SIGRTMIN, &sa, NULL);
:
mq_notify(mq, &notification);
:
no_msg = 1;
while (no_msg) {
:
sched_yield();
}
mq_receive(mq, buffer, size, NULL);
:
break;
default:
:
mq_send(mq, buffer, size, MQ_PRIO_MAX-1);
:
}
:
mq_close(mq);
mq_unlink("message_queue");
:
}

void signal_handler(signo, info, context)
int signo;
siginfo_t *info;
void *context;
{
:
no_msg = 0;
:
}

Changes from Draft 9 to POSIX.1b

Interface Changes

Message queues have changed in a fairly major way. A number of facilities from Draft 9 are no longer available; however, POSIX.1b offers a new facility for notification of message availability. The new implementation offers better performance. Speeds comparable to raw memory copy are attainable using the new, simple POSIX.1b functions

Message Queue Interface  
Draft 9
POSIX.1b
Message queue = special file
Independent of file system
Persistent as well as non-persistent message queues with the MQ_PERSIST flag
Persistent message queues
Queue wrapping with MQWRAP
No queue wrapping
Buffer management with MSG_COPY, MSG_USE, MSG_MOVE
All messages copied
Message transfer synchronization control with MSG_WAIT, MSG_ASYNC, MSG_NOWAIT
No message synchronization
Truncation control with MSG_TRUNC
Overlong messages rejected at the time
of sending
Ability to send an event via a
message queue
No event sending
Selective message receive order
No equivalent1
<sys/mqueue.h>
<mqueue.h>
sender_t
mqd_t
open()
mq_open()
close()
mq_close()
mkmq()
Done with mq_open()
unlink()
mq_unlink()
mqsend()
mq_send()
mqreceive()
mq_receive()
mqsetattr()
mq_setattr()
mqgetattr()
mq_getattr()
msgalloc()
No Equivalent
msgfree()
No Equivalent
mqpurge()
No Equivalent
mqgetpid()
No Equivalent
mqputevt()
No Equivalent
mqgetevt()
No Equivalent
No Equivalent
mq_notify()
Notify process that a message is available on a queue.
struct msgcb
struct mqstatus
struct mq_attr
Combines the flags of msgcb and mqstatus.
1
LynxOS provides the mq_selective_receive() function to support this behavior, even though it is not in the POSIX.1b standard.

Data Structures

The msgcb and mqstatus structures are combined into the single mq_attr structure in POSIX.1b.

Data Structure Equivalence  
Draft 9
POSIX.1b
msgcb.msg_flags
mq_attr.mq_flags
msgcb.msg_type
Message Priorities
msgcb.msg_length
No Equivalent
msgcb.msg_bufsize
No Equivalent
msgcb.msg_data
No Equivalent
msgcb.msg_event
No Equivalent
msgcb.msg_errno
No Equivalent
msgcb.msg_timesent
No Equivalent
msgcb.msg_sender
No Equivalent
mqstatus.mqrsvmsg
No Equivalent
mqstatus.mqrsvbytes
No Equivalent
mqstatus.mqmaxmsg
mq_attr.mq_maxmsg
mqstatus.mqmaxbytes
mq_attr.mq_msgsize
mqstatus.mqwrap
No Equivalent
mqstatus.mqmaxarcv
No Equivalent
mqstatus.mqcurmsgs
mq_attr.mq_curmsgs
mqstatus.mqsendwait
No Equivalent
mqstatus.mqrcvwait
No Equivalent

Attributes

There are various restrictions on setting attributes for message queues from POSIX.1b. The table below shows the attributes that may be set, and when. All attributes may be queried at any time.

Message Queue Attributes  
Attribute
Set
mq_flags
Yes, any time after creation
mq_maxmsg
Yes, only at creation
mq_msgsize
Yes, only at creation
mq_curmsgs
No

Messages

Message Priorities

POSIX.1b provides a new concept of message priorities. A message is inserted into the queue, and received from the queue according to message priority. This priority is independent of the process priority.

Selective Receive

Draft 9 message queues allow the application to selectively remove queued messages by type. This facility has been replaced by the message priority facility described above. Note that priorities are somewhat less flexible than message typing, because only the highest priority message is retrievable. LynuxWorks has provided a proprietary extension, mq_selective_receive, to retain
this functionality.

Process Priorities

Process priorities come into the picture when sending and receiving messages. If more than one process is blocked while sending to a full message queue (or receiving from an empty message queue) with priority scheduling, the highest-priority process, which has been waiting the longest, is unblocked first.

Synchronization Control

With Draft 9 message queues, it is possible to control how processes waited for each other by specifying the MSG_WAIT, MSG_ASYNC, and MSG_NOWAIT flags on a per-message basis. Such options are not available with POSIX.1b message queues. All messages in POSIX.1b are sent and received with behavior equivalent to the Draft 9 MSG_NOWAIT.

Buffer Management

With Draft 9 message queues, it is possible to control the use of buffers to achieve higher performance with the MSG_MOVE, MSG_USE, and MSG_COPY flags on a per-message basis. This feature is discontinued in POSIX.1b. All POSIX.1b message queues have behavior equivalent to the MSG_COPY flag from Draft 9.

Sending and Receiving Events

Draft 9 allows events to be sent along message queues. POSIX.1b does not provide this capability.

Purging, Data Buffer Allocation/Freeing

Draft 9 provides the following functions:

mqpurge() purge a message queue
msgalloc() allocate a message data buffer
msgfree() free a message data buffer

The mqpurge() function can be simulated with mq_receive() in a while loop until it fails. The msgalloc() and msgfree() functions have no
corresponding functionality.

Sender ID

The mqgetpid() function from Draft 9 allowed a process to determine the pid of the sender process. There is no equivalent function for this feature in POSIX.1b. However, the user can work around this by encoding the pid in the
message itself.

Queue Wrap

With Draft 9 message queues, it is possible to specify the queue wrap behavior, so that older messages could be overwritten by newer ones as messages were sent to a full queue. This behavior was requested with the MQWRAP flag at message queue creation time. POSIX.1b does not support this capability.

Time-Stamping

It is possible to time-stamp Draft 9 messages. This feature is not supported by POSIX.1b. An application writer can work around this by encoding the time-stamp in the message.

Truncation Control

Draft 9 provides a MSG_TRUNC flag to truncate a message when receiving, if it is larger than the buffer. POSIX.1b does not allow a message to be sent if its length exceeds the message size of the queue, and does not allow mq_receive to be called with a buffer size smaller than the message size.

A Pointer-Worth of Data

Draft 9 provides a MSG_OVERRIDE flag to indicate receipt of a pointer-worth of data. POSIX.1b does not provide special support for such functionality, although
4-byte-long messages are supported.

Notification of Message Availability

POSIX.1b provides the new function, mq_notify(), to notify a process when a message queue changes from empty to non-empty.

exec() Behavior

With Draft 9, message queue file descriptors of a process remain open after exec(), except if the FD_CLOEXEC flag was set. With POSIX.1b, open message queue descriptors of a calling process are closed upon exec().

New Utilities

LynxOS provides two new utilities, lipcs and lipcrm, to list and remove message queues (and other POSIX.1b IPC facilities), respectively; refer to the lipcs and lipcrm man pages for more information.

Interoperability

Draft 9 message queues and POSIX.1b message queues are distinct. There is no interoperability. For example, it is not possible to send a message on a Draft 9 queue and receive it on a POSIX.1b message queue.



LynuxWorks, Inc.
855 Branham Lane East
San Jose, CA 95138
http://www.lynuxworks.com
1.800.255.5969
TOC PREV NEXT INDEX