← Back to all projects

UNIX IPC STEVENS VOL2 MASTERY

Interprocess Communication is the backbone of every modern Unix system. When you run `ls | grep foo`, you're using pipes. When PostgreSQL coordinates between its processes, it uses shared memory and semaphores. When your web server handles thousands of connections, it uses message queues and synchronization primitives.

Sprint: Unix IPC Mastery - Stevens Vol 2 Complete

Goal: Master every Interprocess Communication mechanism in Unix by working through W. Richard Stevensโ€™ โ€œUnix Network Programming Volume 2: Interprocess Communications.โ€ Youโ€™ll deeply understand how processes share data and synchronizeโ€”from simple pipes to complex shared memory regions, from local semaphores to remote procedure calls. By the end, youโ€™ll know exactly when to use each IPC mechanism, understand the trade-offs between POSIX and System V APIs, and have built real systems that coordinate multiple processes.


Why Unix IPC Matters

Interprocess Communication is the backbone of every modern Unix system. When you run ls | grep foo, youโ€™re using pipes. When PostgreSQL coordinates between its processes, it uses shared memory and semaphores. When your web server handles thousands of connections, it uses message queues and synchronization primitives.

Historical Context

W. Richard Stevens wrote the definitive treatment of Unix IPC in 1999, covering mechanisms that date back to:

  • 1970s: Pipes (original Unix)
  • 1983: System V IPC (shared memory, semaphores, message queues)
  • 1988: POSIX standardization efforts began
  • 1993: POSIX.1b real-time extensions (including IPC)

Real-World Impact

According to research on IPC performance analysis:

  • Unix domain sockets perform 2x faster than TCP/IP for local communication
  • Shared memory remains the fastest mechanism for bulk data transfer
  • Named pipes (FIFOs) are still widely used for reliability and simplicity
  • Message queues provide natural request/response patterns

Modern systems like ByteDanceโ€™s Shmipc achieve 4x throughput improvements using shared memory IPC.

The IPC Landscape

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                        UNIX IPC MECHANISMS                               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                     โ”‚
โ”‚  โ”‚   DATA TRANSFER     โ”‚    โ”‚   SYNCHRONIZATION   โ”‚                     โ”‚
โ”‚  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                     โ”‚
โ”‚  โ”‚                     โ”‚    โ”‚                     โ”‚                     โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚    โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚                     โ”‚
โ”‚  โ”‚  โ”‚    Pipes      โ”‚  โ”‚    โ”‚  โ”‚   Mutexes &   โ”‚  โ”‚                     โ”‚
โ”‚  โ”‚  โ”‚   (unnamed)   โ”‚  โ”‚    โ”‚  โ”‚  Cond Vars    โ”‚  โ”‚                     โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚    โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚                     โ”‚
โ”‚  โ”‚         โ”‚           โ”‚    โ”‚         โ”‚           โ”‚                     โ”‚
โ”‚  โ”‚         โ–ผ           โ”‚    โ”‚         โ–ผ           โ”‚                     โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚    โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚                     โ”‚
โ”‚  โ”‚  โ”‚    FIFOs      โ”‚  โ”‚    โ”‚  โ”‚  Read-Write   โ”‚  โ”‚                     โ”‚
โ”‚  โ”‚  โ”‚ (named pipes) โ”‚  โ”‚    โ”‚  โ”‚    Locks      โ”‚  โ”‚                     โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚    โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚                     โ”‚
โ”‚  โ”‚         โ”‚           โ”‚    โ”‚         โ”‚           โ”‚                     โ”‚
โ”‚  โ”‚         โ–ผ           โ”‚    โ”‚         โ–ผ           โ”‚                     โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚    โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚                     โ”‚
โ”‚  โ”‚  โ”‚   Message     โ”‚โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”‚  Semaphores   โ”‚  โ”‚                     โ”‚
โ”‚  โ”‚  โ”‚    Queues     โ”‚  โ”‚    โ”‚  โ”‚ (POSIX/SysV)  โ”‚  โ”‚                     โ”‚
โ”‚  โ”‚  โ”‚ (POSIX/SysV)  โ”‚  โ”‚    โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚                     โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚    โ”‚         โ”‚           โ”‚                     โ”‚
โ”‚  โ”‚         โ”‚           โ”‚    โ”‚         โ–ผ           โ”‚                     โ”‚
โ”‚  โ”‚         โ–ผ           โ”‚    โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚                     โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚    โ”‚  โ”‚    Record     โ”‚  โ”‚                     โ”‚
โ”‚  โ”‚  โ”‚Shared Memory  โ”‚โ—„โ”€โ”ผโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”‚   Locking     โ”‚  โ”‚                     โ”‚
โ”‚  โ”‚  โ”‚ (POSIX/SysV)  โ”‚  โ”‚    โ”‚  โ”‚   (fcntl)     โ”‚  โ”‚                     โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚    โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚                     โ”‚
โ”‚  โ”‚         โ”‚           โ”‚    โ”‚                     โ”‚                     โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                     โ”‚
โ”‚            โ”‚                                                             โ”‚
โ”‚            โ–ผ                                                             โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                โ”‚
โ”‚  โ”‚   REMOTE PROCEDURE  โ”‚                                                โ”‚
โ”‚  โ”‚       CALLS         โ”‚                                                โ”‚
โ”‚  โ”‚  (Sun RPC + XDR)    โ”‚                                                โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Unix IPC Architecture Overview

POSIX vs System V: The Two API Families

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    POSIX vs SYSTEM V IPC                                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   POSIX IPC (Modern)                 System V IPC (Legacy)              โ”‚
โ”‚   โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                 โ”‚
โ”‚                                                                          โ”‚
โ”‚   โœ“ Uses filesystem namespace        โœ“ Uses numeric keys (ftok)         โ”‚
โ”‚   โœ“ Reference counting               โœ“ Kernel-persistent                โ”‚
โ”‚   โœ“ Simpler API                      โœ“ More features (semaphore sets)   โ”‚
โ”‚   โœ“ Better portability               โœ“ Widely deployed                  โ”‚
โ”‚                                                                          โ”‚
โ”‚   Message Queues:                    Message Queues:                    โ”‚
โ”‚   mq_open(), mq_send()               msgget(), msgsnd()                 โ”‚
โ”‚   mq_receive(), mq_close()           msgrcv(), msgctl()                 โ”‚
โ”‚                                                                          โ”‚
โ”‚   Semaphores:                        Semaphores:                        โ”‚
โ”‚   sem_open(), sem_wait()             semget(), semop()                  โ”‚
โ”‚   sem_post(), sem_close()            semctl()                           โ”‚
โ”‚                                                                          โ”‚
โ”‚   Shared Memory:                     Shared Memory:                     โ”‚
โ”‚   shm_open(), mmap()                 shmget(), shmat()                  โ”‚
โ”‚   shm_unlink()                       shmdt(), shmctl()                  โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

POSIX vs System V Comparison


Prerequisites & Background Knowledge

Before starting these projects, you should have foundational understanding in these areas:

Essential Prerequisites (Must Have)

Programming Skills:

  • C programming (pointers, memory management, structs)
  • Understanding of process creation with fork()
  • Basic file I/O operations (open, read, write, close)
  • Familiarity with errno and error handling
  • Recommended Reading: โ€œThe C Programming Languageโ€ by Kernighan & Ritchie

Operating Systems Fundamentals:

  • Process vs Thread concepts
  • Virtual memory basics
  • File descriptors
  • System calls vs library functions
  • Recommended Reading: โ€œOperating Systems: Three Easy Piecesโ€ by Arpaci-Dusseau โ€” Ch. 5-6

Unix Environment:

  • Shell scripting basics
  • Reading man pages (man 2 pipe, man 7 sem_overview)
  • Using strace and lsof
  • Recommended Reading: โ€œAdvanced Programming in the UNIX Environmentโ€ by Stevens & Rago โ€” Ch. 1-3

Helpful But Not Required

Threading:

  • pthreads basics (pthread_create, pthread_join)
  • Can learn during: Projects 7-9

Networking:

  • TCP/IP basics
  • Can learn during: Project 18 (Sun RPC)

Self-Assessment Questions

Before starting, ask yourself:

  1. โœ… Can you explain what happens when you call fork()?
  2. โœ… Do you understand file descriptors and why 0, 1, 2 are special?
  3. โœ… Can you allocate memory with malloc() and avoid leaks?
  4. โœ… Have you used strace to trace system calls?
  5. โœ… Do you know the difference between a process and a thread?

If you answered โ€œnoโ€ to questions 1-3: Spend 2 weeks on Stevensโ€™ APUE Ch. 1-8 before starting. If you answered โ€œyesโ€ to all: Youโ€™re ready to begin!

Development Environment Setup

Required Tools:

  • GCC or Clang (C11 support)
  • Linux (Ubuntu 22.04+ or similar) โ€” macOS lacks some System V features
  • make for building projects
  • strace and ltrace for debugging

Recommended Tools:

  • Valgrind for memory leak detection
  • GDB for debugging
  • ipcs and ipcrm for inspecting System V IPC objects

Testing Your Setup:

# Verify POSIX IPC support
$ ls /dev/shm/
# Should list any existing shared memory objects

# Verify System V IPC support
$ ipcs
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

# Verify compiler
$ gcc --version
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0

# Check PIPE_BUF limit
$ getconf PIPE_BUF /
4096

Time Investment:

  • Foundation projects (1-4): Weekend each (4-8 hours)
  • Synchronization projects (5-10): 1 week each (10-20 hours)
  • Shared Memory projects (11-14): 1-2 weeks each (15-30 hours)
  • Advanced projects (15-18): 2+ weeks each (20-40 hours)
  • Total sprint: 4-6 months if doing all projects sequentially

Important Reality Check: IPC is notoriously tricky to debug. Deadlocks will happen. Processes will hang. Youโ€™ll leak semaphores and shared memory segments that persist after your program crashes. This is normal. The ipcs and ipcrm commands will become your best friends. Embrace the chaosโ€”itโ€™s how you learn.


Core Concept Analysis

1. Pipes: The Simplest IPC

Pipes are unidirectional byte streams between related processes. Created by pipe(), they return two file descriptors: one for reading, one for writing.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                           PIPE MECHANISM                                 โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   Parent Process                        Child Process                   โ”‚
โ”‚   โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                        โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                   โ”‚
โ”‚                                                                          โ”‚
โ”‚   Before fork():                                                         โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”‚
โ”‚   โ”‚  fd[0] โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ KERNEL PIPE BUFFER โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ fd[1] โ”‚           โ”‚
โ”‚   โ”‚  (read)            (4KB - 64KB)              (write)    โ”‚           โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜           โ”‚
โ”‚                                                                          โ”‚
โ”‚   After fork():                                                          โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                โ”‚
โ”‚   โ”‚   PARENT     โ”‚                      โ”‚    CHILD     โ”‚                โ”‚
โ”‚   โ”‚              โ”‚                      โ”‚              โ”‚                โ”‚
โ”‚   โ”‚  fd[0] (R)   โ”‚    KERNEL BUFFER     โ”‚  fd[0] (R)   โ”‚                โ”‚
โ”‚   โ”‚  fd[1] (W) โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚  fd[1] (W)   โ”‚                โ”‚
โ”‚   โ”‚              โ”‚     โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€            โ”‚                โ”‚
โ”‚   โ”‚  close(fd[0])โ”‚                      โ”‚ close(fd[1]) โ”‚                โ”‚
โ”‚   โ”‚  write(fd[1])โ”‚                      โ”‚ read(fd[0])  โ”‚                โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                โ”‚
โ”‚                                                                          โ”‚
โ”‚   Key Insight: After fork, CLOSE the ends you don't need!               โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Pipe Mechanism

