Next | Prev | Up | Top | Contents | Index

System V Messages

The message mechanism allows processes to exchange data stored in buffers. This data is transmitted between processes in discrete units called messages. Processes using this type of IPC can perform two operations: sending messages and receiving messages.

Before a process can send or receive messages, the process must request that the operating system generate a new message queue (the mechanism used to control and keep track of messages) and an associated data structure. A process makes this request by using the msgget() system call. The requesting process becomes the owner and creator of the resulting message queue, and specifies the initial operation permissions for all processes that might use that queue (including itself). Subsequently, the owning process can relinquish ownership or change the operation permissions using the msgctl() system call. However, the creator remains the creator as long as the queue exists. Other processes with permission can use msgctl() to perform various other control functions, as described in "Controlling Message Queues: msgctl()."

A process that is attempting to send a message can suspend execution temporarily in order to wait until the process that is to receive the message is ready; similarly, a receiving process can suspend execution until the sending process is ready. Message operations that suspend execution in this fashion are called "blocking message operations." A process that specifies that its execution is not to be suspended--that is, a process that does not wait for communication if such is not immediately available--is performing a "nonblocking message operation."

A blocking message operation can be told to suspend a calling process until one of three conditions occurs:

To request a message operation, the calling process passes arguments to a system call, and the system call attempts to perform its function. If the system call is successful, it returns its results. Otherwise, it returns a known error code (-1), and an external error variable, errno, is set accordingly.


Message Structures

Before a message can be sent or received, a uniquely identified message queue and data structure must be created. The unique identifier created is called the message queue identifier (msqid); it is used to reference the associated message queue and data structure.

Each message queue has a data structure associated with it. This data structure is declared as struct msqid_ds in the /usr/include/sys/msg.h header file and contains the following fields:

msg_perm Permisssions information as struct ipc_perm
msg_first, msg_last Pointers to queue of message structures
msg_cbytes Number of bytes on the queue
msg_qnum Number of messages on the queue
msg_qbytes Maximum number of bytes on the queue
msg_lspid Process ID (PID) of last message sender
msg_lrpid PID of last message receiver
msg_stime Last message sent time
msg_rtime Last message receive time.
msg_ctime Last change time

The permissions structure msg_perm is based on another structure called ipc_perm, which is also used as a template for permissions for other forms of IPC. The ipc_perm data structure format can be found in the /usr/include/sys/ipc.h header file.

The message queue points to a chain of header structures that define the messages in the queue. This per-message header is declared as struct msg in /usr/include/msg.h, and includes the following fields:

msg_next Pointer to next message in the queue
msg_type Message type code
msg_ts Text size of message
msg_spot Message text address


Message Operations Overview

The following functions are supplied to manage messages and message queues:

msgget(2) Get access to a message queue.
msgctl(2) Get information about a message queue; change ownership of a queue; or destroy the queue.
msgsnd(2) Send a message to a queue.
msgrcv(2) Receive a message from a queue.

The msgget() system call receives an argument msgflg, which can be set to indicate various flags. When only the IPC_CREAT flag is set in msgflg, msgget() performs one of two tasks:

The task performed is determined by the value of the key argument passed to the msgget() system call. For the first task, if the key is not already in use for an existing msqid, a new msqid is returned with an associated message queue and data structure created for the key, unless some system tuning parameter (such as the maximum allowable number of message queues) would be exceeded.

Instead of requesting a specific key number, you may indicate a key of value zero, which is known as the private key (the constant IPC_PRIVATE is defined to be zero). When you specify IPC_PRIVATE for the key value, a new msqid is always returned with an associated message queue and data structure created for it unless a system tuning parameter would be exceeded. When the ipcs command is performed, the KEY field for the msqid is all zeros, for security reasons.

For the second task, if a msqid exists for the key specified, the value of the existing msqid is returned. If you do not want an existing msqid returned, you can specify a control command (IPC_EXCL) in the msgflg argument passed to the system call. The details of using this system call are discussed in "Getting Message Queues With msgget()"in this chapter.

