Chapter 46 · File 2 of 6
Creating & Opening a Message Queue
msgget() · IPC Keys · Flags · Permissions
Before you can send or receive any messages, you need a queue. The msgget() system call either creates a new queue or opens an existing one. This file covers everything about msgget — from the basic API signature to key generation strategies.
Section 46.1 — The msgget() System Call
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
/* Returns: queue identifier (msqid) on success, -1 on error */
It takes two arguments:
- key — a unique identifier for the queue. Two processes that pass the same key will get the same queue.
- msgflg — a bitmask combining permission bits AND control flags (like IPC_CREAT).
On success, it returns the msqid — an integer that uniquely identifies the queue. Use this in every subsequent call.
Understanding IPC Keys
The key_t key argument is how processes agree on which queue to use. There are three common ways to get a key:
| Method | How | Best for |
|---|---|---|
| IPC_PRIVATE | Use the constant IPC_PRIVATE as key (value = 0) | Parent-child communication; the created queue ID is passed via fork or env var |
| ftok() | Derive key from a filename + project ID | Unrelated processes that both know the same file path |
| Hard-coded key | Pick a number manually (e.g., 1234) | Simple tests; not recommended for production |
The ftok() Function
ftok() generates a key from a file path + a 1-byte project ID. Two processes calling ftok() with the same arguments get the same key — that’s how they find each other’s queue.
key_t ftok(const char *pathname, int proj_id);
/* Returns a key_t. The file must exist. proj_id uses only low 8 bits. */
/etc/passwd or your application’s binary).The msgflg Argument
msgflg is a bitwise OR of permission bits and control flags:
| Flag | Value | Meaning |
|---|---|---|
IPC_CREAT |
01000 | Create queue if it doesn’t exist |
IPC_EXCL |
02000 | Fail with EEXIST if queue already exists (used with IPC_CREAT) |
0666 |
octal | rwx permission bits — same as file permissions |
0600 |
octal | Only owner can read/write |
• Otherwise → return existing queue ID
• If IPC_CREAT not set → ENOENT error
Code Example 1 — Create with IPC_PRIVATE
The simplest case: create a private queue and use it in the same process (or pass the ID to a child via fork).
/* create_private.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <unistd.h>
struct Msg { long mtype; char mtext[64]; };
int main(void)
{
/* IPC_PRIVATE always creates a NEW queue — guaranteed unique */
int msqid = msgget(IPC_PRIVATE, IPC_CREAT | 0666);
if (msqid == -1) { perror("msgget"); exit(1); }
printf("[Parent] Created queue ID = %d\n", msqid);
pid_t pid = fork();
if (pid == -1) { perror("fork"); exit(1); }
if (pid == 0) {
/* Child: send a message */
struct Msg m = { .mtype = 1 };
snprintf(m.mtext, sizeof(m.mtext), "Hello from child PID %d", getpid());
if (msgsnd(msqid, &m, sizeof(m.mtext), 0) == -1)
perror("msgsnd");
else
printf("[Child] Sent: '%s'\n", m.mtext);
exit(0);
} else {
/* Parent: wait for child, then receive */
wait(NULL);
struct Msg rcv;
if (msgrcv(msqid, &rcv, sizeof(rcv.mtext), 0, 0) == -1)
perror("msgrcv");
else
printf("[Parent] Got: '%s'\n", rcv.mtext);
/* Clean up */
msgctl(msqid, IPC_RMID, NULL);
printf("[Parent] Queue removed.\n");
}
return 0;
}
Code Example 2 — Using ftok() for Unrelated Processes
This pattern is used when two completely separate programs (not parent-child) need to share a queue. Both agree on the same file and project ID.
/* queue_server_setup.c — Server creates the queue */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define PROJ_ID 'A' /* Single char used as project identifier */
#define KEY_FILE "/tmp/myapp" /* Must exist; both server and client use this */
int main(void)
{
/* Step 1: Make sure the key file exists */
FILE *f = fopen(KEY_FILE, "w");
if (!f) { perror("fopen"); exit(1); }
fclose(f);
/* Step 2: Generate key from file + project ID */
key_t key = ftok(KEY_FILE, PROJ_ID);
if (key == -1) { perror("ftok"); exit(1); }
printf("Generated key = 0x%x\n", (unsigned int)key);
/* Step 3: Create the queue — IPC_EXCL ensures we don't reuse a stale one */
int msqid = msgget(key, IPC_CREAT | IPC_EXCL | 0660);
if (msqid == -1) {
if (errno == EEXIST) {
/* Queue already exists — open it */
msqid = msgget(key, 0660);
printf("Opened existing queue ID = %d\n", msqid);
} else {
perror("msgget");
exit(1);
}
} else {
printf("Created new queue ID = %d\n", msqid);
}
/* Now use msqid for sending/receiving... */
return 0;
}
/* queue_client_setup.c — Client opens the SAME queue */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#define PROJ_ID 'A'
#define KEY_FILE "/tmp/myapp"
int main(void)
{
/* Same key generation as server */
key_t key = ftok(KEY_FILE, PROJ_ID);
if (key == -1) { perror("ftok"); exit(1); }
/* Open existing queue — NO IPC_CREAT, so fails if not created yet */
int msqid = msgget(key, 0660);
if (msqid == -1) {
if (errno == ENOENT)
fprintf(stderr, "Queue not found! Start server first.\n");
else
perror("msgget");
exit(1);
}
printf("Client opened queue ID = %d\n", msqid);
/* Now use msqid ... */
return 0;
}
Code Example 3 — Checking If a Queue Exists
/* check_queue.c — Check if a queue exists without creating it */
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int queue_exists(key_t key)
{
/* msgget with no IPC_CREAT: succeeds if queue exists, fails with ENOENT if not */
int id = msgget(key, 0);
if (id == -1) {
if (errno == ENOENT)
return 0; /* Does not exist */
perror("msgget");
return -1; /* Some other error */
}
return 1; /* Exists */
}
int main(void)
{
key_t key = ftok("/tmp/myapp", 'A');
int result = queue_exists(key);
if (result == 1)
printf("Queue exists!\n");
else if (result == 0)
printf("Queue does not exist.\n");
else
printf("Error checking queue.\n");
return 0;
}
Viewing Active Queues — ipcs & ipcrm
The ipcs command lists all active System V IPC objects (queues, semaphores, shared memory). Use it to check for leftover queues.
$ ipcs -q # Show all message queues
------ Message Queues --------
key msqid owner perms used-bytes messages
0x00000000 65536 ravi 666 64 1
0x41020a52 65537 ravi 660 0 0
$ ipcrm -q 65536 # Remove queue with ID 65536
$ ipcrm -Q 0x41020a52 # Remove queue with this key
msgctl(IPC_RMID), the queue remains. Running ipcs -q after testing is good practice. On a server, leaked queues accumulate until the kernel limit is hit.Interview Questions — msgget() & IPC Keys
ipcs -q command. To remove a queue from the shell: ipcrm -q msqid or ipcrm -Q key.