Critical Constants:

  • PIPE_BUF: Writes up to this size are atomic (usually 4096 bytes)
  • If pipe is full, write() blocks
  • If pipe is empty, read() blocks
  • If all write ends close, read() returns 0 (EOF)
  • If all read ends close, write() generates SIGPIPE

2. FIFOs: Named Pipes for Unrelated Processes

FIFOs appear in the filesystem and allow communication between unrelated processes.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                           FIFO (Named Pipe)                              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   $ mkfifo /tmp/myfifo                                                  โ”‚
โ”‚   $ ls -l /tmp/myfifo                                                   โ”‚
โ”‚   prw-r--r-- 1 user user 0 Jan 1 12:00 /tmp/myfifo                     โ”‚
โ”‚   ^                                                                      โ”‚
โ”‚   โ””โ”€โ”€ 'p' indicates pipe (FIFO)                                         โ”‚
โ”‚                                                                          โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”‚
โ”‚   โ”‚  Process A      โ”‚          โ”‚  Process B      โ”‚                      โ”‚
โ”‚   โ”‚  (Writer)       โ”‚          โ”‚  (Reader)       โ”‚                      โ”‚
โ”‚   โ”‚                 โ”‚          โ”‚                 โ”‚                      โ”‚
โ”‚   โ”‚  fd = open(     โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”  โ”‚  fd = open(     โ”‚                      โ”‚
โ”‚   โ”‚    "/tmp/myfifo"โ”‚  โ”‚FIFOโ”‚  โ”‚    "/tmp/myfifo"โ”‚                      โ”‚
โ”‚   โ”‚    O_WRONLY)    โ”‚โ”€โ”€โ”ค    โ”œโ”€โ”€โ”‚    O_RDONLY)    โ”‚                      โ”‚
โ”‚   โ”‚                 โ”‚  โ””โ”€โ”€โ”€โ”€โ”˜  โ”‚                 โ”‚                      โ”‚
โ”‚   โ”‚  write(fd, ...) โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚  read(fd, ...)  โ”‚                      โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ”‚
โ”‚                                                                          โ”‚
โ”‚   Blocking Behavior:                                                     โ”‚
โ”‚   โ€ข open() for reading BLOCKS until a writer opens                      โ”‚
โ”‚   โ€ข open() for writing BLOCKS until a reader opens                      โ”‚
โ”‚   โ€ข Use O_NONBLOCK to avoid blocking                                    โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

FIFO Named Pipe

3. POSIX Message Queues

Message queues provide discrete messages with priorities, unlike the byte-stream model of pipes.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      POSIX MESSAGE QUEUE                                 โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   Message Queue: /my_queue                                              โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚   โ”‚  Priority 31 (Highest)                                           โ”‚   โ”‚
โ”‚   โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                     โ”‚   โ”‚
โ”‚   โ”‚  โ”‚ MSG 1   โ”‚ โ† Dequeued first (highest priority)                โ”‚   โ”‚
โ”‚   โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                     โ”‚   โ”‚
โ”‚   โ”‚  Priority 15                                                     โ”‚   โ”‚
โ”‚   โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                        โ”‚   โ”‚
โ”‚   โ”‚  โ”‚ MSG 2   โ”‚ โ”‚ MSG 3   โ”‚ โ† FIFO within same priority           โ”‚   โ”‚
โ”‚   โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                        โ”‚   โ”‚
โ”‚   โ”‚  Priority 0 (Lowest)                                             โ”‚   โ”‚
โ”‚   โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                            โ”‚   โ”‚
โ”‚   โ”‚  โ”‚ MSG 4   โ”‚ โ”‚ MSG 5   โ”‚ โ”‚ MSG 6   โ”‚                            โ”‚   โ”‚
โ”‚   โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                            โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                          โ”‚
โ”‚   Key Functions:                                                         โ”‚
โ”‚   โ€ข mq_open("/my_queue", O_CREAT | O_RDWR, 0644, &attr)               โ”‚
โ”‚   โ€ข mq_send(mqd, buffer, len, priority)                                 โ”‚
โ”‚   โ€ข mq_receive(mqd, buffer, max_len, &priority)                        โ”‚
โ”‚   โ€ข mq_notify(mqd, &sigevent) โ€” async notification                     โ”‚
โ”‚   โ€ข mq_getattr(mqd, &attr) / mq_setattr()                              โ”‚
โ”‚                                                                          โ”‚
โ”‚   Attributes (mq_attr):                                                  โ”‚
โ”‚   โ€ข mq_maxmsg  โ€” max messages in queue                                  โ”‚
โ”‚   โ€ข mq_msgsize โ€” max size of each message                               โ”‚
โ”‚   โ€ข mq_curmsgs โ€” current number of messages                             โ”‚
โ”‚   โ€ข mq_flags   โ€” O_NONBLOCK                                             โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

POSIX Message Queue

4. System V Message Queues

Older API with message types for multiplexing multiple logical channels.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    SYSTEM V MESSAGE QUEUE                                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   key_t key = ftok("/path/to/file", 'A');  // Generate unique key       โ”‚
โ”‚   int msqid = msgget(key, IPC_CREAT | 0644);                            โ”‚
โ”‚                                                                          โ”‚
โ”‚   Message Structure:                                                     โ”‚
โ”‚   struct msgbuf {                                                        โ”‚
โ”‚       long mtype;     // Message type (MUST be > 0)                     โ”‚
โ”‚       char mtext[N];  // Message data                                   โ”‚
โ”‚   };                                                                     โ”‚
โ”‚                                                                          โ”‚
โ”‚   Queue with Multiple Message Types:                                     โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚   โ”‚  mtype=1 โ”‚ mtype=2 โ”‚ mtype=1 โ”‚ mtype=3 โ”‚ mtype=2 โ”‚              โ”‚   โ”‚
โ”‚   โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”‚              โ”‚   โ”‚
โ”‚   โ”‚  โ”‚ A   โ”‚ โ”‚ โ”‚ B   โ”‚ โ”‚ โ”‚ C   โ”‚ โ”‚ โ”‚ D   โ”‚ โ”‚ โ”‚ E   โ”‚ โ”‚              โ”‚   โ”‚
โ”‚   โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚              โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                          โ”‚
โ”‚   Receive Modes (msgrcv msgtyp parameter):                              โ”‚
โ”‚   โ€ข msgtyp = 0  โ†’ Receive first message (any type)                      โ”‚
โ”‚   โ€ข msgtyp > 0  โ†’ Receive first message of type msgtyp                  โ”‚
โ”‚   โ€ข msgtyp < 0  โ†’ Receive first message with type โ‰ค |msgtyp|           โ”‚
โ”‚                                                                          โ”‚
โ”‚   Example: Client-Server Multiplexing                                   โ”‚
โ”‚   โ€ข Server receives: msgtyp = 1 (requests)                              โ”‚
โ”‚   โ€ข Client 100 receives: msgtyp = 100 (responses for client 100)        โ”‚
โ”‚   โ€ข Client 101 receives: msgtyp = 101 (responses for client 101)        โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

System V Message Queue

5. Mutexes and Condition Variables

The fundamental building blocks for thread synchronization.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                 MUTEX + CONDITION VARIABLE PATTERN                       โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   Producer-Consumer with Bounded Buffer:                                 โ”‚
โ”‚                                                                          โ”‚
โ”‚   PRODUCER                              CONSUMER                        โ”‚
โ”‚   โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                              โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                        โ”‚
โ”‚   pthread_mutex_lock(&mutex);           pthread_mutex_lock(&mutex);     โ”‚
โ”‚                                                                          โ”‚
โ”‚   while (count == MAX_SIZE) {           while (count == 0) {            โ”‚
โ”‚       pthread_cond_wait(                    pthread_cond_wait(          โ”‚
โ”‚           &not_full, &mutex);                   &not_empty, &mutex);    โ”‚
โ”‚   }                                     }                               โ”‚
โ”‚   // CRITICAL: while, not if!           // Handle spurious wakeups!    โ”‚
โ”‚                                                                          โ”‚
โ”‚   buffer[in] = item;                    item = buffer[out];             โ”‚
โ”‚   in = (in + 1) % MAX_SIZE;             out = (out + 1) % MAX_SIZE;     โ”‚
โ”‚   count++;                              count--;                        โ”‚
โ”‚                                                                          โ”‚
โ”‚   pthread_cond_signal(&not_empty);      pthread_cond_signal(&not_full); โ”‚
โ”‚   pthread_mutex_unlock(&mutex);         pthread_mutex_unlock(&mutex);   โ”‚
โ”‚                                                                          โ”‚
โ”‚                                                                          โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚   โ”‚                         BOUNDED BUFFER                            โ”‚  โ”‚
โ”‚   โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”                       โ”‚  โ”‚
โ”‚   โ”‚  โ”‚    โ”‚    โ”‚ D1 โ”‚ D2 โ”‚ D3 โ”‚    โ”‚    โ”‚    โ”‚                       โ”‚  โ”‚
โ”‚   โ”‚  โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”˜                       โ”‚  โ”‚
โ”‚   โ”‚            โ–ฒ              โ–ฒ                                       โ”‚  โ”‚
โ”‚   โ”‚           out             in                                      โ”‚  โ”‚
โ”‚   โ”‚           (consumer)      (producer)                              โ”‚  โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                                                          โ”‚
โ”‚   SPURIOUS WAKEUP: pthread_cond_wait() can return even when no         โ”‚
โ”‚   signal was sent. ALWAYS use while() loop, never if()!                 โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Mutex and Condition Variables

6. Read-Write Locks

