---
title: Shared Memory and Semaphores
url: https://doc.liz6.com/en/systems-programming/06-ipc-and-synchronization/03-shared-memory-and-semaphores
locale: en
area: systems-programming
tags:
- systems-programming
- ipc-and-synchronization
date: 2026-06-30
modified: 2026-07-16
description: 'Coverage: shmget/shmat (SysV) → mmap(MAP_SHARED) → POSIX semaphore → file locking → memfd_create → Comparison and Selection. Applicable to: Linux user space'
---

# Shared Memory and Semaphores

> Coverage: shmget/shmat (SysV) → mmap(MAP_SHARED) → POSIX semaphore → file locking → memfd_create → Comparison and Selection
> Applicable to: Linux user space

## Overview

Pipes and sockets transfer data via copying, whereas shared memory allows multiple processes to access the same physical memory—zero-copy. This is the highest-performance IPC method, but it requires additional synchronization mechanisms (semaphores, file locks, or lockless data structures).

## mmap(MAP_SHARED): POSIX Shared Memory

```c
// Style 1: Anonymous shared memory (shared after fork)
void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE,
                  MAP_SHARED|MAP_ANONYMOUS, -1, 0);
// After fork: parent and child processes see the same physical page (not COW!)

// Style 2: File-backed shared memory
int fd = open("/dev/shm/myregion", O_CREAT|O_RDWR, 0600);
ftruncate(fd, size);
void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
// Unrelated processes: open the same file → mmap → share

// All processes see the same physical page → changes are visible to each other → synchronization required!
```

## memfd_create: Anonymous File Descriptor

```c
int fd = memfd_create("myregion", MFD_CLOEXEC);
ftruncate(fd, size);
void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

// Advantages:
//   - No filesystem mount required → no need for /dev/shm
//   - Can be sealed (prevent modification): fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW)
//   - Can be passed to another process: sendmsg(SCM_RIGHTS) → fd passing

// systemd uses memfd for all internal IPC
```

## SysV Shared Memory (Legacy, Not Recommended)

```c
int shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600);
void *addr = shmat(shmid, NULL, 0);
// ... read/write ...
shmdt(addr);
shmctl(shmid, IPC_RMID, NULL);

// Why it is obsolete: global key conflicts, risk of resource leaks, lack of flexibility
```

## POSIX Semaphores

```c
#include <semaphore.h>

// Anonymous semaphore (for threads or shared memory):
sem_t sem;
sem_init(&sem, 1, 1);   // pshared=1 → in shared memory
sem_wait(&sem);          // P (decrement by 1, block)
sem_post(&sem);          // V (increment by 1, possibly wake waiters)
sem_destroy(&sem);

// Named semaphore (for unrelated processes):
sem_t *sem = sem_open("/mysem", O_CREAT, 0600, 1);
sem_wait(sem);
sem_post(sem);
sem_close(sem);
sem_unlink("/mysem");
```

### Inside sem_wait: futex

```c
// glibc sem_wait implementation (simplified):
sem_wait(sem_t *sem) {
    while (1) {
        if (atomic_fetch_sub(sem->count, 1) > 0)
            return;  // Success! Zero system calls

        // count becomes negative → need to wait
        atomic_fetch_add(sem->count, 1);  // undo
        futex_wait(&sem->count, val);
    }
}
// Same as pthread_mutex: zero syscalls when uncontended → the power of futex
```

## File Locking: Inter-process Mutual Exclusion

```c
// fcntl record lock: lock a region of a file
struct flock fl = {
    .l_type   = F_WRLCK,  // Exclusive lock
    .l_whence = SEEK_SET,
    .l_start  = 0,
    .l_len    = 0,        // 0 = to end of file
};
fcntl(fd, F_SETLKW, &fl);  // Block and wait

// Advantages: Kernel manages automatically → process crash → lock automatically released
// Suitable for: Daemon single-instance, database file protection
```

## Selection Guide

```
Scenario                              Recommended Solution
─────────────────────────────────────────────
Parent-child unidirectional data        pipe
Parent-child bidirectional data         socketpair
Unrelated processes sharing large data  mmap(MAP_SHARED) + POSIX sem
Daemon single-instance + inter-process lock  file lock (F_SETLK)
Thread synchronization (same process)   pthread_mutex (futex)
Counting semaphore between threads/     POSIX sem (futex)
reliable credential passing             AF_UNIX + SCM_CREDENTIALS
```

## References

- **man**: mmap(2), shm_overview(7), sem_overview(7), fcntl(2) (record locks), memfd_create(2)
- **Source code**: `ipc/sem.c` (SysV), `ipc/shm.c`, `mm/mmap.c`
- **LWN**: "memfd_create and sealing"

*Keywords: mmap MAP_SHARED, memfd_create, POSIX semaphore, sem_wait, futex, file lock, F_SETLK, shared memory*
