Fundamentals 13 min read

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.

Open Source Linux
Open Source Linux
Open Source Linux
How Does Linux Shared Memory Work? A Deep Dive into shmget, shmat, and shmdt

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. shmflgSHM_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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

linuxSystem Programmingshared memoryIPCshmatshmgetshmdt
Open Source Linux
Written by

Open Source Linux

Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.