Programming Interfaces Guide

System V Messages

Before a process can send or receive a message, you must initialize the queue through msgget(2). The owner or creator of a queue can change its ownership or permissions using msgctl(2). Any process with permission can use msgctl(2) for control operations.

IPC messaging enables processes to send and receive messages and queue messages for processing in an arbitrary order. Unlike the file byte-stream data flow of pipes, each IPC message has an explicit length.

Messages can be assigned a specific type. A server process can thus direct message traffic between clients on its queue by using the client process PID as the message type. For single-message transactions, multiple server processes can work in parallel on transactions sent to a shared message queue.

Operations to send and receive messages are performed by msgsnd(2) and msgrcv(2), respectively. When a message is sent, its text is copied to the message queue. msgsnd(2) and msgrcv(2) can be performed as either blocking or non-blocking operations. A blocked message operation remains suspended until one of the following three conditions occurs:

Initializing a Message Queue

msgget(2) initializes a new message queue. It can also return the message queue ID (msqid) of the queue corresponding to the key argument. The value passed as the msgflg argument must be an octal integer with settings for the queue's permissions and control flags.

The MSGMNI kernel configuration option determines the maximum number of unique message queues that the kernel supports. msgget(2) fails when this limit is exceeded.

The following code illustrates msgget(2).


#include <sys/ipc.h>
 #include <sys/msg.h>

 ...
 	key_t	key;		/* key to be passed to msgget() */
 	int	msgflg,	/* msgflg to be passed to msgget() */
 			msqid;	/* return value from msgget() */
 	...
 	key = ...
 	msgflg = ...
 	if ((msqid = msgget(key, msgflg)) == -1)
 	{
 		perror("msgget: msgget failed");
 		exit(1);
 	} else
 		(void) fprintf(stderr, "msgget succeeded");
 	...

Controlling Message Queues

msgctl(2) alters the permissions and other characteristics of a message queue. The msqid argument must be the ID of an existing message queue. The cmd argument is one of the following:

IPC_STAT

Place information about the status of the queue in the data structure pointed to by buf. The process must have read permission for this call to succeed.

IPC_SET

Set the owner's user and group ID, the permissions, and the size (in number of bytes) of the message queue. A process must have the effective user ID of the owner, creator, or superuser for this call to succeed.

IPC_RMID

Remove the message queue specified by the msqid argument.

The following code illustrates msgctl(2) with all its various flags.


#include			<sys/types.h>
 #include			<sys/ipc.h>
 #include			<sys/msg.h>

 	...
 	if (msgctl(msqid, IPC_STAT, &buf) == -1)  {
 		perror("msgctl: msgctl failed");
 		exit(1);
 	}
 	...
 	if (msgctl(msqid, IPC_SET, &buf) == –1) {
 		perror("msgctl: msgctl failed");
 		exit(1);
 	}
 	...

Sending and Receiving Messages

msgsnd(2) and msgrcv(2) send and receive messages, respectively. The msqid argument must be the ID of an existing message queue. The msgp argument is a pointer to a structure that contains the type of the message and its text. The msgsz argument specifies the length of the message in bytes. The msgflg argument passes various control flags.

The following code illustrates msgsnd(2) and msgrcv(2).


#include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>

 ...
 	int				msgflg;	/* message flags for the operation */
 	struct msgbuf 	*msgp;	/* pointer to the message buffer */
 	size_t			msgsz;	/* message size */
		size_t			maxmsgsize;
 	long				msgtyp;	/* desired message type */
 	int				msqid		/* message queue ID to be used */
 	...
 	msgp = malloc(sizeof(struct msgbuf) – sizeof (msgp–>mtext) 
							+ maxmsgsz);
 	if (msgp == NULL) {
 		(void) fprintf(stderr, "msgop: %s %ld byte messages.\n",
 				"could not allocate message buffer for", maxmsgsz);
 		exit(1);
 		...
 		msgsz = ...
 		msgflg = ...
 		if (msgsnd(msqid, msgp, msgsz, msgflg) == –1)
 			perror("msgop: msgsnd failed");
 		...
 		msgsz = ...
 		msgtyp = first_on_queue;
 		msgflg = ...
 		if (rtrn = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) == –1)
 			perror("msgop: msgrcv failed");
 		...