When performing the first task, the process that calls msgget() becomes the owner/creator, and the associated data structure is initialized accordingly. Remember, ownership can be changed but the creating process always remains the creator; see "Controlling Message Queues: msgctl()." The creator of the message queue also determines the initial operation permissions for it.

Once a uniquely identified message queue and data structure are created, message operations and message control can be used.

The available message operations are sending and receiving. System calls are provided for these operations: msgsnd() and msgrcv(), respectively. Refer to "Operations for Messages: msgsnd() and msgrcv()," for details of these system calls.

Message control is done by using the msgctl() system call. It permits you to control the message facility in the following ways:

Refer to "Controlling Message Queues: msgctl()" for details of the msgctl() system call.


Getting Message Queues With msgget()

This section details the msgget() system call and provides an example program illustrating its use. The prototype of the function is as follows (see also the msgget(2) reference page):

int msgget (key_t key, int msgflg)

The type of the key parameter, key_t, is defined in the types.h header file to be equivalent to an integer.

Upon successful completion, msgget() returns a message queue identifier. A new msqid with an associated message queue and data structure is provided if either of the following is true:

The value passed to the msgflg argument is an integer that specifies access permissions, execution modes, and control fields (commands). Access permissions determine the read/write attributes, while execution modes determine the user/group/other attributes of the msgflg argument. The permissions and modes are collectively referred to as "operation permissions." Table 2-2 shows the numeric values (expressed in octal notation) for the valid operation permissions codes.

Message Queue Operation Permissions Codes
Operation PermissionsOctal Value
Read by Owner (MSG_R)00400
Write by Owner (MSG_W)00200
Read by Group00040
Write by Group00020
Read by Others00004
Write by Others00002

A specific octal value is derived by adding the octal values for the operation permissions desired. For instance, if you want a message queue to be readable by its owner and both readable and writable by others, use the code value 00406 (00400 plus 00004 plus 00002). The constants MSG_R and MSG_W, defined in the msg.h header file, can be used instead of 00400 and 00200, respectively.

Control commands are constants defined in the ipc.h header file. See Table 2-3, which contains the names of the constants that apply to the msgget() system call and their values.

Control Commands (Flags)
Control CommandValue
IPC_CREAT0001000
IPC_EXCL0002000

The value for msgflg is therefore a combination of operation permissions and control commands. To accomplish this combination, perform a bitwise OR (|) on the flags with the operation permissions. The bit positions and values for the control commands in relation to those of the operation permissions make this possible.

Two examples:

msqid = msgget (key, (IPC_CREAT | MSG_R));
msqid = msgget (key, (IPC_CREAT | IPC_EXCL | 0400));
The msgget() system call attempts to return a new msqid if either of the following conditions is true:

To satisfy the first condition, simply pass IPC_PRIVATE as the key argument when calling msgget():

msqid = msgget (IPC_PRIVATE, msgflg);
The second condition is satisfied if the value for key is not already associated with an msqid and a bitwise AND of msgflg and IPC_CREAT gives "true" (1). This means that the given key is not currently being used to refer to any message queue on the computer the program is running on, and that the IPC_CREAT flag is set in msgflg.

Note: The system tuning parameter MSGMNI determines the maximum number of unique message queues (msqids) in the UNIX operating system. Attempting to exceed MSGMNI always causes a failure. IPC_EXCL is another control flag used with IPC_CREAT to exclusively have the system call fail if, and only if, a msqid exists for the specified key provided. This is necessary to prevent the process from thinking that it has received a new (unique) msqid when it has not. In other words, when both IPC_CREAT and IPC_EXCL are specified, a new msqid is returned if the system call is successful.

Refer to the intro(2) reference page for details about the data structures associated with a message queue. The specific failure conditions, with error names, are listed there as well.


Message Queue Example Program

The example program in this section (Example 2-4) is a menu-driven program that exercises all possible combinations of the msgget() system call.

