- Message Queue: Independent Sender and Receiver This example demonstrates a basic message queue system where two separate processes — one acting as sender and the other as receiver — communicate via System V message queues.
Sender Implementation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_TEXT_LEN 200
typedef struct {
long type;
char body[MAX_TEXT_LEN];
} Message;
#define MESSAGE_SIZE (sizeof(Message) - sizeof(long))
int main() {
const key_t queue_key = ftok("./", 'Q');
if (queue_key == -1) {
perror("ftok failed");
exit(EXIT_FAILURE);
}
const int qid = msgget(queue_key, IPC_CREAT | 0666);
if (qid == -1) {
perror("msgget failed");
exit(EXIT_FAILURE);
}
Message msg = {0};
while (1) {
printf("Enter message type: ");
if (scanf("%ld", &msg.type) != 1) break;
while (getchar() != '\n'); // flush input buffer
printf("Enter message content: ");
if (fgets(msg.body, MESSAGE_SIZE, stdin) == NULL) break;
if (msgsnd(qid, &msg, MESSAGE_SIZE, 0) == -1) {
perror("msgsnd failed");
break;
}
if (strncmp(msg.body, "quit", 4) == 0) break;
}
if (msgctl(qid, IPC_RMID, NULL) == -1) {
perror("msgctl IPC_RMID failed");
exit(EXIT_FAILURE);
}
return 0;
}
Receiver Implementation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_TEXT_LEN 200
typedef struct {
long type;
char body[MAX_TEXT_LEN];
} Message;
#define MESSAGE_SIZE (sizeof(Message) - sizeof(long))
int main() {
const key_t queue_key = ftok("./", 'Q');
if (queue_key == -1) {
perror("ftok failed");
exit(EXIT_FAILURE);
}
const int qid = msgget(queue_key, IPC_CREAT | 0666);
if (qid == -1) {
perror("msgget failed");
exit(EXIT_FAILURE);
}
Message msg = {0};
while (1) {
ssize_t read_size = msgrcv(qid, &msg, MESSAGE_SIZE, 0, 0);
if (read_size == -1) {
perror("msgrcv failed");
break;
}
printf("%s", msg.body);
if (strncmp(msg.body, "quit", 4) == 0) break;
}
return 0;
}
- Shared Memory: Producer and Consumer This section shows how two independent processes may share a region of memory for data exchange using System V shared memory segments.
Producer (Writing Process)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define BUF_SIZE 4096
int main() {
const key_t shm_key = ftok("./", 'M');
if (shm_key == -1) {
perror("ftok failed");
exit(EXIT_FAILURE);
}
const int segment_id = shmget(shm_key, BUF_SIZE, IPC_CREAT | 0666);
if (segment_id == -1) {
perror("shmget failed");
exit(EXIT_FAILURE);
}
char *addr = shmat(segment_id, NULL, 0);
if (addr == (void *)-1) {
perror("shmat failed");
exit(EXIT_FAILURE);
}
char buffer[BUF_SIZE];
while (1) {
printf("Enter data for shared memory: ");
if (fgets(buffer, sizeof(buffer), stdin) == NULL) break;
strncpy(addr, buffer, BUF_SIZE - 1);
addr[BUF_SIZE - 1] = '\0';
if (strncmp(addr, "quit", 4) == 0) break;
}
if (shmdt(addr) == -1) {
perror("shmdt failed");
exit(EXIT_FAILURE);
}
if (shmctl(segment_id, IPC_RMID, NULL) == -1) {
perror("shmctl IPC_RMID failed");
exit(EXIT_FAILURE);
}
return 0;
}
Consumer (Reading Process)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define BUF_SIZE 4096
int main() {
const key_t shm_key = ftok("./", 'M');
if (shm_key == -1) {
perror("ftok failed");
exit(EXIT_FAILURE);
}
const int segment_id = shmget(shm_key, BUF_SIZE, IPC_CREAT | 0666);
if (segment_id == -1) {
perror("shmget failed");
exit(EXIT_FAILURE);
}
char *addr = shmat(segment_id, NULL, 0);
if (addr == (void *)-1) {
perror("shmat failed");
exit(EXIT_FAILURE);
}
while (1) {
printf("Received: %s", addr);
if (strncmp(addr, "quit", 4) == 0) break;
sleep(1); // simulate polling delay
}
if (shmdt(addr) == -1) {
perror("shmdt failed");
exit(EXIT_FAILURE);
}
return 0;
}
- Inter-Process Communication Using Forked Pairs with Separate Queues Here, two programs each spawn a parent and child process. Parent and child use different message queues to enable bidirectional communication:
Program A:
Parent sends to Queue 'Q', child reads from Queue 'R'
Program B:
Parent sends to Queue 'R', child reads from Queue 'Q'
Program A
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#define MSG_SIZE 200
typedef struct {
long type;
char body[MSG_SIZE];
} Message;
#define BODY_SIZE (sizeof(Message) - sizeof(long))
int main() {
const key_t send_key = ftok("./", 'Q');
const key_t recv_key = ftok("./", 'R');
if (send_key == -1 || recv_key == -1) {
perror("ftok failed");
exit(EXIT_FAILURE);
}
const int send_qid = msgget(send_key, IPC_CREAT | 0666);
const int recv_qid = msgget(recv_key, IPC_CREAT | 0666);
if (send_qid == -1 || recv_qid == -1) {
perror("msgget failed");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid > 0) { // Parent: send via send_qid
Message msg = {0};
while (1) {
printf("Parent: Enter type & message: ");
if (scanf("%ld", &msg.type) != 1) break;
while (getchar() != '\n');
if (fgets(msg.body, BODY_SIZE, stdin) == NULL) break;
if (msgsnd(send_qid, &msg, BODY_SIZE, 0) == -1) {
perror("msgsnd failed");
break;
}
if (strncmp(msg.body, "quit", 4) == 0) break;
}
wait(NULL);
}
else if (pid == 0) { // Child: receive on recv_qid
Message msg = {0};
while (1) {
if (msgrcv(recv_qid, &msg, BODY_SIZE, 0, 0) == -1) {
perror("msgrcv failed");
break;
}
printf("Child received: %s", msg.body);
if (strncmp(msg.body, "quit", 4) == 0) break;
}
}
return 0;
}
Program B
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#define MSG_SIZE 200
typedef struct {
long type;
char body[MSG_SIZE];
} Message;
#define BODY_SIZE (sizeof(Message) - sizeof(long))
int main() {
const key_t send_key = ftok("./", 'R');
const key_t recv_key = ftok("./", 'Q');
if (send_key == -1 || recv_key == -1) {
perror("ftok failed");
exit(EXIT_FAILURE);
}
const int send_qid = msgget(send_key, IPC_CREAT | 0666);
const int recv_qid = msgget(recv_key, IPC_CREAT | 0666);
if (send_qid == -1 || recv_qid == -1) {
perror("msgget failed");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid > 0) { // Parent: send via send_qid (R)
Message msg = {0};
while (1) {
printf("Parent: Enter type & message: ");
if (scanf("%ld", &msg.type) != 1) break;
while (getchar() != '\n');
if (fgets(msg.body, BODY_SIZE, stdin) == NULL) break;
if (msgsnd(send_qid, &msg, BODY_SIZE, 0) == -1) {
perror("msgsnd failed");
break;
}
if (strncmp(msg.body, "quit", 4) == 0) break;
}
wait(NULL);
}
else if (pid == 0) { // Child: receive on recv_qid (Q)
Message msg = {0};
while (1) {
if (msgrcv(recv_qid, &msg, BODY_SIZE, 0, 0) == -1) {
perror("msgrcv failed");
break;
}
printf("Child received: %s", msg.body);
if (strncmp(msg.body, "quit", 4) == 0) break;
}
}
return 0;
}