Optimize for read-heavy workloads where multiple readers can proceed concurrently.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         READ-WRITE LOCKS                                 โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   Concurrency Matrix:                                                    โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                            โ”‚
โ”‚   โ”‚            โ”‚  Reader     โ”‚   Writer    โ”‚                            โ”‚
โ”‚   โ”‚            โ”‚  Holding    โ”‚   Holding   โ”‚                            โ”‚
โ”‚   โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                            โ”‚
โ”‚   โ”‚ Reader     โ”‚     โœ“       โ”‚     โœ—       โ”‚                            โ”‚
โ”‚   โ”‚ Wants      โ”‚  (allowed)  โ”‚  (blocked)  โ”‚                            โ”‚
โ”‚   โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                            โ”‚
โ”‚   โ”‚ Writer     โ”‚     โœ—       โ”‚     โœ—       โ”‚                            โ”‚
โ”‚   โ”‚ Wants      โ”‚  (blocked)  โ”‚  (blocked)  โ”‚                            โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                            โ”‚
โ”‚                                                                          โ”‚
โ”‚   Timeline Example:                                                      โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚   โ”‚ Time:  t1    t2    t3    t4    t5    t6    t7    t8    t9       โ”‚   โ”‚
โ”‚   โ”‚        โ”‚     โ”‚     โ”‚     โ”‚     โ”‚     โ”‚     โ”‚     โ”‚     โ”‚        โ”‚   โ”‚
โ”‚   โ”‚ R1:    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค              โ”‚   โ”‚
โ”‚   โ”‚        โ”‚     rdlock()                    unlock() โ”‚              โ”‚   โ”‚
โ”‚   โ”‚ R2:    โ”‚     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค              โ”‚              โ”‚   โ”‚
โ”‚   โ”‚        โ”‚     โ”‚  rdlock()   unlock() โ”‚              โ”‚              โ”‚   โ”‚
โ”‚   โ”‚ R3:    โ”‚     โ”‚     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค              โ”‚              โ”‚   โ”‚
โ”‚   โ”‚        โ”‚     โ”‚     โ”‚               โ”‚              โ”‚              โ”‚   โ”‚
โ”‚   โ”‚ W1:    โ”‚     โ”‚     โ”‚  wrlock()โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€BLOCKEDโ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   โ”‚   โ”‚
โ”‚   โ”‚        โ”‚     โ”‚     โ”‚               โ”‚              โ”‚    RUNS  โ”‚   โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                          โ”‚
โ”‚   Writer Starvation Problem:                                             โ”‚
โ”‚   โ€ข If readers continuously arrive, writer may wait forever             โ”‚
โ”‚   โ€ข Some implementations give preference to writers                      โ”‚
โ”‚   โ€ข pthread_rwlockattr_setkind_np() can set preference                  โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Read-Write Locks

7. Record Locking (fcntl)

Lock byte ranges within files, enabling concurrent database access.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         RECORD LOCKING (fcntl)                           โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   File: database.db                                                      โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
โ”‚   โ”‚ Offset:  0      100     200     300     400     500     600    โ”‚    โ”‚
โ”‚   โ”‚          โ”‚       โ”‚       โ”‚       โ”‚       โ”‚       โ”‚       โ”‚     โ”‚    โ”‚
โ”‚   โ”‚          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚    โ”‚
โ”‚   โ”‚          โ”‚                   FILE DATA                    โ”‚     โ”‚    โ”‚
โ”‚   โ”‚          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ”‚    โ”‚
โ”‚   โ”‚                                                                 โ”‚    โ”‚
โ”‚   โ”‚  Process A: Write Lock [100-200)                               โ”‚    โ”‚
โ”‚   โ”‚          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ–“โ–“โ–“โ–“โ–“โ–“โ–“โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚    โ”‚
โ”‚   โ”‚                  โ–ฒโ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–ฒ                                      โ”‚    โ”‚
โ”‚   โ”‚                  โ”‚LOCKED โ”‚                                      โ”‚    โ”‚
โ”‚   โ”‚                                                                 โ”‚    โ”‚
โ”‚   โ”‚  Process B: Read Lock [300-500)                                โ”‚    โ”‚
โ”‚   โ”‚          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚    โ”‚
โ”‚   โ”‚                                  โ–ฒโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–ฒ              โ”‚    โ”‚
โ”‚   โ”‚                                  โ”‚  READ LOCKED  โ”‚              โ”‚    โ”‚
โ”‚   โ”‚                                                                 โ”‚    โ”‚
โ”‚   โ”‚  Process C wants: Write Lock [150-350)                         โ”‚    โ”‚
โ”‚   โ”‚          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€XXXXโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผXXXXโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚    โ”‚
โ”‚   โ”‚                  โ–ฒCONFLICTโ–ฒ      โ–ฒCONFLICT                      โ”‚    โ”‚
โ”‚   โ”‚                  BLOCKED!        BLOCKED!                       โ”‚    โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ”‚                                                                          โ”‚
โ”‚   struct flock {                                                         โ”‚
โ”‚       short l_type;    // F_RDLCK, F_WRLCK, F_UNLCK                     โ”‚
โ”‚       short l_whence;  // SEEK_SET, SEEK_CUR, SEEK_END                  โ”‚
โ”‚       off_t l_start;   // Starting offset                               โ”‚
โ”‚       off_t l_len;     // Length (0 = to EOF)                           โ”‚
โ”‚       pid_t l_pid;     // PID holding lock (F_GETLK only)              โ”‚
โ”‚   };                                                                     โ”‚
โ”‚                                                                          โ”‚
โ”‚   Commands:                                                              โ”‚
โ”‚   โ€ข F_SETLK  โ€” Try to acquire lock, return error if blocked            โ”‚
โ”‚   โ€ข F_SETLKW โ€” Try to acquire lock, WAIT if blocked                    โ”‚
โ”‚   โ€ข F_GETLK  โ€” Test if lock would succeed, return blocker info         โ”‚
โ”‚                                                                          โ”‚
โ”‚   Advisory vs Mandatory:                                                 โ”‚
โ”‚   โ€ข Advisory (default): Cooperative, processes can ignore locks         โ”‚
โ”‚   โ€ข Mandatory: Kernel enforces (mount -o mand, chmod g+s,g-x)          โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Record Locking

8. POSIX Semaphores

Counting semaphores for resource management and synchronization.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                        POSIX SEMAPHORES                                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   Named Semaphore (persists in filesystem):                             โ”‚
โ”‚   sem_t *sem = sem_open("/my_sem", O_CREAT, 0644, initial_value);      โ”‚
โ”‚                                                                          โ”‚
โ”‚   Unnamed Semaphore (in shared memory):                                  โ”‚
โ”‚   sem_t sem;                                                             โ”‚
โ”‚   sem_init(&sem, pshared, initial_value);                               โ”‚
โ”‚   // pshared = 0: thread-shared                                         โ”‚
โ”‚   // pshared = 1: process-shared (must be in shared memory!)            โ”‚
โ”‚                                                                          โ”‚
โ”‚   Binary Semaphore (Mutex-like):                                         โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”‚
โ”‚   โ”‚  Value: 1                                                      โ”‚     โ”‚
โ”‚   โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚     โ”‚
โ”‚   โ”‚  โ”‚  sem_wait()           sem_post()                        โ”‚  โ”‚     โ”‚
โ”‚   โ”‚  โ”‚      โ”‚                    โ–ฒ                             โ”‚  โ”‚     โ”‚
โ”‚   โ”‚  โ”‚      โ–ผ                    โ”‚                             โ”‚  โ”‚     โ”‚
โ”‚   โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                         โ”‚  โ”‚     โ”‚
โ”‚   โ”‚  โ”‚  โ”‚ 1โ†’0   โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚ 0โ†’1   โ”‚                         โ”‚  โ”‚     โ”‚
โ”‚   โ”‚  โ”‚  โ”‚ ENTER โ”‚  CRITICAL  โ”‚ EXIT  โ”‚                         โ”‚  โ”‚     โ”‚
โ”‚   โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   SECTION  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                         โ”‚  โ”‚     โ”‚
โ”‚   โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚     โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ”‚
โ”‚                                                                          โ”‚
โ”‚   Counting Semaphore (Resource Pool):                                    โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”‚
โ”‚   โ”‚  Value: 3 (3 database connections available)                   โ”‚     โ”‚
โ”‚   โ”‚                                                                 โ”‚     โ”‚
โ”‚   โ”‚  sem_wait() โ†’ 3โ†’2  (Thread A takes connection)                 โ”‚     โ”‚
โ”‚   โ”‚  sem_wait() โ†’ 2โ†’1  (Thread B takes connection)                 โ”‚     โ”‚
โ”‚   โ”‚  sem_wait() โ†’ 1โ†’0  (Thread C takes connection)                 โ”‚     โ”‚
โ”‚   โ”‚  sem_wait() โ†’ BLOCKED! (Thread D waits)                        โ”‚     โ”‚
โ”‚   โ”‚  sem_post() โ†’ 0โ†’1  (Thread A returns connection)               โ”‚     โ”‚
โ”‚   โ”‚  โ†’ Thread D unblocks, 1โ†’0                                      โ”‚     โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ”‚
โ”‚                                                                          โ”‚
โ”‚   Key Difference from Mutex:                                             โ”‚
โ”‚   โ€ข Semaphore has no "owner" โ€” any thread can post                      โ”‚
โ”‚   โ€ข Can count beyond 1                                                   โ”‚
โ”‚   โ€ข sem_post() from signal handler is safe                              โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

POSIX Semaphores

9. System V Semaphores

Complex but powerful: semaphore sets with atomic multi-semaphore operations.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                       SYSTEM V SEMAPHORES                                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   Semaphore Set (3 semaphores):                                         โ”‚
โ”‚   key_t key = ftok("/path", 'S');                                       โ”‚
โ”‚   int semid = semget(key, 3, IPC_CREAT | 0644);                        โ”‚
โ”‚                                                                          โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚   โ”‚  semid = 12345                                                   โ”‚   โ”‚
โ”‚   โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                    โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  sem[0]     โ”‚  sem[1]     โ”‚  sem[2]     โ”‚                    โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  value=5    โ”‚  value=1    โ”‚  value=0    โ”‚                    โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  (resources)โ”‚  (mutex)    โ”‚  (counter)  โ”‚                    โ”‚   โ”‚
โ”‚   โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                    โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                          โ”‚
โ”‚   Atomic Multi-Semaphore Operation:                                      โ”‚
โ”‚   struct sembuf ops[] = {                                                โ”‚
โ”‚       { 0, -1, 0 },      // Decrement sem[0] by 1                       โ”‚
โ”‚       { 1, -1, 0 },      // Decrement sem[1] by 1                       โ”‚
โ”‚       { 2,  1, 0 },      // Increment sem[2] by 1                       โ”‚
โ”‚   };                                                                     โ”‚
โ”‚   semop(semid, ops, 3);  // ALL THREE happen atomically!                โ”‚
โ”‚                                                                          โ”‚
โ”‚   SEM_UNDO Flag (Crash Recovery):                                        โ”‚
โ”‚   struct sembuf op = { 0, -1, SEM_UNDO };                               โ”‚
โ”‚   // If process crashes, kernel automatically reverses the operation    โ”‚
โ”‚   // Kernel maintains semadj value per process per semaphore            โ”‚
โ”‚                                                                          โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚   โ”‚  Process A                                                       โ”‚   โ”‚
โ”‚   โ”‚  semop(semid, {0, -1, SEM_UNDO}, 1);  // sem[0]: 5โ†’4            โ”‚   โ”‚
โ”‚   โ”‚  semop(semid, {0, -1, SEM_UNDO}, 1);  // sem[0]: 4โ†’3            โ”‚   โ”‚
โ”‚   โ”‚  semadj[0] = +2                                                  โ”‚   โ”‚
โ”‚   โ”‚                                                                  โ”‚   โ”‚
โ”‚   โ”‚  CRASH! ๐Ÿ’ฅ                                                       โ”‚   โ”‚
โ”‚   โ”‚                                                                  โ”‚   โ”‚
โ”‚   โ”‚  Kernel applies semadj: sem[0]: 3โ†’5 (restored!)                 โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                          โ”‚
โ”‚   Wait-for-Zero:                                                         โ”‚
โ”‚   struct sembuf op = { 0, 0, 0 };  // Wait until sem[0] == 0            โ”‚
โ”‚   // Useful for barrier synchronization                                  โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

