How Does Linux Shared Memory Work? A Deep Dive into shmget, shmat, and shmdt
This article explains Linux's shared‑memory mechanism, covering the concepts of virtual versus physical memory, the three core system calls (shmget, shmat, shmdt), example programs for two processes, and a detailed look at the kernel structures and functions that implement shared memory.
Shared Memory Overview
In Linux each process has its own virtual address space, so the same virtual address in different processes refers to different physical memory. To enable inter‑process communication, Linux provides shared memory, which maps the same physical pages into the virtual spaces of multiple processes.
Using Shared Memory
1. Obtaining a shared memory segment
The shmget() system call creates or retrieves a segment. Its prototype is:
int shmget(key_t key, size_t size, int shmflg); key– usually generated by ftok() to uniquely identify the IPC resource. size – size of the segment to allocate. shmflg – flags such as IPC_CREAT, IPC_EXCL, and permission bits.
On success shmget() returns a non‑negative identifier; on failure it returns –1 and sets errno.
2. Attaching the segment
After obtaining the identifier, shmat() attaches the segment to the caller’s address space:
void *shmat(int shmid, const void *shmaddr, int shmflg); shmid– identifier returned by shmget(). shmaddr – desired virtual address; if 0 the kernel chooses one. shmflg – SHM_RDONLY for read‑only mapping, otherwise read‑write.
On success it returns a pointer to the attached memory; on error it returns (void *)‑1.
3. Detaching the segment
When a process no longer needs the segment, it calls shmdt(): int shmdt(const void *shmaddr); The function returns 0 on success and –1 on failure.
Example Programs
Process A creates a segment, attaches it, writes “Hello World”, and exits. Process B obtains the same segment, attaches it, reads the string, and prints it.
Process A
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_PATH "/tmp/shm"
#define SHM_SIZE 128
int main(int argc, char *argv[]) {
int shmid;
char *addr;
key_t key = ftok(SHM_PATH, 0x6666);
shmid = shmget(key, SHM_SIZE, IPC_CREAT|IPC_EXCL|0666);
if (shmid < 0) {
printf("failed to create share memory
");
return -1;
}
addr = shmat(shmid, NULL, 0);
if (addr <= 0) {
printf("failed to map share memory
");
return -1;
}
sprintf(addr, "%s", "Hello World
");
return 0;
}Process B
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_PATH "/tmp/shm"
#define SHM_SIZE 128
int main(int argc, char *argv[]) {
int shmid;
char *addr;
key_t key = ftok(SHM_PATH, 0x6666);
char buf[128];
shmid = shmget(key, SHM_SIZE, IPC_CREAT);
if (shmid < 0) {
printf("failed to get share memory
");
return -1;
}
addr = shmat(shmid, NULL, 0);
if (addr <= 0) {
printf("failed to map share memory
");
return -1;
}
strcpy(buf, addr, 128);
printf("%s", buf);
return 0;
}Running A first and then B prints “Hello World”, confirming successful shared‑memory communication.
Kernel Implementation Overview
The kernel represents each segment with struct shmid_kernel, stored in the global shm_segs array (maximum 128 entries). The key fields include shm_npages (number of pages) and shm_pages (array of page pointers).
struct shmid_ds {
struct ipc_perm shm_perm;
int shm_segsz;
__kernel_time_t shm_atime;
__kernel_time_t shm_dtime;
__kernel_time_t shm_ctime;
__kernel_ipc_pid_t shm_cpid;
__kernel_ipc_pid_t shm_lpid;
unsigned short shm_nattch;
/* ... */
};
struct shmid_kernel {
struct shmid_ds u;
unsigned long shm_npages;
pte_t *shm_pages;
struct vm_area_struct *attaches;
};
static struct shmid_kernel *shm_segs[SHMMNI];The shmget() implementation checks arguments, searches the shm_segs array with findkey(), creates a new segment with newseg() if needed, and returns the identifier.
The shmat() routine locates the segment, allocates a suitable virtual address (using get_unmapped_area() when none is supplied), creates a vm_area_struct to describe the mapping, increments the attach count, and finally calls shm_map() to install the mapping.
The shm_vm_ops structure defines callbacks for the mapping; the most important is shm_nopage(), which is invoked on a page fault. shm_nopage() allocates a physical page with get_free_highpage(), clears it, updates the segment’s page table, and returns the page to the faulting process.
Key Takeaways
Shared memory provides fast, zero‑copy IPC by sharing physical pages.
System calls shmget, shmat, and shmdt form the user‑level API.
The kernel tracks segments in struct shmid_kernel and handles mapping via vm_area_struct and page‑fault callbacks.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Linux
Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
