Originally Published: Friday, 24 August 2001 Author: Subhasish Ghosh
Published to: develop_articles/Development Articles Page: 4/5 - [Printable]

Understanding Linux Kernel Inter-process Communication: Pipes, FIFO & IPC (Part 2)

The Linux kernel is a thing of great beauty and learning to understand and appreciate its facets and edges is a worthy and noble pursuit. Take our hand as Linux.com offers this second part of Subhasish Ghosh's look at Inter-Process Communication in the Linux Kernel. Together we will find the grok, sooner or later.

IPC Messages  << Page 4 of 5  >>

IPC Messages

Another IPC resource, which processes can use to communicate with each other is IPC Messages. Each message generated by a process is sent to an "IPC Message Queue", where it stays until another process reads it. So, the question now is: What is this so-called "IPC message" made up of? A message is made up of a fixed-size "header" and a variable-length "text". Thus, it can be labeled with an integer value (the message type) which allows a process to selectively retrieve messages from the message queue. Readers must note that: A message queue is implemented in reality by means of a linked list. Once a process has read a message from an IPC message queue, the Kernel destroys it. Thus, this proves the well-known fact: Only one process can receive a given message. So, let's now see what functions a process needs to invoke in order to send a message and retrieve one.

For sending a message, a process invokes the msgsnd() function, passing as parameters:

  1. The 'IPC Identifier' of the destination message queue.
  2. The message 'text' size.
  3. The address of the User Mode buffer that contains the message type immediately followed by the message text.

For retrieving a message, a process invokes the msgrcv() function, passing as parameters:

  1. The 'IPC Identifier' of the destination message queue resource.
  2. The pointer to a User Mode buffer to which the message type and message text ought to be copied.
  3. The User Mode buffer size.
  4. What message should be retrieved, denoted by a value t.

Now, the integer t can take any one of these three values: either t is null, t is (+ve) or t is (-ve). If the value of t is null, the first message in the queue is returned. If t is positive, the first message in the queue with its type equal to t is returned. Finally, if t is negative, the function returns the first message whose message type is the lowest value less than or equal to the absolute value of t. Till this, it's just fine. Beyond this, make sure you get ready for a real roller-coaster ride. Why? Read on.

Now, let's talk a little about the data structures associated with IPC messages. There exists an "IPC Message Queue Descriptor", whose address is very important since it is used for many critical purposes. Understanding what this "IPC Message Queue Descriptor" is, is where our roller-coaster ride begins. Make sure you hold on tight! The "IPC Message Queue Descriptor" is a msqid_ds structure, whose fields are shown below. The most significant fields are msg_first and msg_last, which point to the first and to the last message in the linked list, respectively. The rwait field points to a "wait queue". A wait queue includes all processes currently waiting for some message in the queue. The wwait field points to a "wait queue" that includes all processes currently waiting for some free space in the queue so they can add a new message. The total size of the header and the text of all messages in the queues cannot exceed the value stored in the msg_qbytes field. The default maximum size is MSGMNB, which is 16,384 bytes.

Type Field Description
struct ipc_perm msg_perm ipc_perm data structure
struct msg * msg_first First message in queue
struct msg * msg_last Last message in queue
long msg_stime Time of last msgsnd()
long msg_rtime Time of last msgrcv()
long msg_ctime Last change time
struct wait_queue * wwait Processes waiting for free space
struct wait_queue * rwait Processes waiting for messages
unsigned short msg_cbytes Current number of bytes in queue
unsigned short msg_qnum Number of messages in queue
unsigned short msg_qbytes Maximum number of bytes in queue
unsigned short msg_lspid PID of last msgsnd()
unsigned short msg_lrpid PID of last msgrcv()

Let's now look at a code snippet illustrating an IPC Message queue in action.

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

int msgget(key_t key, int msgflg);
int msgsnd(int msgid, struct msgbuf *msgp, int msgsz,int msgflg);

int msgrcv(int msgid, struct msgbuf *msgp, int msgsz,long msgtyp, int msgflg );

struct msgbuf
{

long mtype; /* message type, must be > 0 */
char mtext[msgsz]; /* message data */

};

MSGMAX
MSGMNB

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
IPC_STAT
IPC_SET
IPC_RMID
struct msqid_ds;

Now, that we have seen what an IPC message is and in what way it relates to an IPC Message Queue, the most important data structure in action, along with a code snippet illustrating a message queue, its now time for all of us to move on to the next and last section of this article, IPC Shared Memory.





IPC Messages  << Page 4 of 5  >>