System V Semaphores

10. POSIX Shared Memory

Map memory regions that multiple processes can access directly.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      POSIX SHARED MEMORY                                 โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   Creating Shared Memory:                                                โ”‚
โ”‚   int fd = shm_open("/my_shm", O_CREAT | O_RDWR, 0644);                โ”‚
โ”‚   ftruncate(fd, SIZE);                                                   โ”‚
โ”‚   void *ptr = mmap(NULL, SIZE, PROT_READ|PROT_WRITE,                    โ”‚
โ”‚                    MAP_SHARED, fd, 0);                                   โ”‚
โ”‚                                                                          โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚   โ”‚                        PHYSICAL MEMORY                           โ”‚   โ”‚
โ”‚   โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚   โ”‚
โ”‚   โ”‚   โ”‚              SHARED MEMORY REGION                         โ”‚  โ”‚   โ”‚
โ”‚   โ”‚   โ”‚             /dev/shm/my_shm                               โ”‚  โ”‚   โ”‚
โ”‚   โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚   โ”‚
โ”‚   โ”‚                             โ”‚                                   โ”‚   โ”‚
โ”‚   โ”‚              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                   โ”‚   โ”‚
โ”‚   โ”‚              โ”‚                              โ”‚                   โ”‚   โ”‚
โ”‚   โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   PROCESS A         โ”‚     โ”‚    PROCESS B            โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   Virtual Address   โ”‚     โ”‚    Virtual Address      โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   Space             โ”‚     โ”‚    Space                โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚     โ”‚    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   โ”‚ 0x7f...    โ”‚    โ”‚     โ”‚    โ”‚ 0x7f...    โ”‚       โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   โ”‚ mmap()     โ”‚โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”‚ mmap()     โ”‚       โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   โ”‚ region     โ”‚    โ”‚     โ”‚    โ”‚ region     โ”‚       โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚     โ”‚    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                          โ”‚
โ”‚   MAP_SHARED vs MAP_PRIVATE:                                             โ”‚
โ”‚   โ€ข MAP_SHARED: Changes visible to all processes, written to file       โ”‚
โ”‚   โ€ข MAP_PRIVATE: Copy-on-write, changes are private                     โ”‚
โ”‚                                                                          โ”‚
โ”‚   CRITICAL: Shared memory requires EXTERNAL SYNCHRONIZATION!            โ”‚
โ”‚   Use mutexes/semaphores with PTHREAD_PROCESS_SHARED attribute          โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

POSIX Shared Memory

11. System V Shared Memory

The older API with explicit attach/detach semantics.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                     SYSTEM V SHARED MEMORY                               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   key_t key = ftok("/path", 'M');                                       โ”‚
โ”‚   int shmid = shmget(key, SIZE, IPC_CREAT | 0644);                     โ”‚
โ”‚   void *ptr = shmat(shmid, NULL, 0);  // Attach                        โ”‚
โ”‚   // ... use shared memory ...                                          โ”‚
โ”‚   shmdt(ptr);                          // Detach                        โ”‚
โ”‚   shmctl(shmid, IPC_RMID, NULL);       // Mark for deletion             โ”‚
โ”‚                                                                          โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚   โ”‚  shmget() creates segment in kernel                              โ”‚   โ”‚
โ”‚   โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  Kernel Shared Memory Table                                  โ”‚โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  โ”‚shmid โ”‚ key   โ”‚ size  โ”‚nattch โ”‚ permissions             โ”‚โ”‚โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”‚โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  โ”‚ 100  โ”‚0x1234 โ”‚ 4096  โ”‚   2   โ”‚ rw-r--r--               โ”‚โ”‚โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  โ”‚ 101  โ”‚0x5678 โ”‚ 8192  โ”‚   1   โ”‚ rw-------               โ”‚โ”‚โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚โ”‚   โ”‚
โ”‚   โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚   โ”‚
โ”‚   โ”‚                                                                  โ”‚   โ”‚
โ”‚   โ”‚  shmat() maps to process address space                          โ”‚   โ”‚
โ”‚   โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”             โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  Process A         โ”‚      โ”‚  Process B         โ”‚             โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  nattch++          โ”‚      โ”‚  nattch++          โ”‚             โ”‚   โ”‚
โ”‚   โ”‚  โ”‚  0x7fff0000 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ–ถ shmid=100       โ”‚             โ”‚   โ”‚
โ”‚   โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜             โ”‚   โ”‚
โ”‚   โ”‚                                                                  โ”‚   โ”‚
โ”‚   โ”‚  shmctl(IPC_RMID) marks for deletion                            โ”‚   โ”‚
โ”‚   โ”‚  โ€ข Segment deleted when nattch reaches 0                        โ”‚   โ”‚
โ”‚   โ”‚  โ€ข Survives process exit if nattch > 0                          โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                          โ”‚
โ”‚   Attachment Address:                                                    โ”‚
โ”‚   โ€ข NULL: Kernel chooses address                                         โ”‚
โ”‚   โ€ข Specific address: shmat(shmid, addr, SHM_RND)                       โ”‚
โ”‚   โ€ข SHM_RDONLY: Attach read-only                                        โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

System V Shared Memory

12. Sun RPC (Remote Procedure Calls)

Make function calls across network boundaries transparently.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                          SUN RPC ARCHITECTURE                            โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                          โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚   โ”‚                         RPC FLOW                                 โ”‚   โ”‚
โ”‚   โ”‚                                                                  โ”‚   โ”‚
โ”‚   โ”‚   CLIENT                                SERVER                   โ”‚   โ”‚
โ”‚   โ”‚   โ”€โ”€โ”€โ”€โ”€โ”€                                โ”€โ”€โ”€โ”€โ”€โ”€                   โ”‚   โ”‚
โ”‚   โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚  Application    โ”‚                  โ”‚  Application    โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚  result = add(a,b)                 โ”‚  int add(a,b) { โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                  โ”‚    return a+b;  โ”‚      โ”‚   โ”‚
โ”‚   โ”‚            โ”‚                           โ”‚  }               โ”‚      โ”‚   โ”‚
โ”‚   โ”‚            โ–ผ                           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚   โ”‚
โ”‚   โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚  Client Stub    โ”‚                  โ”‚  Server Stub    โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚  (generated by  โ”‚                  โ”‚  (generated by  โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   rpcgen)       โ”‚                  โ”‚   rpcgen)       โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚   โ”‚
โ”‚   โ”‚            โ”‚ XDR encode                         โ”‚ XDR decode    โ”‚   โ”‚
โ”‚   โ”‚            โ–ผ                                    โ”‚               โ”‚   โ”‚
โ”‚   โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”‚   โ”‚
โ”‚   โ”‚   โ”‚   RPC Runtime   โ”‚                  โ”‚   RPC Runtime   โ”‚      โ”‚   โ”‚
โ”‚   โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚   โ”‚
โ”‚   โ”‚            โ”‚                                    โ”‚               โ”‚   โ”‚
โ”‚   โ”‚            โ–ผ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• NETWORK โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•               โ”‚   โ”‚
โ”‚   โ”‚                                                                  โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                          โ”‚
โ”‚   rpcgen Workflow:                                                       โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚   โ”‚  calc.x (Interface Definition)                                   โ”‚   โ”‚
โ”‚   โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                                   โ”‚   โ”‚
โ”‚   โ”‚  program CALC_PROG {                                             โ”‚   โ”‚
โ”‚   โ”‚      version CALC_VERS {                                         โ”‚   โ”‚
โ”‚   โ”‚          int ADD(operands) = 1;                                  โ”‚   โ”‚
โ”‚   โ”‚          int SUB(operands) = 2;                                  โ”‚   โ”‚
โ”‚   โ”‚      } = 1;                                                      โ”‚   โ”‚
โ”‚   โ”‚  } = 0x20000001;                                                 โ”‚   โ”‚
โ”‚   โ”‚                                                                  โ”‚   โ”‚
โ”‚   โ”‚  $ rpcgen calc.x                                                 โ”‚   โ”‚
โ”‚   โ”‚  โ†“                                                               โ”‚   โ”‚
โ”‚   โ”‚  calc.h        - Common definitions                              โ”‚   โ”‚
โ”‚   โ”‚  calc_clnt.c   - Client stub                                     โ”‚   โ”‚
โ”‚   โ”‚  calc_svc.c    - Server main + dispatch                          โ”‚   โ”‚
โ”‚   โ”‚  calc_xdr.c    - XDR serialization routines                      โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                          โ”‚
โ”‚   Port Mapper (rpcbind):                                                 โ”‚
โ”‚   โ€ข Server registers: program number + version โ†’ port                   โ”‚
โ”‚   โ€ข Client queries: "Where is CALC_PROG version 1?"                    โ”‚
โ”‚   โ€ข Response: "Port 45678"                                              โ”‚
โ”‚   โ€ข Client connects directly to port 45678                              โ”‚
โ”‚                                                                          โ”‚
โ”‚   XDR (External Data Representation):                                    โ”‚
โ”‚   โ€ข Big-endian, 4-byte aligned                                          โ”‚
โ”‚   โ€ข Handles int, float, string, arrays, structs                         โ”‚
โ”‚   โ€ข Machine-independent wire format                                      โ”‚
โ”‚                                                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Sun RPC Architecture


Concept Summary Table

This section provides a map of the mental models you will build during these projects.

Concept Cluster What You Need to Internalize
Pipes & FIFOs Unidirectional byte streams. Parent-child inheritance. PIPE_BUF atomicity. EOF on close.
Message Queues Discrete messages vs byte streams. POSIX priorities vs System V types. Kernel persistence.
Mutexes & Condvars Protect shared data, signal state changes. ALWAYS use while() not if() for conditions.
Read-Write Locks Multiple readers OR one writer. Trade-off between concurrency and fairness.
Record Locking Byte-range locks within files. Advisory vs mandatory. Deadlock detection.
Semaphores Counting resources, not just locking. POSIX simplicity vs System V atomic sets. SEM_UNDO recovery.
Shared Memory Fastest IPC but requires external synchronization. POSIX mmap vs System V attach.
Sun RPC Transparently call functions across network. rpcgen for stubs, XDR for serialization.

Deep Dive Reading by Concept

This section maps each concept to specific book chapters for deeper understanding.

Pipes & Basic IPC

Concept Book & Chapter Why This Matters
Pipe fundamentals โ€œAdvanced Programming in the UNIX Environmentโ€ by Stevens & Rago โ€” Ch. 15 Canonical explanation of pipe semantics and limitations
FIFO implementation โ€œThe Linux Programming Interfaceโ€ by Kerrisk โ€” Ch. 44 Modern Linux-specific details and edge cases
Shell pipelines โ€œThe Linux Command Lineโ€ by Shotts โ€” Ch. 6 Understanding how the shell uses pipes

Message Queues

Concept Book & Chapter Why This Matters
POSIX message queues โ€œThe Linux Programming Interfaceโ€ by Kerrisk โ€” Ch. 52 Complete POSIX MQ coverage with examples
System V message queues โ€œAdvanced Programming in the UNIX Environmentโ€ by Stevens & Rago โ€” Ch. 15.7 Classic treatment with design rationale

