Chapter 11 — Paging, page faults, and the TLB
In one sentence
Physical memory is managed in fixed-size chunks called pages, and when a process touches a virtual address that isn't currently mapped to a physical page, the CPU raises a page fault — which the kernel may resolve instantly, slowly (by reading from disk), or fatally (by killing the process).
Why this matters
"Why did my program's first request feel slow, but the second one was fast" and "why does swapping make everything grind to a halt" are both, directly, page-fault stories.
How it actually works
PAGES: physical RAM and virtual address space are both divided into
fixed-size chunks -- PAGES -- commonly 4KB on Linux/x86 (larger "huge
pages," 2MB or 1GB, exist for specific performance-sensitive
workloads). The kernel's PAGE TABLE records, for every virtual page a
process uses, WHERE (or whether) it's currently backed by a physical
page.
A PAGE FAULT happens when a process accesses a virtual address whose
page ISN'T currently mapped to physical RAM. There are several very
different flavours:
MINOR FAULT (cheap, common, totally normal)
the page exists somewhere accessible but isn't yet mapped into
THIS process (e.g. a shared library page another process already
loaded) -- the kernel just updates the mapping. Fast, invisible.
MAJOR FAULT (expensive)
the data has to be read FROM DISK -- either it's part of a
memory-mapped file not yet loaded, or (the painful case) it was
previously SWAPPED OUT to disk to free up RAM for something else,
and now has to be swapped back IN. This is orders of magnitude
slower than RAM access (Chapter 12's hierarchy).
SEGMENTATION FAULT (fatal)
the process touched a virtual address that ISN'T VALID AT ALL for
it -- not "not yet loaded," but genuinely not part of its address
space (a wild pointer, a buffer overrun). The kernel delivers
SIGSEGV (Chapter 20) and the process usually dies. This is the
infamous "segfault."
THE TLB (Translation Lookaside Buffer) is a small, very fast CACHE,
right on the CPU, of recent virtual-to-physical translations -- so the
full page-table lookup (itself potentially several memory accesses)
doesn't have to happen on EVERY single memory access. A "TLB miss"
means falling back to the slower, full page-table walk.
Real-world example
THRASHING is the well-documented, classic failure mode this chapter's
mechanism produces under memory pressure: when a system's actively-
used memory (its "working set") exceeds available RAM, the kernel
starts SWAPPING pages out to disk to make room, and swapping others
BACK IN as they're needed -- generating a storm of expensive MAJOR
PAGE FAULTS. If the working set is large enough relative to RAM, the
system can spend almost ALL of its time swapping pages in and out
and almost NONE of its time doing actual work -- CPU usage looks
deceptively LOW (everything is stuck waiting on disk I/O, D-state,
Chapter 5) while the system feels completely unresponsive. This
remains one of the most common real production incidents reported in
SRE/ops communities: "the server isn't doing much CPU-wise but is
totally unresponsive" is, very often, a thrashing system -- and it's
exactly why cloud providers and Kubernetes (Chapter 58) generally
prefer to KILL a process/pod that's exceeding its memory budget
(Chapter 13's OOM killer) rather than let it swap into oblivion.
Try it yourself
# See page fault counts for a command -- minor vs major
/usr/bin/time -v ls / 2>&1 | grep -i "page faults"
# (on some systems: /usr/bin/time -v cat /proc/self/maps 2>&1 | grep fault)
# Watch major faults spike under real memory pressure (careful, only on
# your disposable VM -- this deliberately stresses memory)
free -h # baseline
vmstat 1 5 # watch the "si"/"so" (swap in/out) columns
# See your system's page size
getconf PAGE_SIZE # almost always 4096 on x86_64 Linux
Common mistakes
- Treating all page faults as bad. Minor faults are constant, cheap, and completely normal — only SUSTAINED major faults (especially swap activity) are a red flag.
- Confusing a segmentation fault with "the program is out of memory." A segfault means an INVALID memory access (a bug), not memory exhaustion — those are different failures with different causes (Chapter 13 covers actual memory exhaustion).
- Assuming more swap space fixes a thrashing system. It usually just makes the thrashing last longer before the system becomes truly unusable — the real fix is more RAM or a smaller working set.
Check yourself
- What's the difference between a minor page fault and a major page fault?
- What does the TLB cache, and why does it exist?
- What is thrashing, and why does a thrashing system often show LOW CPU usage despite being unresponsive?
Further reading
- Book (free): OSTEP, "Paging" and "Swapping" chapters.
- Reference:
man 2 mmap,man 8 vmstat. - Article: search "Linux memory thrashing troubleshooting" for current, concrete production writeups.