Key Methods
File to Key
Always unique
Why Do We Need Keys?
When two unrelated processes want to share an IPC object (like a message queue), they need a way to agree on which object to use. They cannot pass an identifier directly (there’s no common channel yet). So they agree on a key beforehand — like agreeing on a door number before meeting at a building.
A key is an integer of type key_t. Both processes call the same get() function with the same key, and the kernel returns the same identifier to both.
IPC_PRIVATE as keyftok() functionWhen you specify IPC_PRIVATE as the key to a get call, the kernel always creates a brand new IPC object with a unique identifier. You don’t need IPC_CREAT or IPC_EXCL — they are implied.
The main use case for IPC_PRIVATE is in parent-child process communication: the parent creates the IPC object before calling fork(), and the child inherits the identifier (since it’s just an integer in the process’s data).
Classic use: parent creates the IPC object before fork(), child inherits the ID.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
/* Simple message structure */
struct mymsg {
long mtype; /* must be > 0 */
char mtext[100];
};
int main(void) {
int msqid;
struct mymsg msg;
pid_t pid;
/* IPC_PRIVATE always creates a new unique queue */
msqid = msgget(IPC_PRIVATE, S_IRUSR | S_IWUSR);
if (msqid == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
printf("[Parent] Created queue with ID = %d\n", msqid);
pid = fork();
if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); }
if (pid == 0) {
/* CHILD: sends a message */
msg.mtype = 1;
snprintf(msg.mtext, sizeof(msg.mtext), "Hello from child PID=%d", getpid());
if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) == -1) {
perror("msgsnd");
exit(EXIT_FAILURE);
}
printf("[Child] Sent: %s\n", msg.mtext);
exit(EXIT_SUCCESS);
} else {
/* PARENT: waits for child, then receives message */
wait(NULL);
if (msgrcv(msqid, &msg, sizeof(msg.mtext), 0, 0) == -1) {
perror("msgrcv");
exit(EXIT_FAILURE);
}
printf("[Parent] Received: %s\n", msg.mtext);
/* Clean up */
if (msgctl(msqid, IPC_RMID, NULL) == -1) {
perror("msgctl IPC_RMID");
}
printf("[Parent] Queue deleted.\n");
}
return 0;
}
gcc -o ipc_private ipc_private.c && ./ipc_privateThe queue identifier is automatically shared between parent and child through the fork() — no key coordination needed.
ftok() generates a key by combining information from an existing file with a project number you provide. The function signature is:
#include <sys/ipc.h>
key_t ftok(char *pathname, int proj);
/* Returns an integer key on success, or -1 on error */
How does it generate the key? On Linux, ftok() combines three pieces of information:
stat() on the pathname internally.- Only the least significant 8 bits of
projare used. Avoid using 0 as proj — it is not portable. - The pathname must exist and be accessible by
stat()— otherwise ftok() returns -1. - ftok() uses the i-node number, not the filename. So two different names pointing to the same file (hard links) give the same key.
- Do NOT delete and re-create the file during the application’s life — the new file will have a different i-node and produce a different key.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#define KEY_FILE "/tmp/myapp_ipc_keyfile" /* agreed-upon file */
#define PROJ_ID 'A' /* agreed-upon project char */
int main(void) {
key_t key;
int msqid;
/* Step 1: Generate the key from the file + project ID */
key = ftok(KEY_FILE, PROJ_ID);
if (key == -1) {
perror("ftok");
fprintf(stderr, "Make sure %s exists!\n", KEY_FILE);
exit(EXIT_FAILURE);
}
printf("Generated key = 0x%x (%d)\n", (unsigned int)key, key);
/* Step 2: Use the key to create or open the message queue */
msqid = msgget(key, IPC_CREAT | 0660);
if (msqid == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
printf("Message queue ID = %d\n", msqid);
/* Any other process that calls ftok(KEY_FILE, 'A')
will get the same key, and thus the same msqid */
/* Cleanup */
msgctl(msqid, IPC_RMID, NULL);
printf("Queue removed.\n");
return 0;
}
touch /tmp/myapp_ipc_keyfileBoth server and client call
ftok("/tmp/myapp_ipc_keyfile", 'A') — they get the same key and the same message queue ID.An application might need several IPC objects of the same type (e.g., three semaphore sets). Use different proj values with the same file to generate distinct keys:
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#define KEY_FILE "/tmp/myapp_keyfile"
int main(void) {
key_t key1, key2, key3;
int semid1, semid2, semid3;
/* Three different proj values → three different keys */
key1 = ftok(KEY_FILE, 'A');
key2 = ftok(KEY_FILE, 'B');
key3 = ftok(KEY_FILE, 'C');
if (key1 == -1 || key2 == -1 || key3 == -1) {
perror("ftok");
exit(EXIT_FAILURE);
}
printf("key1 = 0x%x\n", (unsigned int)key1);
printf("key2 = 0x%x\n", (unsigned int)key2);
printf("key3 = 0x%x\n", (unsigned int)key3);
/* Create three separate semaphore sets */
semid1 = semget(key1, 1, IPC_CREAT | 0600);
semid2 = semget(key2, 1, IPC_CREAT | 0600);
semid3 = semget(key3, 1, IPC_CREAT | 0600);
if (semid1 == -1 || semid2 == -1 || semid3 == -1) {
perror("semget");
exit(EXIT_FAILURE);
}
printf("Semaphore IDs: %d, %d, %d\n", semid1, semid2, semid3);
/* Cleanup */
semctl(semid1, 0, IPC_RMID);
semctl(semid2, 0, IPC_RMID);
semctl(semid3, 0, IPC_RMID);
printf("All semaphores removed.\n");
return 0;
}
proj argument (choose values 1–255, not 0) lets you derive multiple distinct keys from a single agreed-upon file.ftok() is widely used but has a small limitation: there is a very small chance of key collisions. Two different files on different filesystems could yield the same key if:
- The least significant bits of their i-node numbers happen to match, AND
- The minor device numbers of their respective filesystems happen to match
In practice, this possibility is small enough that ftok() is a viable technique for most applications. The glibc implementation of ftok() has the same limitation as other UNIX implementations.
- Parent and child processes communicate
- You fork() before creating the IPC object
- You can pass the ID through inheritance or a file
- Completely unrelated processes need to share an IPC object
- Both processes know a common pathname and proj value
- You want a stable key that survives restarts
🎯 Interview Questions — IPC Keys, IPC_PRIVATE, ftok()
key_t, which is an integer type defined in <sys/ipc.h>. On Linux it is a 32-bit value.ftok(char *pathname, int proj). pathname is the path to an existing file whose i-node number is used. proj is a project number (only least significant 8 bits used) that allows generating multiple different keys from the same file. Returns a key_t.← Previous: Intro & API Overview Next: Data Structures & Permissions →