Synchronization Primitives

Concept Book & Chapter Why This Matters
Mutexes & Condvars โ€œProgramming with POSIX Threadsโ€ by Butenhof โ€” Ch. 3 The definitive pthreads reference
Deadlock avoidance โ€œOperating Systems: Three Easy Piecesโ€ by Arpaci-Dusseau โ€” Ch. 32 Theoretical foundation for deadlock
Semaphore theory โ€œOperating Systems: Three Easy Piecesโ€ by Arpaci-Dusseau โ€” Ch. 31 Dijkstraโ€™s semaphores explained clearly

Shared Memory

Concept Book & Chapter Why This Matters
mmap fundamentals โ€œThe Linux Programming Interfaceโ€ by Kerrisk โ€” Ch. 49 Memory mapping in depth
POSIX shared memory โ€œThe Linux Programming Interfaceโ€ by Kerrisk โ€” Ch. 54 Modern shared memory API
System V shared memory โ€œAdvanced Programming in the UNIX Environmentโ€ by Stevens & Rago โ€” Ch. 15.9 Classic shm* API

Remote Procedure Calls

Concept Book & Chapter Why This Matters
RPC concepts โ€œDistributed Systemsโ€ by Tanenbaum โ€” Ch. 4 Theoretical RPC foundation
XDR serialization โ€œUnix Network Programming Vol 2โ€ by Stevens โ€” Ch. 16 Wire format details

Quick Start: Your First 48 Hours

Feeling overwhelmed? Start here instead of reading everything:

Day 1 (4 hours):

  1. Read only the โ€œPipesโ€ section in Core Concepts above
  2. Open a terminal and run: echo "hello" | cat โ€” you just used a pipe!
  3. Start Project 1 - write a simple program that creates a pipe and forks
  4. Donโ€™t worry about FIFOs or message queues yet

Day 2 (4 hours):

  1. Add error handling to your Project 1 code
  2. Experiment with closing/not closing pipe ends
  3. See what happens when you write more than PIPE_BUF bytes
  4. Read โ€œThe Core Question Youโ€™re Answeringโ€ for Project 1

End of Weekend: You now understand that pipes are kernel-buffered byte streams connecting related processes. You can explain โ€œwhy does ls | grep foo work?โ€ to someone. Thatโ€™s 80% of the pipe mental model.

Next Steps:

  • If it clicked: Continue to Project 2 (FIFOs)
  • If confused: Re-read man pages (man 2 pipe, man 7 pipe)
  • If frustrated: Take a break! IPC is hard. Read Kerrisk Ch. 44 slowly.

Best for: Those who want a solid foundation in all IPC mechanisms

  1. Start with Projects 1-3 (Pipes, FIFOs, popen) - Build intuition for byte streams
  2. Then Projects 4-6 (Message Queues) - Understand discrete messages
  3. Then Projects 7-9 (Synchronization) - Master locking primitives
  4. Then Projects 10-14 (Shared Memory) - The fastest IPC
  5. Finally Projects 15-18 (RPC) - Cross-network IPC

Path 2: The Performance Engineer

Best for: Those optimizing high-throughput systems

  1. Start with Projects 10-12 (Shared Memory) - Skip to the fastest mechanism
  2. Then Projects 7-9 (Semaphores) - Synchronize shared memory
  3. Then Project 13 (Lock-free) - Eliminate synchronization overhead
  4. Back to Projects 1-6 (Pipes/MQ) - Understand simpler alternatives

Path 3: The Completionist

Best for: Those building a complete IPC reference implementation

Phase 1: Data Transfer (Weeks 1-3)

  • Projects 1-6 (All pipe and message queue variants)

Phase 2: Synchronization (Weeks 4-6)

  • Projects 7-10 (All locking mechanisms)

Phase 3: Shared Memory (Weeks 7-9)

  • Projects 11-14 (POSIX and System V)

Phase 4: Remote IPC (Weeks 10-12)

  • Projects 15-18 (Sun RPC complete)

Project List

The following projects guide you from basic pipes to complete RPC systems, covering every IPC mechanism from Stevensโ€™ book.


Project 1: Build a Shell Pipeline Executor

  • File: P01-shell-pipeline.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, Go
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 1 (Resume Gold)
  • Difficulty: Level 2 (Intermediate)
  • Knowledge Area: Operating Systems, Process Management
  • Software or Tool: None (pure syscalls)
  • Main Book: โ€œAdvanced Programming in the UNIX Environmentโ€ by Stevens & Rago

What youโ€™ll build: A program that executes cmd1 | cmd2 | cmd3 by creating pipes and forking processes, just like a real shell.

Why it teaches IPC: Forces you to understand pipe file descriptor inheritance across fork(), the critical importance of closing unused ends, and how EOF propagates through a pipeline.

Core challenges youโ€™ll face:

  • File descriptor management โ†’ Understanding dup2() and close()
  • Process coordination โ†’ Multiple fork() calls, parent waiting for children
  • EOF handling โ†’ Why closing write ends matters

Real World Outcome

When complete, youโ€™ll have a program that can execute arbitrary shell pipelines:

What you will see:

  1. Working pipeline execution: Your program runs ls -la | grep txt | wc -l
  2. Correct output: Same result as typing it in bash
  3. Proper cleanup: No zombie processes, no leaked file descriptors

Command Line Outcome Example:

# 1. Compile your pipeline executor
$ gcc -o mypipe mypipe.c
# No errors

# 2. Run a simple two-command pipeline
$ ./mypipe "ls -la" "grep txt"
-rw-r--r-- 1 user user  1234 Jan  1 12:00 notes.txt
-rw-r--r-- 1 user user  5678 Jan  1 12:00 data.txt

# 3. TEST: Three-command pipeline
$ ./mypipe "cat /etc/passwd" "grep root" "cut -d: -f1"
root
# Output shows only "root" - data flowed through all three commands

# 4. TEST: Verify no file descriptor leaks
$ ./mypipe "ls" "cat" &
$ ls -la /proc/$!/fd
total 0
lrwx------ 1 user user 64 Jan  1 12:00 0 -> /dev/pts/0
lrwx------ 1 user user 64 Jan  1 12:00 1 -> /dev/pts/0
lrwx------ 1 user user 64 Jan  1 12:00 2 -> /dev/pts/0
# Only 0,1,2 - no leaked pipe fds!

# 5. TEST: Verify no zombie processes
$ ./mypipe "sleep 1" "cat"
$ ps aux | grep defunct
# No output - no zombies

The Core Question Youโ€™re Answering

โ€œHow does ls | grep foo | wc -l actually work at the system call level?โ€

Before you write any code, trace this on paper: the shell calls pipe() twice, fork() three times, and uses dup2() to rewire stdin/stdout. Each process inherits all file descriptors, but must close the ones it doesnโ€™t use. If you donโ€™t close the write end of a pipe, the reader never gets EOF.


Concepts You Must Understand First

Stop and research these before coding:

  1. File Descriptor Inheritance
    • What file descriptors does a child inherit after fork()?
    • Why does closing fd in parent not affect child?
    • Book Reference: โ€œAPUEโ€ Ch. 3 - Stevens & Rago
  2. dup2() System Call
    • How does dup2(oldfd, newfd) work?
    • What happens to newfd if it was already open?
    • Book Reference: โ€œAPUEโ€ Ch. 3.12 - Stevens & Rago
  3. Pipe Capacity and Blocking
    • What is PIPE_BUF on your system?
    • When does write() to a pipe block?
    • Book Reference: โ€œThe Linux Programming Interfaceโ€ Ch. 44 - Kerrisk

Questions to Guide Your Design

Before implementing, think through these:

  1. Pipe Creation Order
    • Create all pipes before any fork, or one at a time?
    • How do you track which pipe connects which processes?
  2. File Descriptor Cleanup
    • Which process closes which ends of which pipes?
    • What happens if you forget to close the write end?
  3. Error Handling
    • What if exec() fails?
    • What if pipe() fails partway through?

Thinking Exercise

Trace the File Descriptors

Before coding, draw the file descriptor table for this pipeline: A | B | C

After pipe(p1), pipe(p2), before any fork:
Parent FD table:
  3 โ†’ p1[0] (read end of pipe 1)
  4 โ†’ p1[1] (write end of pipe 1)
  5 โ†’ p2[0] (read end of pipe 2)
  6 โ†’ p2[1] (write end of pipe 2)

After forking child A:
  Child A needs: stdin=p1[0]? No wait... A writes TO pipe.
  Actually, A's stdout should go to p1[1].

  [Continue this trace for all processes...]

Questions while tracing:

  • Which fds does process A close after dup2?
  • What would happen if B doesnโ€™t close p1[1]?
  • When does Aโ€™s write() return EOF?

The Interview Questions Theyโ€™ll Ask

Prepare to answer these:

  1. โ€œWalk me through what happens when you type ls | grep foo in a shell.โ€
  2. โ€œWhy is it important to close unused pipe file descriptors?โ€
  3. โ€œWhatโ€™s the difference between pipe() and pipe2() on Linux?โ€
  4. โ€œHow would you implement a pipeline with error propagation (pipefail)?โ€
  5. โ€œWhat happens if a process in the middle of a pipeline dies?โ€

Hints in Layers

Hint 1: Start Simple First, make a TWO command pipeline work. Ignore three+ commands until two works perfectly.

Hint 2: The Pattern For A | B: Create one pipe. Fork twice. Child A: dup2(pipe_write, STDOUT), close both ends, exec. Child B: dup2(pipe_read, STDIN), close both ends, exec. Parent: close both ends, wait for both children.

Hint 3: Generalizing

// Pseudocode for N commands
create N-1 pipes
for i in 0..N:
    fork child i
    in child:
        if i > 0:
            dup2(pipe[i-1].read, STDIN)
        if i < N-1:
            dup2(pipe[i].write, STDOUT)
        close ALL pipe fds (very important!)
        exec(command[i])
parent: close all pipe fds, wait for all children

Hint 4: Debugging Use strace -f ./mypipe "ls" "cat" to see all syscalls across all processes. Look for unclosed fds or blocking reads.


Books That Will Help

Topic Book Chapter
Pipe semantics โ€œAdvanced Programming in the UNIX Environmentโ€ by Stevens & Rago Ch. 15.2
Process creation โ€œOperating Systems: Three Easy Piecesโ€ by Arpaci-Dusseau Ch. 5
File descriptors โ€œThe Linux Programming Interfaceโ€ by Kerrisk Ch. 5

Common Pitfalls & Debugging

Problem 1: โ€œPipeline hangs foreverโ€

  • Why: The read end is waiting for EOF, but some process still has the write end open.
  • Fix: Make sure EVERY process closes EVERY pipe fd it doesnโ€™t need, BEFORE exec.
  • Quick test: ls -la /proc/$(pgrep yourprogram)/fd - should only show 0,1,2

Problem 2: โ€œBroken pipe errorโ€

  • Why: Writer tried to write after reader closed its end.
  • Fix: Usually means reader died unexpectedly. Check your exec() error handling.
  • Debug: Add signal handler for SIGPIPE to see where it happens.

