Memory Management | Computer Science
flowchart TD A[5_Memory Management] --> B[Key Concepts] A --> C[Core Principles] A --> D[Practical Applications] B --> E[Fundamental definitions] C --> F[Design patterns] D --> G[Real-world usage]Intuition
Section titled “Intuition”Memory management answers: how do you give every process its own address space while sharing limited physical RAM? The solution is virtual memory — each process sees a private, contiguous address space that maps to scattered physical pages. This provides isolation (one process can’t corrupt another) and enables overcommitment (using more total memory than physically available).
Paging intuition: Physical memory is divided into fixed-size frames; virtual memory into pages of the same size. A page table maps each virtual page to a physical frame. When a process accesses a page not currently in RAM, a page fault occurs and the OS loads it from disk. This is slow (milliseconds vs nanoseconds for RAM), so the OS tries to keep frequently-used pages in memory.
Replacement algorithm intuition: When physical memory is full, the OS must evict a page. LRU (Least Recently Used) approximates the principle that recently-used pages will be used again. The working set model tracks which pages a process actively uses — if its working set doesn’t fit in RAM, the process thrashes (spends more time paging than computing).
5.1 Contiguous Memory Allocation
Section titled “5.1 Contiguous Memory Allocation”Fixed partitioning. Memory divided into fixed-size partitions at boot. Internal fragmentation.
Variable partitioning. Partitions created dynamically. External fragmentation.
Allocation strategies:
| Strategy | Description |
|---|---|
| First-fit | Allocate the first hole large enough |
| Best-fit | Allocate the smallest hole large enough |
| Worst-fit | Allocate the largest hole |
| Next-fit | Continue searching from the last allocation |
Theorem 5.1. First-fit and best-fit have roughly equivalent utilisation; first-fit is faster.
5.2 Paging
Section titled “5.2 Paging”Divide physical memory into fixed-size frames and logical memory into same-size pages. A page table maps page numbers to frame numbers.
Where is the frame number for page and is the frame size.
Page table entry fields:
| Field | Purpose |
|---|---|
| Frame number | Physical frame containing this page |
| Valid bit | Page is in memory (1) or not (0) |
| Dirty bit | Page has been modified |
| Reference bit | Page accessed recently |
| Protection | Read/write/execute permissions |
Multi-level page tables. A single page table for a 64-bit address space is infeasible. A Two-level scheme uses a page directory indexed by the outer page number, pointing to inner Page tables:
X86-64 with 48-bit virtual addresses uses four-level page tables.
Inverted page table. One entry per physical frame (not per virtual page). Reduces memory Overhead but makes searching for a specific virtual page expensive; solved by hashing.
5.3 Segmentation
Section titled “5.3 Segmentation”Segments divide the address space into logical units (code, data, stack, heap). Each segment has a base and limit:
Advantages: Reflects program structure; supports sharing individual segments. Disadvantages: External fragmentation (variable-size segments).
Worked Example 5.1 — Segmented Address Translation
A process has three segments with the following segment table:
| Segment | Base | Limit |
|---|---|---|
| Code | 4096 | 2048 |
| Data | 12288 | 4096 |
| Stack | 20480 | 2048 |
Translate logical address (segment = 1, offset = 1500):
- Check: offset limit . Valid.
- Physical address = base + offset = .
Translate (segment = 2, offset = 2500):
- Check: offset limit . Invalid. Segmentation fault.
5.4 Segmented Paging
Section titled “5.4 Segmented Paging”Combine segmentation and paging: the segment offset is divided into page number and page offset.
Used by x86 (segmentation + paging).
5.5 Virtual Memory
Section titled “5.5 Virtual Memory”Virtual memory allows processes to use more memory than physically available by keeping only active Pages in RAM; the rest reside on disk (swap space).
Demand paging. Pages loaded on access, not at process start.
Page fault handling:
- CPU generates logical address; page table entry has valid bit = 0.
- Trap to OS page fault handler.
- Find a free frame (possibly evicting a victim page).
- Read the page from disk into the frame.
- Update page table entry (valid bit = 1, frame number).
- Restart the faulting instruction.
Effective access time (EAT):
Where = page fault rate, = memory access time, = page fault service Time.
For , ns, ms:
This is roughly slower than pure memory access, illustrating why a low page fault rate Is critical.
5.6 Translation Lookaside Buffer (TLB)
Section titled “5.6 Translation Lookaside Buffer (TLB)”A TLB is a hardware cache of recently used page table entries, avoiding an extra memory access Per translation.
Where is the TLB hit ratio.
For , ns, ns:
TLB coherence. When the OS modifies a page table entry, it must invalidate the corresponding TLB entry. On x86-64: invlpg for single-entry invalidation, or reload CR3 to flush the entire TLB.
Worked Example 5.2 — TLB + Page Fault EAT Calculation
A system with TLB access time = 2 ns, memory access time = 100 ns, page fault service time = 8 ms, TLB hit ratio = 0.80, and page fault rate = 0.0005.
Case 1: TLB hit, no page fault (): Time = ns.
Case 2: TLB miss, no page fault (): Time = ns.
Case 3: Page fault (): Time = ns.
This is roughly slower than pure memory access, driven almost entirely by the page fault Component.
5.7 Page Replacement Algorithms
Section titled “5.7 Page Replacement Algorithms”When physical memory is full, a victim page must be selected for eviction.
Optimal (OPT/MIN). Replace the page not used for the longest time in the future. Provably Optimal but requires future knowledge; used only as a benchmark.
Theorem 5.2 (Belady”s Optimality). OPT yields the fewest page faults for any reference string.
Proof. If OPT replaces page (used furthest in future) and another algorithm replaces page (used sooner), the other algorithm faults at least once more by the time is next Referenced.
First-In, First-Out (FIFO). Replace the oldest page. Simple but may evict heavily used pages. Suffers from Belady’s anomaly: increasing frames can increase faults.
Example of Belady’s anomaly. Reference string: 1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5. With 3 Frames: 9 faults. With 4 frames: 10 faults.
Least Recently Used (LRU). Replace the page not used for the longest time. Approximates OPT Well. Does not suffer from Belady’s anomaly.
Theorem 5.3. LRU is a stack algorithm: the set of pages in frames is a superset of the Set in frames, for any reference string.
Proof. When adding a frame, LRU keeps the most recently used pages (same as before) plus the New frame. No page in the -frame set can be more recently used than a page outside it, so the set must contain the -frame set.
Clock (Second Chance). Pages in a circular list with a reference bit. On replacement:
- If reference bit is 0, replace the page.
- If reference bit is 1, clear it and advance.
Approximates LRU with per operation.
LFU (Least Frequently Used). Replace the page with the smallest access count. May fail to adapt To changing access patterns.
Approximating LRU in practice. Most OSes use a variant of Clock. Linux uses an LRU-like Approximation with active and inactive lists: pages on the active list are protected; pages Not accessed are demoted to the inactive list; eviction targets the inactive list.
Worked Example 5.3 — Optimal Page Replacement
Reference string: 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1. Three frames.
| Ref | Frame 1 | Frame 2 | Frame 3 | Fault? | Victim |
|---|---|---|---|---|---|
| 7 | 7 | Yes | — | ||
| 0 | 7 | 0 | Yes | — | |
| 1 | 7 | 0 | 1 | Yes | — |
| 2 | 2 | 0 | 1 | Yes | 7 (used at 18) |
| 0 | 2 | 0 | 1 | No | — |
| 3 | 2 | 3 | 1 | Yes | 0 (used at 10) |
| 0 | 2 | 3 | 0 | Yes | 1 (used at 14) |
| 4 | 2 | 4 | 0 | Yes | 3 (used at 11) |
| 2 | 2 | 4 | 0 | No | — |
| 3 | 3 | 4 | 0 | Yes | 2 (used at 13) |
| 0 | 3 | 4 | 0 | No | — |
| 3 | 3 | 4 | 0 | No | — |
| 2 | 2 | 4 | 0 | Yes | 3 (used at 11, already past) |
| 1 | 2 | 1 | 0 | Yes | 4 (used at ) |
| 2 | 2 | 1 | 0 | No | — |
| 0 | 2 | 1 | 0 | No | — |
| 1 | 2 | 1 | 0 | No | — |
| 7 | 7 | 1 | 0 | Yes | 2 (used at 13, already past) |
| 0 | 7 | 1 | 0 | No | — |
| 1 | 7 | 1 | 0 | No | — |
Total page faults: 9. This is the theoretical minimum.
Worked Example 5.4 — LRU Page Replacement
Same reference string, three frames. LRU replaces the page whose last use was furthest in the past.
| Ref | F1 | F2 | F3 | Fault? | Victim (least recent) |
|---|---|---|---|---|---|
| 7 | 7 | Yes | — | ||
| 0 | 7 | 0 | Yes | — | |
| 1 | 7 | 0 | 1 | Yes | — |
| 2 | 2 | 0 | 1 | Yes | 7 |
| 0 | 2 | 0 | 1 | No | — |
| 3 | 2 | 3 | 1 | Yes | 0 |
| 0 | 0 | 3 | 1 | Yes | 2 |
| 4 | 0 | 4 | 1 | Yes | 3 |
| 2 | 0 | 4 | 2 | Yes | 1 |
| 3 | 3 | 4 | 2 | Yes | 0 |
| 0 | 3 | 0 | 2 | Yes | 4 |
| 3 | 3 | 0 | 2 | No | — |
| 2 | 3 | 0 | 2 | No | — |
| 1 | 1 | 0 | 2 | Yes | 3 |
| 2 | 1 | 0 | 2 | No | — |
| 0 | 1 | 0 | 2 | No | — |
| 1 | 1 | 0 | 2 | No | — |
| 7 | 1 | 0 | 7 | Yes | 2 |
| 0 | 1 | 0 | 7 | No | — |
| 1 | 1 | 0 | 7 | No | — |
Total page faults: 12. LRU produces 33% more faults than optimal, but does not require future Knowledge.
Worked Example 5.5 — Clock (Second Chance) Replacement
Same reference string, three frames. Clock hand starts at frame 0. R = reference bit.
| Ref | State (R bits) | Fault? | Action |
|---|---|---|---|
| 7 | [7,R] [-] [-] | Yes | Load 7 into F0 |
| 0 | [7,R] [0,R] [-] | Yes | Load 0 into F1 |
| 1 | [7,R] [0,R] [1,R] | Yes | Load 1 into F2 |
| 2 | [2,R] [0,R] [1,R] | Yes | F0: R=1, clear, advance; F1: R=1, clear, advance; F2: R=1, clear, advance; F0: R=0, replace with 2 |
| 0 | [2,R] [0,R] [1,R] | No | Set R on F1 |
| 3 | [2,R] [3,R] [1,R] | Yes | F0: R=1, clear, advance; F1: R=1, clear, advance; F2: R=1, clear, advance; F0: R=0, replace with 3 |
| 0 | [0,R] [3,R] [1,R] | Yes | F0: R=0, replace with 0 |
| 4 | [0,R] [4,R] [1,R] | Yes | F0: R=1, clear, advance; F1: R=0, replace with 4 |
| 2 | [2,R] [4,R] [1,R] | Yes | F0: R=0, replace with 2 |
| 3 | [2,R] [3,R] [1,R] | Yes | F0: R=1, clear, advance; F1: R=0, replace with 3 |
| 0 | [0,R] [3,R] [1,R] | Yes | F0: R=0, replace with 0 |
| 3 | [0,R] [3,R] [1,R] | No | Set R on F1 |
| 2 | [2,R] [3,R] [1,R] | Yes | F0: R=0, replace with 2 |
| 1 | [2,R] [3,R] [1,R] | No | Set R on F2 |
| 2 | [2,R] [3,R] [1,R] | No | Set R on F0 |
| 0 | [2,R] [0,R] [1,R] | Yes | F0: R=1, clear, advance; F1: R=1, clear, advance; F2: R=1, clear, advance; F0: R=0, replace with 0 |
| 1 | [0,R] [1,R] [1,R] | No | Set R on F2 |
| 7 | [7,R] [1,R] [1,R] | Yes | F0: R=0, replace with 7 |
| 0 | [7,R] [0,R] [1,R] | Yes | F0: R=1, clear, advance; F1: R=0, replace with 0 |
| 1 | [7,R] [0,R] [1,R] | No | Set R on F2 |
Total page faults: 15. Clock performs worse than LRU here but requires only per operation And no global ordering of references.
Cross-References
Section titled “Cross-References”Process Management — Each process has its own address space managed by the operating system’s memory management subsystem.
Virtualization — Memory virtualization extends basic memory management to support multiple virtual machines.
File Systems — Memory-mapped files blur the boundary between memory management and file system operations.
Common Mistakes
Section titled “Common Mistakes”Confusing virtual addresses with physical addresses. Processes always see virtual addresses. The MMU translates them to physical addresses using page tables. A virtual address 0x7fff0000 in one process maps to a completely different physical frame than the same virtual address in another process.
Believing LRU is always optimal. LRU is a practical approximation but not optimal for all access patterns. Sequential scans of large files can evict the entire working set from memory (Bélády’s anomaly for FIFO, and LRU thrashing under scan patterns). Optimal replacement is theoretically best but requires future knowledge.
Confusing thrashing with poor algorithm choice. Thrashing occurs when the total working set of all processes exceeds physical memory, not because a page replacement algorithm is “bad.” Adding more frames or reducing the number of concurrent processes is the correct fix, not switching algorithms.
Ignoring the cost of page faults. A single page fault requires a disk access (milliseconds), which is orders of magnitude slower than a memory access (nanoseconds). Code that triggers frequent page faults — e.g., iterating over a large array with poor locality — will be dramatically slower than code with good spatial and temporal locality.
Assuming
fork()is expensive without COW. Without copy-on-write,fork()would need to copy every page of the parent’s address space, making it O(n) in the number of pages. With COW, only modified pages are copied, makingfork()followed byexec()extremely cheap since the child’s pages are never actually copied.