From studying this program, you can observe the method of passing arguments and receiving return values. The user-written program requirements are pointed out.

This program begins (lines 4-8) by including the required header files as specified by the msgget(2) reference page. Note that the errno.h header file is included instead of declaring errno as an external variable; either method works.

Variable names have been chosen to be as close as possible to those in the synopsis for the system call. Their declarations are self-explanatory. This choice of names makes the program more readable, and it is perfectly legal since the variables are local to this program.

The variables in this program and their purposes are as follows:

key The value for the desired message queue key
opperm The desired operation permissions
opperm_flags The combination from the logical ORing of the opperm and flags variables; used in the system call to pass the msgflg argument
msqid The message queue identification number for a successful system call or the error code (-1) for an unsuccessful one

The program begins by prompting for a hexadecimal key, an octal operation permissions code, and finally for the control command combinations (flags), which are selected from a menu (lines 15-32). All possible combinations are allowed even though they might not be viable. This allows observing the errors for illegal combinations.

Next, the menu selection for the flags is combined with the operation permissions, and the result is stored in the opperm_flags variable (lines 36-51).

The system call is made next, and the result is stored in the msqid variable (line 53).

Since the msqid variable now contains a valid message queue identifier or the error code (-1), it is tested to see if an error occurred (line 55). If msqid equals -1, a message indicates that an error resulted, and the external errno variable is displayed (lines 57, 58).

If no error occurred, the returned message queue identifier is displayed (line 62).

Example 2-4 : msgget() System Call Example

1  /*This is a program to illustrate the capabilities of
2   *the msgget() (message-get) system call.
3   */
4  #include <stdio.h>
5  #include <sys/types.h>
6  #include <sys/ipc.h>
7  #include <sys/msg.h>
8  #include <errno.h>
9  /*Start of main C program*/
10 main()
11 {
12     key_t key;
13     int opperm, flags; 
14     int msqid, opperm_flags; 
15     /*Enter the desired key*/ 
16     printf("Enter the desired key in hex = "); 
17     scanf("%x", &key);
18     /*Enter the desired octal operation
19       permissions.*/
20     printf("\nEnter the operation ");
21     printf("permissions in octal = "); 
22     scanf("%o", &opperm);
23     /*Set the desired flags.*/
24     printf("\nEnter corresponding number to\n"); 
25     printf("set the desired flags:\n");
26     printf("No flags = 0\n");
27     printf("IPC_CREAT = 1\n");
28     printf("IPC_EXCL = 2\n"); 
29     printf("IPC_CREAT and IPC_EXCL = 3\n");
30     printf(" Flags = ");
31     /*Get the flag(s) to be set.*/ 
32     scanf("%d", &flags);
33     /*Check the values.*/
34     printf ("\nkey =0x%x, opperm = 0%o, flags = 0%o\n",
35         key, opperm, flags);
36     /*Incorporate the control fields (flags) with
37       the operation permissions*/
38     switch (flags)
39     {
40     case 0: /*No flags are to be set.*/
41         opperm_flags = (opperm | 0);
42         break; 
43     case 1: /*Set the IPC_CREAT flag.*/ 
44         opperm_flags = (opperm | IPC_CREAT);
45         break;
46     case 2: /*Set the IPC_EXCL flag.*/
47         opperm_flags = (opperm | IPC_EXCL); 
48         break; 
49     case 3: /*Set the IPC_CREAT and IPC_EXCL flags.*/
50         opperm_flags = (opperm | IPC_CREAT | IPC_EXCL);
51     }
52     /*Call the msgget() system call.*/
53     msqid = msgget (key, opperm_flags);
54     /*Perform the following if the call failed.*/
55     if(msqid == -1)
56     {
57         printf ("\nThe msgget system call failed!\n");
58         printf ("The error number was %d.\n", errno);
59     }
60     /*Return the msqid upon successful completion.*/
61     else 
62         printf ("\nThe msqid is %d.\n", msqid);
63     exit(0);
64 }

Next | Prev | Up | Top | Contents | Index