Problem 3: โ€œZombie processes remainโ€

  • Why: Parent isnโ€™t calling wait() or waitpid() for each child.
  • Fix: Parent must wait for ALL children after closing its pipe fds.
  • Quick test: ps aux | grep defunct should show nothing

Testing Your Pipeline:

# Compare your output to bash
$ ./mypipe "ls" "wc -l"
$ ls | wc -l
# Should be identical

# Test with large data
$ ./mypipe "seq 1 1000000" "wc -l"
1000000
# Should not deadlock

Project 2: Client-Server with Named Pipes (FIFOs)

  • File: P02-fifo-client-server.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, Python
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 2 (Micro-SaaS potential)
  • Difficulty: Level 2 (Intermediate)
  • Knowledge Area: IPC, Client-Server Architecture
  • Software or Tool: None (pure syscalls)
  • Main Book: โ€œThe Linux Programming Interfaceโ€ by Michael Kerrisk

What youโ€™ll build: A simple calculator server that listens on a well-known FIFO, receives requests from multiple clients, and sends responses back through client-specific FIFOs.

Why it teaches IPC: FIFOs allow unrelated processes to communicate. This project teaches the common pattern of one well-known server FIFO plus per-client response FIFOs.

Core challenges youโ€™ll face:

  • Blocking behavior โ†’ open() blocks until both ends connected
  • Atomic writes โ†’ Keeping requests from multiple clients separate
  • Cleanup โ†’ Removing FIFOs on shutdown

Real World Outcome

What you will see:

  1. Server running: Waiting for connections on /tmp/calc_server
  2. Multiple clients: Each creates its own response FIFO
  3. Concurrent requests: Clients donโ€™t interfere with each other

Command Line Outcome Example:

# Terminal 1: Start server
$ ./calc_server
Server listening on /tmp/calc_server...
Received: 5 + 3 from client 12345
Sending response: 8 to /tmp/calc_client_12345
Received: 10 * 4 from client 12346
Sending response: 40 to /tmp/calc_client_12346

# Terminal 2: Client 1
$ ./calc_client "5 + 3"
Result: 8

# Terminal 3: Client 2 (simultaneously)
$ ./calc_client "10 * 4"
Result: 40

# Verify FIFOs exist
$ ls -la /tmp/calc*
prw-r--r-- 1 user user 0 Jan  1 12:00 /tmp/calc_server
prw-r--r-- 1 user user 0 Jan  1 12:00 /tmp/calc_client_12345
prw-r--r-- 1 user user 0 Jan  1 12:00 /tmp/calc_client_12346

# After clients exit, their FIFOs are cleaned up
$ ls -la /tmp/calc_client*
ls: cannot access '/tmp/calc_client*': No such file or directory

The Core Question Youโ€™re Answering

โ€œHow can unrelated processes communicate when they canโ€™t share file descriptors through fork()?โ€

Named pipes (FIFOs) live in the filesystem, so any process can open them by path. The challenge is the bidirectional communication pattern: server needs to know where to send the response. The standard solution is client-specific response FIFOs.


Concepts You Must Understand First

Stop and research these before coding:

  1. FIFO Creation and Permissions
    • What does mkfifo() do? Whatโ€™s the mode parameter?
    • What happens if FIFO already exists?
    • Book Reference: โ€œThe Linux Programming Interfaceโ€ Ch. 44.7 - Kerrisk
  2. Blocking Semantics
    • When does open() on a FIFO block?
    • Whatโ€™s O_NONBLOCK behavior for FIFOs?
    • Book Reference: โ€œAPUEโ€ Ch. 15.5 - Stevens & Rago
  3. Atomic Writes
    • What happens if two clients write simultaneously?
    • Whatโ€™s PIPE_BUF and why does it matter for FIFOs?

Hints in Layers

Hint 1: The Protocol Client sends: "pid:operation\n" (e.g., โ€œ12345:5 + 3\nโ€). Server extracts pid, computes, responds to /tmp/calc_client_<pid>.

Hint 2: FIFO Lifecycle Server: mkfifo(โ€œ/tmp/calc_serverโ€), open(O_RDONLY), read loop. Client: mkfifo(โ€œ/tmp/calc_client_PIDโ€), open server FIFO O_WRONLY, write request, open client FIFO O_RDONLY, read response, unlink client FIFO.

Hint 3: Handling EOF When all writers close, read() returns 0. Server should re-open or use O_RDWR trick to prevent EOF.


Books That Will Help

Topic Book Chapter
FIFO details โ€œThe Linux Programming Interfaceโ€ by Kerrisk Ch. 44
Client-server patterns โ€œUnix Network Programming Vol 2โ€ by Stevens Ch. 4
Atomic I/O โ€œAPUEโ€ by Stevens & Rago Ch. 3.11

Project 3: Implement popen() and pclose()

  • File: P03-implement-popen.md
  • Main Programming Language: C
  • Coolness Level: Level 4 (Hardcore Tech Flex)
  • Business Potential: Level 1 (Resume Gold)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: Library Implementation, Process Management

What youโ€™ll build: Your own implementation of the popen() and pclose() library functions.

Why it teaches IPC: popen() combines pipe(), fork(), dup2(), and exec() into a convenient API. Building it yourself ensures you understand all the pieces.

Core challenges youโ€™ll face:

  • Bidirectional limitation โ†’ Why popen is read OR write, not both
  • Process tracking โ†’ Mapping FILE* to child pid for pclose()
  • Signal handling โ†’ What happens if child ignores SIGPIPE?

Real World Outcome

# Your implementation passes the same tests as the real popen
$ ./test_mypopen
Testing mypopen("ls", "r")...
  Read: file1.txt\nfile2.txt\n
  mypclose returned: 0
  PASS

Testing mypopen("cat", "w")...
  Wrote: "Hello from parent\n"
  mypclose returned: 0
  PASS

Testing mypopen("exit 42", "r")...
  mypclose returned: 42
  PASS (exit status preserved)

The Core Question Youโ€™re Answering

โ€œWhy does popen() only support reading OR writing, not both?โ€

Think about it: with a single pipe, data flows one direction. For bidirectional communication, youโ€™d need two pipes and careful coordination to avoid deadlock. popen() is a convenience function for simple cases.


Project 4: POSIX Message Queue Priority Dispatcher

  • File: P04-posix-mq-dispatcher.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 3 (Service & Support Model)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: IPC, Task Scheduling

What youโ€™ll build: A job dispatcher that uses POSIX message queue priorities to ensure high-priority jobs are processed first.

Why it teaches IPC: Unlike pipes, message queues preserve message boundaries and support priorities. This project makes those features essential.

Core challenges youโ€™ll face:

  • Priority inversion โ†’ Low-priority jobs starving
  • Queue full handling โ†’ What to do when mq_send blocks
  • Async notification โ†’ Using mq_notify for efficiency

Real World Outcome

# Start the dispatcher
$ ./job_dispatcher &
Dispatcher running, queue: /job_queue

# Submit jobs with different priorities
$ ./submit_job --priority=0 --cmd="sleep 10"  # Low priority
Job 1 queued (priority 0)

$ ./submit_job --priority=31 --cmd="echo URGENT"  # High priority
Job 2 queued (priority 31)

$ ./submit_job --priority=15 --cmd="date"  # Medium priority
Job 3 queued (priority 15)

# Watch dispatcher output - processes high priority first!
Dispatcher: Processing job 2 (priority 31): echo URGENT
URGENT
Dispatcher: Processing job 3 (priority 15): date
Sat Jan  1 12:00:00 UTC 2025
Dispatcher: Processing job 1 (priority 0): sleep 10
(10 seconds later...)

Concepts You Must Understand First

  1. mq_attr Structure
    • mq_maxmsg: How many messages can queue hold?
    • mq_msgsize: Maximum size of each message?
    • Book Reference: โ€œThe Linux Programming Interfaceโ€ Ch. 52 - Kerrisk
  2. Priority Ordering
    • Higher priority = dequeued first
    • FIFO within same priority level
  3. mq_notify for Async
    • Notify via signal or thread when message arrives
    • One-shot: must re-register after each notification

Project 5: System V Message Queue Multi-Client Server

  • File: P05-sysv-mq-server.md
  • Main Programming Language: C
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 2 (Micro-SaaS)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: IPC, Multiplexing

What youโ€™ll build: A server using System V message queues where clients multiplex on a single queue using message types.

Why it teaches IPC: System V message types allow selective receives (msgtyp parameter), enabling multiple logical channels on one queue.

Core challenges youโ€™ll face:

  • ftok collisions โ†’ Understanding key generation
  • Message type protocol โ†’ Designing the multiplexing scheme
  • Cleanup on crash โ†’ Orphaned queues persist!

Real World Outcome

# Server uses one queue for all clients
$ ./sysv_server
Server starting, key=0x12345678, msqid=100
Waiting for requests (msgtyp=1)...

# Client 1 (PID 5001) sends request
$ ./sysv_client "HELLO"
Sending to server (msgtyp=1)
Waiting for response (msgtyp=5001)
Response: HELLO_PROCESSED

# Client 2 (PID 5002) sends simultaneously
$ ./sysv_client "WORLD"
Response: WORLD_PROCESSED

# Both used the SAME queue, but different message types!
$ ipcs -q
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
0x12345678 100        user       644        0            0

The Core Question Youโ€™re Answering

โ€œHow can multiple clients share a single message queue without mixing up their responses?โ€

Message types are the key. Server receives msgtyp=1 (requests). Each client sends its PID in the request, and server responds with msgtyp=. Clients receive only their own responses.


Project 6: Message Queue Performance Benchmark

  • File: P06-mq-benchmark.md
  • Main Programming Language: C
  • Coolness Level: Level 2 (Practical but Forgettable)
  • Business Potential: Level 1 (Resume Gold)
  • Difficulty: Level 2 (Intermediate)
  • Knowledge Area: Performance Analysis, IPC

What youโ€™ll build: A benchmark comparing POSIX vs System V message queues, pipes, and Unix domain sockets.

Why it teaches IPC: Numbers donโ€™t lie. Youโ€™ll see exactly when each mechanism shines.


Real World Outcome

$ ./ipc_benchmark --msg-size=1024 --iterations=100000

IPC Mechanism Benchmark (1KB messages, 100K iterations)
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Mechanism              Throughput     Latency (avg)   Latency (p99)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Pipe                   1.2 GB/s       0.8 ฮผs          2.1 ฮผs
FIFO                   1.1 GB/s       0.9 ฮผs          2.4 ฮผs
Unix Domain Socket     1.4 GB/s       0.7 ฮผs          1.8 ฮผs
POSIX Message Queue    0.8 GB/s       1.2 ฮผs          3.5 ฮผs
System V Message Queue 0.6 GB/s       1.6 ฮผs          4.2 ฮผs
Shared Memory + Sem    2.8 GB/s       0.3 ฮผs          0.8 ฮผs

Winner: Shared Memory (for raw throughput)
Best simplicity: Unix Domain Socket

Project 7: Producer-Consumer with Mutexes and Condition Variables

  • File: P07-producer-consumer.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, C++
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 1 (Resume Gold)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: Concurrency, Synchronization

What youโ€™ll build: The classic bounded-buffer producer-consumer with multiple producers and consumers using pthreads.

Why it teaches IPC: This is THE canonical synchronization problem. If you can implement this correctly, you understand mutexes and condition variables.

