Exploring System V Message Queues in Linux

Exploring System V Message Queues in Linux

INTRODUCTION

In a multitasking Linux environment, multiple processes often need to exchange data and coordinate their actions. While shared memory offers fast access, it can become complex when synchronization is required, especially with frequent read/write operations or when only selective processes need to communicate. This is where System V Message Queues come into play—a structured and reliable form of Interprocess Communication (IPC).

Message queues allow processes to send and receive messages in a FIFO (First-In, First-Out) manner, ensuring orderly and isolated data transfer without the need for shared memory space. They support multiple message types, enabling targeted communication between specific processes. Ideal for applications dealing with small, discrete data packets, message queues simplify process interaction with built-in message categorization and queue control.

In this tutorial, you’ll learn the core system calls—msgget(), msgsnd(), msgrcv(), and msgctl()—used to implement message queue communication in C. We’ll also walk through a hands-on example where one process sends and another receives messages, giving you practical experience in building efficient Linux IPC systems.

Message Queues

Why do we need message queues when we already have the shared memory? It would be for multiple reasons, let us try to break this into multiple points for simplification –

  • As understood, once the message is received by a process it would be no longer available for any other process. Whereas in shared memory ,the data is available for multiple processes to access.
  • If we want to communicate with small message formats
  • Shared memory data need to be protected with synchronization when multiple processes communicating at the same time.
  • Frequency of writing and reading using the shared memory is high then it would be very complex to implement the functionality. Not worth with regard utilization in this kind of cases.
  • What if all the processes do not need to access the shared memory but very few process only need it, it would be better to implement with message queues.
  • If we want to commutate with different data packets, say process A is sending message type 1 to process B ,Message type 10 to process C, and message type 20 to process D. In this case, it is simplify to implement with message queues. TO Simplify the given message type as 1,10,20,it can be either 0 or +ve or –ve as discussed below
  • Of course ,the  order of message queue is FIFO (First In First Out) The first message inserted in the queue is the first one to be retrieved

Using shared memory or message queues depends on the need of the application and how effectively it can be utilized.

Communication using message queues can happen in the following ways –

Writing into the shared memory by one process and reading from the shared memory by another process. As we are aware, reading can be done with multiple processes as well

Exploring System V Message Queues in Linux

Writing into the shared memory by one process with different data packets and reading from it by multiple processes, i.e as per message type.



Exploring System V Message Queues in Linux

Having seen certain information on message queues ,Now it is time to check for the system call (system V) Which supports the message queues.

To perform communication using message queues, following are the steps

Step 1:- Create a message queue or connect to an already existing message queue(msgget())

Step 2:- Write into message queue(msgsnd())

Step 3:- Read from the message queue(msgrcv())

Step 4:- Perform control operations on the message queue(msgctl())

Now ,let us check the syntax and certain information on the above calls.

#include <sys/types.h> 

#include <sys/ipc.h> 

#include <sys/msg.h> 

int msgget(key_t key, int msgflg)

This system call creates or allocates a system V message queue. Following arguments need to be passed –

The first argument ,Key ,recognizes the message queue. The key can be either an arbitrary value or one that can be derives from the library function ftok().

The second argument ,Shmflg, Specifies the required message queue flag/s such as IPC_CREAT (Creating message queue if not exists) or IPC_EXCL(Used with IPC_CREAT to create the message queue and the call fails, if the message queue already exists).  Need to pass the permissions as well.

Note:- Refer earlier sections for details on permissions.

This call would return a valid message queue identifier(Used for further calls of message queue) on success and -1 in case of failure To know the cause of failure, check with errno variable or perror() function.

Various errors with respect to this call are EACCESS  (Permission denied),

EEXIST (Queue already exists cant create),ENOENT(queue doesn’t exist),ENOMEM(not enough memory to creat the queue),etc.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)

This system call send/Appends a message into the message queue(System V) Following arguments need to be passed –

  • The first argument ,msgid ,recognized the message queue i.e message queue identifier. The identifier value is received upon the success of msgget()
  • The second argument ,msgp, is the pointer to the message , sent to the caller, defined in the structure of the following form –

struct msgbuf

{

long mtype;

char mtext[1];

};

The variable mtype is used for communicating with different message types. The variable mtext is an array or other structure whose size is specified by msgsz(positive value). If the mtext field is not mentioned, then it is considered as zero size message ,Which is permitted.

  • The third argument, msgsz
    Specifies the size of the message to be received.
    (Note: The message should end with a null character \0.)
  • The fourth argument, msgtype, indicates the type of message:
    1. If msgtype is 0– Reads the first received message in the queue.
    2. If msgtype is positive– Reads the first message of type msgtype in the queue.
      (For example, if msgtype is 10, it reads only the first message of type 10 even if other types are at the beginning of the queue.)
    3. If msgtype is negative– Reads the first message of the lowest type less than or equal to the absolute value of msgtype.
      (For example, if msgtype is -5, it reads the first message of type 1 to 5.)
  • The fifth argument, msgflg, indicates special options or flags:
    1. IPC_NOWAIT – Returns immediately if no message is found in the queue.
    2. MSG_NOERROR – Truncates the message text if it is longer than the size specified by msgsz.

This call would return the number of bytes actually received in mtext array on success and -1 in case of failure. To know the cause of failure, check with errno variable or perror() function.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

int msgctl(int msgid, int cmd, struct msqid_ds *buf)

This system call performs control operations of the message queue (System V). Following arguments need to be passed –

  • The first argument, msgid
    Recognizes the message queue; it is the message queue identifier.
    The identifier value is obtained upon the successful execution of msgget().
  • The second argument, cmd
    Specifies the commandto perform the required control operation on the message queue.
    Valid values for cmd include:
    1. IPC_STAT – Copies the current values of the message queue data structure into a user-defined structure.
    2. IPC_SET – Updates the permission fields (such as UID, GID, and mode) of the queue.
    3. IPC_RMID – Removes the message queue from the system.
    4. IPC_INFO – Provides information about system limits and parameters for message queues (non-standard).
    5. MSG_INFO and MSG_STAT – Provide message-specific information (system dependent).

Steps for Message Queue Communication in C

Step 1 – Create two separate processes:

  • One for sendingdata into the message queue (msgq_send.c)
  • One for retrievingdata from the message queue (msgq_recv.c)

Step 2 – Create a unique key using the ftok() function.

  • For this, first create a file named msgq.txt.
  • This file is used by ftok() to generate a consistent and unique key for the message queue.

Step 3 – In the sending process, perform the following:

  • Create or access the message queue using msgget().
  • Define the message structure (with long mtype and message text).
  • Fill in the message data.
  • Use msgsnd() to send the message to the queue.