Memory Management — Paging & Virtual Memory

Every process believes it has the entire address space to itself. This is a lie — a very useful lie. The OS and hardware work together to create the illusion of virtual memory, mapping each process's addresses to wherever they actually live in physical RAM.

The Problem: Multiple Processes Need Memory

If processes used physical addresses directly:

  • Process A at 0x0–0x4000, Process B at 0x4000–0x8000 — they'd need to know each other's locations at compile time
  • A buggy process could overwrite another's memory
  • You couldn't run more programs than RAM can hold

Virtual memory solves all three.

Logical vs Physical Address

  • Logical (virtual) address: what the program uses (0x1234 in process A's view)
  • Physical address: the actual RAM address (0xABCD where it really lives)

The Memory Management Unit (MMU) — hardware inside the CPU — translates every logical address to a physical one on every memory access.

Paging

The OS divides:

  • Virtual address space into fixed-size pages (typically 4 KB)
  • Physical RAM into equal-size frames

The page table (per process) maps page numbers → frame numbers.

Virtual address (32-bit)Page number20 bitsOffset12 bits3112 110Page table lookup:page 5frame 103Physical address = (103 × 4096) + offset

Page Table Entry (PTE) Fields

BitMeaning
ValidIs this page currently in RAM?
DirtyHas this page been written to?
ReferencedHas this page been accessed recently?
ProtectionRead / Write / Execute permissions
Frame numberWhere in RAM this page lives

The TLB — Translation Lookaside Buffer

Translating every address via the page table would be brutally slow (2 memory accesses per instruction). The TLB is a small, fast cache of recent page-to-frame translations inside the CPU.

CPU issues addressCheck TLBHITGet frame,done (>95%)MISSWalk page tableLoad result into TLB

TLBs hold 64–1024 entries. Because programs have temporal and spatial locality, hit rates are very high.

Page Faults

When a process accesses a page whose valid bit is 0 (not in RAM), the CPU raises a page fault:

  1. OS traps the fault
  2. Finds the page on disk (in the swap space)
  3. Selects a free frame (evicting a page if RAM is full)
  4. Loads the page into that frame
  5. Updates the page table entry
  6. Resumes the faulting instruction

This is slow (disk access = millions of CPU cycles), so minimising page faults is critical.

Virtual Memory — More Memory Than You Have

Virtual memory allows the total size of all processes to exceed physical RAM by keeping rarely used pages on disk.

text
Loading...

Page Replacement Algorithms

When RAM is full and a new page must be loaded, the OS must evict an existing page. Which one?

FIFO (First-In, First-Out)

Evict the page that has been in RAM the longest.

Suffers from Belady's anomaly: more frames can cause more page faults (counterintuitive!).

Optimal (OPT)

Evict the page that won't be used for the longest time in the future. Theoretically perfect but requires future knowledge — only useful as a benchmark.

LRU (Least Recently Used)

Evict the page that was used least recently. Excellent in practice — approximates OPT.

Approximate LRU (clock algorithm):

  • Each page has a reference bit, set to 1 on access
  • A clock hand sweeps pages; if bit=1, clear it and move on; if bit=0, evict it
text
Loading...

Memory-Mapped Files

The OS can map a file directly into a process's address space. Reading and writing the virtual addresses reads/writes the file — no explicit read()/write() calls needed.

python
Loading...

Segmentation

An alternative to paging: divide the address space into variable-size segments (code, stack, heap, data). Each segment has a base address and a limit.

Modern OSes use paging as the primary mechanism but expose a segmented view at the programming model level (stack, heap, text, data sections).

Key Takeaways

  • Virtual addresses are an illusion — the MMU maps them to physical frames on every access
  • Paging uses fixed-size pages to avoid fragmentation and enable sparse address spaces
  • The TLB caches recent translations; without it, virtual memory would be too slow
  • Page faults are expensive — keep the working set in RAM
  • LRU page replacement approximates optimal performance; the clock algorithm implements it cheaply