Core challenges youโ€™ll face:

  • Spurious wakeups โ†’ Why while() not if()
  • Broadcast vs Signal โ†’ When to use each
  • Deadlock potential โ†’ Lock ordering matters

Real World Outcome

$ ./producer_consumer --producers=3 --consumers=2 --buffer-size=10 --items=1000

Producer-Consumer Simulation
Buffer size: 10, Producers: 3, Consumers: 2, Items: 1000

[P1] Produced item 1
[P2] Produced item 2
[C1] Consumed item 1
[P3] Produced item 3
[P1] Produced item 4
[C2] Consumed item 2
...
[C1] Consumed item 1000

Statistics:
  Total produced: 1000
  Total consumed: 1000
  Buffer empty waits: 234
  Buffer full waits: 156

PASS: All items produced and consumed correctly

The Core Question Youโ€™re Answering

โ€œWhy must you ALWAYS use while() instead of if() when checking conditions after pthread_cond_wait()?โ€

Spurious wakeups. The POSIX specification explicitly allows pthread_cond_wait() to return even when no signal was sent. Production code that uses if instead of while will eventually fail.


Project 8: Reader-Writer Lock Implementation

  • File: P08-rwlock-impl.md
  • Main Programming Language: C
  • Coolness Level: Level 4 (Hardcore Tech Flex)
  • Business Potential: Level 1 (Resume Gold)
  • Difficulty: Level 4 (Expert)
  • Knowledge Area: Concurrency, Lock Design

What youโ€™ll build: Your own read-write lock implementation using only mutexes and condition variables.

Why it teaches IPC: Implementing rwlock from primitives reveals the design decisions: reader preference vs writer preference, and the starvation trade-offs.

Core challenges youโ€™ll face:

  • Writer starvation โ†’ Continuous readers block writers forever
  • Reader starvation โ†’ Giving writers priority starves readers
  • Fair queuing โ†’ FIFO ordering is complex

Real World Outcome

$ ./test_myrwlock --readers=10 --writers=3 --duration=10s

My RWLock Test (10 readers, 3 writers, 10 seconds)

Reader 1 acquired read lock (0 writers waiting)
Reader 2 acquired read lock (0 writers waiting)
Reader 3 acquired read lock (0 writers waiting)
Writer 1 waiting... (3 readers active)
Reader 1 released read lock
Reader 2 released read lock
Reader 3 released read lock
Writer 1 acquired write lock
Writer 1 released write lock
Reader 4 acquired read lock
...

Statistics:
  Read operations: 15,234
  Write operations: 456
  Max reader wait: 12ms
  Max writer wait: 45ms
  No starvation detected: PASS

Project 9: Record Locking Database

  • File: P09-record-locking-db.md
  • Main Programming Language: C
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 2 (Micro-SaaS)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: File Systems, Databases

What youโ€™ll build: A simple key-value store where concurrent processes can read and write records using fcntl byte-range locks.

Why it teaches IPC: Record locking is how databases allow concurrent access. Youโ€™ll implement fine-grained locking on a shared file.

Core challenges youโ€™ll face:

  • Deadlock detection โ†’ fcntl with F_SETLKW can deadlock
  • Lock inheritance โ†’ What happens across fork()?
  • Advisory nature โ†’ Uncooperative processes can ignore locks

Real World Outcome

# Start multiple concurrent clients
$ ./kvstore set key1 value1 &
$ ./kvstore set key2 value2 &
$ ./kvstore get key1 &
$ ./kvstore set key1 updated &

# All complete without corruption
$ ./kvstore get key1
updated
$ ./kvstore get key2
value2

# Verify locking works
$ ./kvstore lock-test key1
Process 1: Acquired write lock on key1
Process 2: Waiting for lock...
(Process 1 holds lock for 2 seconds)
Process 1: Released lock
Process 2: Acquired write lock on key1

Project 10: POSIX Semaphore Connection Pool

  • File: P10-semaphore-pool.md
  • Main Programming Language: C
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 3 (Service & Support)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: Resource Management, Concurrency

What youโ€™ll build: A database connection pool manager using POSIX counting semaphores to limit concurrent connections.

Why it teaches IPC: Counting semaphores are perfect for resource pools. The semaphore value represents available resources.

Core challenges youโ€™ll face:

  • sem_timedwait โ†’ Handling connection timeout
  • Process-shared semaphores โ†’ Allocating in shared memory
  • Cleanup on crash โ†’ Returning connections when process dies

Real World Outcome

$ ./pool_manager --max-connections=5 &
Pool manager started (5 connections available)

# Spawn 10 workers, each needs a connection
$ for i in {1..10}; do ./worker $i & done

Worker 1: Acquired connection (4 remaining)
Worker 2: Acquired connection (3 remaining)
Worker 3: Acquired connection (2 remaining)
Worker 4: Acquired connection (1 remaining)
Worker 5: Acquired connection (0 remaining)
Worker 6: Waiting for connection...
Worker 7: Waiting for connection...
Worker 1: Released connection (1 remaining)
Worker 6: Acquired connection (0 remaining)
...

All workers completed successfully

Project 11: System V Semaphore Barrier

  • File: P11-sysv-barrier.md
  • Main Programming Language: C
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 1 (Resume Gold)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: Parallel Computing, Synchronization

What youโ€™ll build: A barrier synchronization primitive using System V semaphores where N processes wait until all arrive.

Why it teaches IPC: System V semaphores can atomically operate on multiple semaphores, enabling complex synchronization patterns.

Core challenges youโ€™ll face:

  • Atomic multi-semaphore ops โ†’ Using semop with multiple sembuf
  • SEM_UNDO โ†’ Handling process crashes mid-barrier
  • Reusable barrier โ†’ Resetting for the next round

Real World Outcome

$ ./barrier_test --processes=5 --iterations=3

Barrier Test (5 processes, 3 iterations)

[P1] Reached barrier 1
[P3] Reached barrier 1
[P2] Reached barrier 1
[P5] Reached barrier 1
[P4] Reached barrier 1
--- All processes passed barrier 1 ---

[P2] Reached barrier 2
[P1] Reached barrier 2
[P4] Reached barrier 2
[P3] Reached barrier 2
[P5] Reached barrier 2
--- All processes passed barrier 2 ---

[P1] Reached barrier 3
[P5] Reached barrier 3
[P3] Reached barrier 3
[P4] Reached barrier 3
[P2] Reached barrier 3
--- All processes passed barrier 3 ---

All processes synchronized correctly. PASS

Project 12: POSIX Shared Memory Ring Buffer

  • File: P12-shm-ringbuffer.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust
  • Coolness Level: Level 4 (Hardcore Tech Flex)
  • Business Potential: Level 4 (Open Core Infrastructure)
  • Difficulty: Level 4 (Expert)
  • Knowledge Area: High-Performance IPC, Lock-Free

What youโ€™ll build: A high-performance ring buffer in POSIX shared memory for producer-consumer communication between processes.

Why it teaches IPC: Shared memory is the fastest IPC, but requires careful synchronization. A ring buffer with proper memory barriers is a production pattern.

Core challenges youโ€™ll face:

  • Memory mapping โ†’ shm_open, ftruncate, mmap
  • Synchronization โ†’ Semaphores in shared memory
  • Cache coherency โ†’ Memory barriers and atomics

Real World Outcome

$ ./shm_ringbuffer_bench --buffer-size=1MB --iterations=10M

Shared Memory Ring Buffer Benchmark
Buffer: 1MB, Messages: 10 million

Producer: Writing 10M messages...
Consumer: Reading 10M messages...

Results:
  Throughput: 8.5 million msg/sec
  Bandwidth: 8.5 GB/sec
  Latency (avg): 0.12 ฮผs
  Latency (p99): 0.35 ฮผs
  Zero-copy: Yes

Comparison to pipe: 7x faster
Comparison to Unix socket: 6x faster

Project 13: System V Shared Memory Image Processor

  • File: P13-sysv-shm-images.md
  • Main Programming Language: C
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 2 (Micro-SaaS)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: Image Processing, Parallel Computing

What youโ€™ll build: An image processing pipeline where multiple worker processes share a large image in System V shared memory.

Why it teaches IPC: Large data (images, matrices) should never be copied through pipes. Shared memory lets workers operate on the same data.

Core challenges youโ€™ll face:

  • Segment sizing โ†’ shmget with large sizes
  • Work partitioning โ†’ Each worker processes a region
  • Coordination โ†’ Signaling when all workers are done

Real World Outcome

$ ./shm_image_filter input.png output.png --filter=blur --workers=4

Shared Memory Image Processor
Image: 4096x4096 (64MB)
Workers: 4
Filter: Gaussian blur

[Master] Loaded image into shared memory (shmid=54321)
[Worker 1] Processing rows 0-1023
[Worker 2] Processing rows 1024-2047
[Worker 3] Processing rows 2048-3071
[Worker 4] Processing rows 3072-4095
[Worker 2] Done (245ms)
[Worker 1] Done (251ms)
[Worker 4] Done (248ms)
[Worker 3] Done (250ms)
[Master] All workers complete, writing output

Total time: 255ms (vs 980ms single-threaded)
Speedup: 3.84x with 4 workers

Project 14: Memory-Mapped File Database

  • File: P14-mmap-database.md
  • Main Programming Language: C
  • Coolness Level: Level 4 (Hardcore Tech Flex)
  • Business Potential: Level 3 (Service & Support)
  • Difficulty: Level 4 (Expert)
  • Knowledge Area: Databases, File Systems

What youโ€™ll build: A simple embedded database using mmap() for zero-copy persistence.

Why it teaches IPC: mmap() is shared memory backed by a file. Changes persist automatically. This is how SQLite, LMDB, and other embedded databases work.

Core challenges youโ€™ll face:

  • File growth โ†’ Remapping when database grows
  • Crash consistency โ†’ msync and fsync
  • Concurrent access โ†’ Record locking + mmap

Real World Outcome

$ ./mmapdb create mydata.db --size=100MB
Database created: mydata.db (100MB)

$ ./mmapdb insert mydata.db user:1 '{"name":"Alice"}'
Inserted at offset 0

$ ./mmapdb insert mydata.db user:2 '{"name":"Bob"}'
Inserted at offset 256

$ ./mmapdb get mydata.db user:1
{"name":"Alice"}

# Kill the process abruptly
$ ./mmapdb insert mydata.db user:3 '{"name":"Charlie"}' &
$ kill -9 $!

# Data still persists (mmap wrote to file)
$ ./mmapdb get mydata.db user:3
{"name":"Charlie"}

Project 15: Lock-Free SPSC Queue

  • File: P15-lockfree-spsc.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, C++
  • Coolness Level: Level 5 (Pure Magic)
  • Business Potential: Level 4 (Open Core)
  • Difficulty: Level 5 (Master)
  • Knowledge Area: Lock-Free Programming, Memory Models

What youโ€™ll build: A single-producer single-consumer lock-free queue in shared memory using only atomic operations.

Why it teaches IPC: Lock-free programming eliminates mutex overhead but requires understanding memory ordering. This is how high-frequency trading systems work.

Core challenges youโ€™ll face:

  • Memory barriers โ†’ __atomic_thread_fence, seq_cst vs relaxed
  • False sharing โ†’ Cache line padding
  • ABA problem โ†’ Sequence numbers

