IPC using Message Queues
A message queue is an inter-process communication (IPC) mechanism that allows processes to exchange data in the form of messages between two processes. It allows processes to communicate asynchronously by sending messages to each other where the messages are stored in a queue, waiting to be processed, and are deleted after being processed.
The message queue is a buffer that is used in non-shared memory environments, where tasks communicate by passing messages to each other rather than by accessing shared variables. Tasks share a common buffer pool. The message queue is an unbounded FIFO queue that is protected from concurrent access by different threads.
Events are asynchronous. When a class sends an event to another class, rather than sending it directly to the target reactive class, it passes the event to the operating system message queue. The target class retrieves the event from the head of the message queue when it is ready to process it. Synchronous events can be passed using triggered operations instead.
Many tasks can write messages into the queue, but only one can read messages from the queue at a time. The reader waits on the message queue until there is a message to process. Messages can be of any size.
Functions of Message Queue
There are four important functions that we will use in the programs to achieve IPC using message queues.
1. int msgget (key_t key, int msgflg);
We use the msgget function to create and access a message queue. It takes two parameters.
2. int msgsnd (int msqid, const void *msg_ptr, size_t msg_sz, int msgflg);
This function allows us to add a message to the message queue.
There are two constraints related to the structure of the message. First, it must be smaller than the system limit and, second, it must start with a long int. This long int is used as a message type in the receive function. The best structure of the message is shown below.
Since the message_type is used in message reception, you can't simply ignore it. You must declare your data structure to include it, and it's also wise to initialize it to contain a known value.
3. int msgrcv (int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg);
This function retrieves messages from a message queue.
4. int msgctl (int msqid, int command, struct msqid_ds *buf);
The final function is msgctl, which is the control function.
The msgctl function returns 0 on success and -1 on error. The send or receive function will fail if a message queue is deleted while a process is waiting in an msgsnd or msgrcv function.
Steps to Perform IPC using Message Queues
A message queue is a linked list of messages stored within the kernel and identified by a message queue identifier. Below are the following steps to perform communication using message queues.
Program 1: Let's write a program for IPC using Message Queues to send data to a message queue.
The above program gives this output.
How does it Work?
The structure my_msg declares the long int variable and the char array to store the data sent to the message queue. Then the message queue is created using the msgget() function. Next, read data from the user into the buffer using fgets() and then copy it into the variable some_text of the structure some_data. Finally, send the data to the queue using the msgsnd() function. The strcmp function is used to stop sending the data by comparing the first three characters of the data. If the data starts with "end", it means no more data is to be sent.
Program 2: Now, let's write a program for IPC using Message Queues to receive or read message from the above created message queue.
The above code gives the following output.
How does it work?
The msg_to_rec variable is set to 0 so that the data is received in the same order as sent. The while is used to continuously receive the data using the mgrcv() function until the text received is "end", which we check using the strcmp function. The data is read using the structure my_msg.