The Process Abstraction & API

A process as a running program with its own virtual CPU and memory — fork, exec, wait, and exit on Unix; how shells chain commands; why zombies and orphans happen.

2/5Overview: 25m

Process = running program + OS state

A process is the OS's unit of CPU virtualization: a program counter, register file, virtual address space, open file descriptors, signal disposition, and metadata (PID, parent, exit status). The kernel schedules processes (really threads), not source files.

The Unix process API

SyscallWhat it doesProduction relevance
fork()Clone current process (CoW address space)Shell pipelines, prefork workers
execve()Replace address space with a new binaryEvery systemd service start
wait() / waitpid()Reap child exit statusPrevents zombies
exit()Terminate, notify parentClean shutdown vs _exit on failure

Typical pattern: fork → child execves target binary → parent waits. The shell does this for every command.

Process states worth knowing

  • Running / Ready — on CPU or in the run queue.
  • Blocked (S) — waiting on I/O, lock, or sleep.
  • Uninterruptible (D) — stuck in kernel I/O; kill -9 won't help.
  • Zombie (Z) — exited but parent hasn't reaped; harmless unless parent leaks thousands.
  • Orphan — parent died; adopted by PID 1 (init/systemd).

Senior-level signal

"Why is my container's PID 1 not reaping zombies?" is a classic production bug — if PID 1 doesn't call wait, zombie count climbs until the namespace hits pid_max. Init systems and proper container entrypoints must reap children.

Where this goes next

Context Switching & Scheduling Basics explains how the kernel decides which process runs next — and what happens to all that saved state when it switches.

Further Reading

Hands-On Tasks (Optional)

Low-setup exercises on your local machine. No autograding — the goal is to build intuition, not pass a test.

  • Observe fork() with a tiny C program or Python os.fork()

    Write (or run) a 10-line program that calls fork() and prints PID on parent and child. Run twice and note PIDs differ but parent/child relationship holds. If uncomfortable with C, use `python3 -c "import os; print('before', os.getpid()); os.fork(); print('after', os.getpid())"`.

    20m