Inter-Process Communication Using Message Queue
1️⃣ What is a Message Queue?
A message queue is an IPC mechanism that allows processes to exchange messages in the form of structured data.

Unlike pipes:

Processes need not be related

Messages are stored in the kernel

Communication is asynchronous

2️⃣ Types of Message Queues in Linux
System V Message Queues (commonly taught in OS labs)

POSIX Message Queues (advanced)

👉 This example uses System V message queues.

3️⃣ System Calls Used
System Call	Purpose
msgget()	        Create or access message queue
msgsnd()	        Send a message
msgrcv()    	        Receive a message
msgctl()	        Control / delete queue
4️⃣ Message Structure
Every message must begin with a long integer message type.

struct msg_buffer {
    long msg_type;
    char msg_text[100];
};
5️⃣ Communication Model (Example)
Sender process sends a message

Receiver process receives and prints it

6️⃣ Small Example: Message Queue IPC
🔹 Sender Program
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

struct msg_buffer {
    long msg_type;
    char msg_text[100];
};

int main() {
    key_t key;
    int msgid;
    struct msg_buffer message;

    // Generate unique key
    key = ftok("progfile", 65);

    // Create message queue
    msgid = msgget(key, 0666 | IPC_CREAT);

    message.msg_type = 1;
    strcpy(message.msg_text, "Hello from sender process");

    // Send message
    msgsnd(msgid, &message, sizeof(message.msg_text), 0);

    printf("Message sent: %s\n", message.msg_text);

    return 0;
}
🔹 Receiver Program
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct msg_buffer {
    long msg_type;
    char msg_text[100];
};

int main() {
    key_t key;
    int msgid;
    struct msg_buffer message;

    // Generate same key
    key = ftok("progfile", 65);

    // Access message queue
    msgid = msgget(key, 0666 | IPC_CREAT);

    // Receive message
    msgrcv(msgid, &message, sizeof(message.msg_text), 1, 0);

    printf("Message received: %s\n", message.msg_text);

    // Destroy the message queue
    msgctl(msgid, IPC_RMID, NULL);

    return 0;
}
7️⃣ How to Run 
gcc sender.c -o sender
gcc receiver.c -o receiver
./sender
./receiver
8️⃣ Sample Output
Sender:

Message sent: Hello from sender process
Receiver:

Message received: Hello from sender process
9️⃣ Important Points 
Message queues allow structured communication

Messages have types

Kernel stores messages until received

Processes need same key

🟦 Explanation of Functions Used in Message Queue Program
We will explain the functions used in sender and receiver programs:

1️⃣ ftok() — Generate Unique Key
Prototype
key_t ftok(const char *pathname, int proj_id);
Purpose
Generates a unique IPC key

Same key must be used by both sender and receiver

Arguments
Argument	Meaning
pathname	            Existing file path
proj_id	            Project identifier (integer/character)
Example
key = ftok("progfile", 65);
Important Notes
File must exist

Used to ensure both processes refer to the same message queue

📌 Exam Tip:

ftok() converts a filename and project ID into a unique key.

2️⃣ msgget() — Create or Access Message Queue
Prototype
int msgget(key_t key, int msgflg);
Purpose
Creates a new message queue or

Accesses an existing message queue

Arguments
Argument	Meaning
key	        Key generated by ftok()
msgflg	        Permission + creation flags
Example
msgid = msgget(key, 0666 | IPC_CREAT);
Flags Explained
0666 → Read/write permission

IPC_CREAT → Create queue if it does not exist

📌 Return Value

Returns message queue ID

-1 on failure

3️⃣ msgsnd() — Send Message to Queue
Prototype
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
Purpose
Sends a message to the queue

Arguments
Argument	Meaning
msqid	            Message queue ID
msgp	            Pointer to message structure
msgsz	            Size of message text (excluding long)
msgflg	            Control flags
Example
msgsnd(msgid, &message, sizeof(message.msg_text), 0);
Important Notes
msg_type must be first field

msgsz excludes long msg_type

📌 Common Mistake

sizeof(struct msg_buffer)   ❌
4️⃣ msgrcv() — Receive Message from Queue
Prototype
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz,
               long msgtyp, int msgflg);
Purpose
Receives a message from the queue

Arguments
Argument	Meaning
msqid	        Message queue ID
msgp	        Pointer to buffer
msgsz	        Size of message text
msgtyp	        Type of message to receive
msgflg	        Control flags
Example
msgrcv(msgid, &message, sizeof(message.msg_text), 1, 0);
Message Type Rules
msgtyp	Meaning
>0	        Receive specific type
0	        Receive first message
<0	        Receive lowest type ≤ abs
📌 Blocking Behavior

Blocks until message arrives (unless IPC_NOWAIT used)

5️⃣ msgctl() — Control Message Queue
Prototype
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
Purpose
Control or delete the message queue

Arguments
Argument	Meaning
msqid	    Message queue ID
cmd	    Control command
buf	    Optional structure
Example
msgctl(msgid, IPC_RMID, NULL);
Common Commands
Command	Description
IPC_RMID	Remove message queue
IPC_STAT	Get status
IPC_SET	Set permissions
📌 Exam Tip

Always remove the message queue to avoid resource leakage.

6️⃣ struct msg_buffer — Message Structure
Definition
struct msg_buffer {
    long msg_type;
    char msg_text[100];
};
Rules
msg_type must be long

First field is mandatory

Used to identify message category

7️⃣ Supporting Library Headers
Header	Purpose
<sys/ipc.h>	        IPC key definitions
<sys/msg.h>	        Message queue functions
<string.h>	        String operations
<stdio.h>	        Input/output