Real World Outcome

$ ./lockfree_bench --iterations=100M

Lock-Free SPSC Queue Benchmark
Operations: 100 million

Lock-free queue: 45M ops/sec
Mutex-based queue: 8M ops/sec
Semaphore-based: 6M ops/sec

Speedup: 5.6x over mutex
Latency (p99): 22ns vs 180ns

Project 16: Basic RPC Calculator

  • File: P16-rpc-calculator.md
  • Main Programming Language: C
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 2 (Micro-SaaS)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: Distributed Systems, RPC

What youโ€™ll build: A calculator service using Sun RPC with rpcgen-generated stubs.

Why it teaches IPC: RPC extends IPC across network boundaries. Youโ€™ll see how rpcgen generates client stubs, server skeletons, and XDR serialization.

Core challenges youโ€™ll face:

  • rpcgen syntax โ†’ Writing .x interface files
  • XDR types โ†’ Serializing complex structures
  • portmapper โ†’ Registering and looking up services

Real World Outcome

# Define the interface (calc.x)
$ cat calc.x
program CALC_PROG {
    version CALC_VERS {
        int ADD(operands) = 1;
        int SUBTRACT(operands) = 2;
        int MULTIPLY(operands) = 3;
    } = 1;
} = 0x31230000;

# Generate stubs
$ rpcgen calc.x
# Creates: calc.h, calc_clnt.c, calc_svc.c, calc_xdr.c

# Start server
$ ./calc_server &
Registered with portmapper: program 0x31230000, version 1

# Run client
$ ./calc_client localhost add 5 3
Result: 8

$ ./calc_client localhost multiply 7 6
Result: 42

# Query portmapper
$ rpcinfo -p localhost | grep 31230000
    100000    4   tcp    111  portmapper
0x31230000    1   tcp  45678  calc

Project 17: RPC with Authentication

  • File: P17-rpc-auth.md
  • Main Programming Language: C
  • Coolness Level: Level 3 (Genuinely Clever)
  • Business Potential: Level 3 (Service & Support)
  • Difficulty: Level 3 (Advanced)
  • Knowledge Area: Security, RPC

What youโ€™ll build: Extend the RPC calculator with AUTH_SYS (Unix) and AUTH_DES authentication.

Why it teaches IPC: Real RPC services need authentication. Youโ€™ll see how Sun RPCโ€™s pluggable authentication works.


Project 18: Distributed Key-Value Store with RPC

  • File: P18-rpc-kvstore.md
  • Main Programming Language: C
  • Coolness Level: Level 4 (Hardcore Tech Flex)
  • Business Potential: Level 4 (Open Core)
  • Difficulty: Level 4 (Expert)
  • Knowledge Area: Distributed Systems, Storage

What youโ€™ll build: A multi-server key-value store using RPC for client-server and server-server communication.

Why it teaches IPC: This combines everything: RPC for remote calls, shared memory for local caching, semaphores for coordination.


Real World Outcome

# Start 3 server replicas
$ ./kv_server --id=1 --port=9001 --peers=localhost:9002,localhost:9003 &
$ ./kv_server --id=2 --port=9002 --peers=localhost:9001,localhost:9003 &
$ ./kv_server --id=3 --port=9003 --peers=localhost:9001,localhost:9002 &

# Client connects to any server
$ ./kv_client --server=localhost:9001 put mykey "Hello World"
OK (replicated to 3 nodes)

$ ./kv_client --server=localhost:9002 get mykey
Hello World

# Kill a server, data still available
$ kill %1
$ ./kv_client --server=localhost:9002 get mykey
Hello World

Project Comparison Table

Project Difficulty Time Depth of Understanding Fun Factor
1. Shell Pipeline Level 2 Weekend High โ˜…โ˜…โ˜…โ˜…โ˜†
2. FIFO Client-Server Level 2 Weekend Medium โ˜…โ˜…โ˜…โ˜†โ˜†
3. Implement popen Level 3 1 Week High โ˜…โ˜…โ˜…โ˜…โ˜†
4. POSIX MQ Dispatcher Level 3 1 Week High โ˜…โ˜…โ˜…โ˜…โ˜†
5. System V MQ Server Level 3 1 Week High โ˜…โ˜…โ˜…โ˜†โ˜†
6. MQ Benchmark Level 2 Weekend Medium โ˜…โ˜…โ˜…โ˜†โ˜†
7. Producer-Consumer Level 3 1 Week Very High โ˜…โ˜…โ˜…โ˜…โ˜…
8. RWLock Implementation Level 4 2 Weeks Very High โ˜…โ˜…โ˜…โ˜…โ˜†
9. Record Locking DB Level 3 1 Week High โ˜…โ˜…โ˜…โ˜†โ˜†
10. Semaphore Pool Level 3 1 Week High โ˜…โ˜…โ˜…โ˜…โ˜†
11. System V Barrier Level 3 1 Week High โ˜…โ˜…โ˜…โ˜†โ˜†
12. SHM Ring Buffer Level 4 2 Weeks Very High โ˜…โ˜…โ˜…โ˜…โ˜…
13. SHM Image Processor Level 3 1 Week Medium โ˜…โ˜…โ˜…โ˜…โ˜†
14. mmap Database Level 4 2 Weeks Very High โ˜…โ˜…โ˜…โ˜…โ˜…
15. Lock-Free Queue Level 5 3 Weeks Extreme โ˜…โ˜…โ˜…โ˜…โ˜…
16. RPC Calculator Level 3 1 Week High โ˜…โ˜…โ˜…โ˜†โ˜†
17. RPC Authentication Level 3 1 Week Medium โ˜…โ˜…โ˜…โ˜†โ˜†
18. Distributed KV Store Level 4 3 Weeks Very High โ˜…โ˜…โ˜…โ˜…โ˜…

Recommendation

If you are new to IPC: Start with Project 1 (Shell Pipeline). It uses only pipes and fork(), the most fundamental IPC primitives.

If you are a systems programmer: Start with Project 7 (Producer-Consumer). Mutexes and condition variables are the foundation of all concurrent code.

If you want high performance: Focus on Projects 12-15 (Shared Memory). This is where the real speed gains happen.

If you need distributed systems: Start with Projects 16-18 (RPC). Understanding Sun RPC helps you appreciate modern alternatives like gRPC.


Final Overall Project: Unix IPC Integration Test Suite

The Goal: Combine all your implementations into a comprehensive IPC benchmark and test harness.

  1. Create a unified library with all IPC mechanisms
  2. Build a benchmark CLI that compares them all
  3. Add stress tests that verify correctness under load
  4. Generate reports with performance comparisons
  5. Document the trade-offs you discovered

Success Criteria: You can run ./ipc_suite benchmark --all and get a complete comparison of every IPC mechanism, with correctness verification and performance metrics.


From Learning to Production: Whatโ€™s Next?

After completing these projects, youโ€™ve built educational implementations. Hereโ€™s how to transition to production-grade systems:

What You Built vs. What Production Needs

Your Project Production Equivalent Gap to Fill
Shared Memory Ring Buffer LMAX Disruptor, io_uring Lock-free MPMC, batch operations
Message Queue Dispatcher RabbitMQ, ZeroMQ Persistence, clustering, acknowledgments
RPC Calculator gRPC, Apache Thrift HTTP/2, streaming, load balancing
mmap Database LMDB, SQLite B-trees, ACID transactions, crash recovery

Skills You Now Have

You can confidently discuss:

  • The trade-offs between POSIX and System V IPC
  • When to use shared memory vs message passing
  • How to avoid deadlocks and race conditions
  • Memory ordering and lock-free programming basics

You can read source code of:

  • PostgreSQL (shared buffers, semaphores)
  • Redis (client-server, fork for persistence)
  • Nginx (worker processes, shared memory)
  • ZeroMQ (message queues, patterns)

You can architect:

  • Multi-process servers with shared state
  • High-performance data pipelines
  • Distributed systems with RPC

1. Contribute to Open Source:

  • libuv: Node.jsโ€™s cross-platform IPC layer
  • ZeroMQ: Modern message queue patterns

2. Build Production Systems:

  • Replace Sun RPC with gRPC in Project 18
  • Add persistence to your message queue
  • Implement a proper B-tree for the mmap database

3. Get Certified:

  • Linux Foundation Certified System Administrator (LFCS)
  • Linux Foundation Certified Engineer (LFCE)

Career Paths Unlocked

With this knowledge, you can pursue:

  • Systems Programming (databases, file systems)
  • Infrastructure Engineering (containers, orchestration)
  • Performance Engineering (low-latency trading, games)
  • Distributed Systems (cloud platforms, data pipelines)

Summary

This learning path covers Unix IPC through 18 hands-on projects.

# Project Name Main Language Difficulty Time Estimate
1 Shell Pipeline Executor C Level 2 Weekend
2 FIFO Client-Server C Level 2 Weekend
3 Implement popen C Level 3 1 Week
4 POSIX MQ Dispatcher C Level 3 1 Week
5 System V MQ Server C Level 3 1 Week
6 MQ Benchmark C Level 2 Weekend
7 Producer-Consumer C Level 3 1 Week
8 RWLock Implementation C Level 4 2 Weeks
9 Record Locking DB C Level 3 1 Week
10 Semaphore Pool C Level 3 1 Week
11 System V Barrier C Level 3 1 Week
12 SHM Ring Buffer C Level 4 2 Weeks
13 SHM Image Processor C Level 3 1 Week
14 mmap Database C Level 4 2 Weeks
15 Lock-Free Queue C Level 5 3 Weeks
16 RPC Calculator C Level 3 1 Week
17 RPC Authentication C Level 3 1 Week
18 Distributed KV Store C Level 4 3 Weeks

Expected Outcomes

After completing these projects, you will:

  • Understand every IPC mechanism in Unix at the system call level
  • Know exactly when to use pipes vs message queues vs shared memory
  • Be able to debug race conditions and deadlocks systematically
  • Have performance intuition for each IPC mechanism
  • Be prepared for systems programming interviews at any company

Youโ€™ll have built a complete IPC toolkit from first principles, covering everything in Stevensโ€™ Unix Network Programming Volume 2.


Additional Resources & References

Standards & Specifications

Online Guides

Books

IPC Specific:

  • โ€œUnix Network Programming Volume 2โ€ by W. Richard Stevens (Prentice Hall) - THE definitive reference
  • โ€œThe Linux Programming Interfaceโ€ by Michael Kerrisk (No Starch Press) - Modern Linux-specific coverage

Concurrency:

  • โ€œProgramming with POSIX Threadsโ€ by David Butenhof - Pthreads bible
  • โ€œRust Atomics and Locksโ€ by Mara Bos - Modern take on lock-free programming

Foundations (from your library):

  • โ€œAdvanced Programming in the UNIX Environmentโ€ by Stevens & Rago - System programming context
  • โ€œOperating Systems: Three Easy Piecesโ€ by Arpaci-Dusseau - Theoretical foundation
  • โ€œComputer Systems: A Programmerโ€™s Perspectiveโ€ by Bryant & Oโ€™Hallaron - Understanding the machine

This guide covers every IPC mechanism from W. Richard Stevensโ€™ โ€œUnix Network Programming Volume 2: Interprocess Communications.โ€ Work through all 18 projects to achieve complete mastery of Unix IPC.