Part 2 — Processes, threads, and the CPU
Part 1 established that the OS multiplexes hardware among programs that each believe they own it. This part is the first and biggest instance of that lie made concrete: what a process actually is, how one CPU is shared between many of them, and where a thread fits into that picture.
Chapter 4 — What a process actually is
In one sentence
A process is a running program plus everything the OS tracks to keep it isolated and resumable: its own memory space, its own file descriptors, and a record of exactly where it is in its own execution.
Why this matters
"How many processes can this server handle" is one of the oldest, most practical capacity-planning questions in computing, and answering it well requires knowing what a process actually costs.
How it actually works
A process is NOT just "the code running." The kernel maintains a
whole record for it (a "process control block") including:
PID a unique process ID number
MEMORY MAP its private virtual address space (Chapter 10)
FILE
DESCRIPTORS a table of everything it has open (files, sockets,
pipes -- Chapter 23)
REGISTERS the CPU's exact state when this process was last
paused, so it can resume perfectly
PARENT PID who created it (for wait()/zombies, Chapter 3)
PERMISSIONS which user it runs as, what it's allowed to do
SIGNAL HANDLERS custom behaviour for signals it's registered for
(Chapter 20)
Creating a process is NOT CHEAP: the kernel has to allocate and set up
all of the above. This cost is exactly why the industry has spent
decades inventing lighter-weight alternatives -- threads (Chapter 7),
thread pools, event loops, and eventually containers (Phase 3), all of
which exist partly to avoid paying the full cost of a brand-new
process for every unit of work.
Real-world example
The "C10K problem" (a name coined by Dan Kegel in a widely-read 1999
essay) asked: can a single server handle 10,000 CONCURRENT
connections? The traditional answer at the time -- Apache's "prefork"
model, spawning one whole OS PROCESS per incoming connection -- hit a
hard wall well before 10,000, because each process's memory
footprint and scheduling overhead (Chapter 8) added up brutally at
that scale.
This is precisely why Igor Sysoev built NGINX (first released 2004),
using an EVENT-DRIVEN model that handles thousands of connections
with a small, FIXED number of worker processes instead of one per
connection -- the same instinct as this chapter's "processes aren't
free" lesson, engineered into one of the world's most-used web
servers. Today's async/event-loop frameworks (Node.js, async Python,
Go's goroutines) all descend from the same realisation: for
high-concurrency I/O-bound work, a process (or even a thread) per
task is too expensive.
Try it yourself
# See what the kernel actually tracks for one process
echo $$ # your shell's own PID
cat /proc/$$/status | head -20 # the kernel's own record of it
ls /proc/$$/fd/ # its open file descriptors right now
# Estimate the real cost of a process on your machine
ps aux | awk '{sum+=$6} END {print sum/1024 " MB total RSS across all processes"}'
Common mistakes
- Thinking a process is "just code." The kernel-tracked state (memory map, file descriptors, permissions) is just as much "the process" as the code itself.
- Assuming more processes is always fine. Each one has real memory and scheduling overhead; "spawn a process per request" doesn't scale the way "spawn a process per user session, ever" does.
- Confusing PID reuse with process identity. PIDs get RECYCLED after a process exits — a PID you saw an hour ago may belong to a totally different process now.
Check yourself
- Name four things the kernel tracks for a process, beyond "the code."
- Why is creating a process more expensive than, say, calling a function?
- What problem was NGINX's event-driven architecture specifically designed to solve?
(Answers: Appendix E.)
Further reading
- Essay: "The C10K problem," Dan Kegel (
kegel.com/c10k.html) — the original, still-relevant essay that shaped a generation of server design. - Book (free): OSTEP, "Processes" chapter.
- Reference:
man 5 proc— the full documentation of everything under/proc/<pid>/.