Coursify

Operating System

Paging: Eliminating External Fragmentation Through Non-Contiguous Allocation

65 mins

Understand how paging solves the external fragmentation problem by breaking both logical and physical memory into fixed-size units, and master the hardware mechanisms — page tables and the TLB — that make address translation fast enough for real-world use.

Learning Goals

  • Explain the concept of frames and pages and how paging eliminates external fragmentation.
  • Split a logical address into page number and offset, perform a page table lookup, and compute the resulting physical address.
  • Calculate Effective Access Time (EAT) given a TLB hit ratio and memory access time.
  • Explain the role of the valid/invalid bit in memory protection.

The Problem Paging Solves

Recall from Section 1 that contiguous memory allocation suffers from external fragmentation — after many allocations and deallocations, free memory is split into many small holes, none of which is large enough for new processes even though the total free memory might be sufficient.

The root cause is the requirement that a process must occupy a single, contiguous block of physical memory. Paging eliminates this requirement entirely.


The Core Idea: Pages and Frames

Paging divides both logical and physical memory into fixed-size blocks:

  • Frame: A fixed-size block of physical memory (RAM). The OS tracks which frames are free and which are occupied.
  • Page: A fixed-size block of a process's logical address space. Every page is the same size as a frame.

The crucial freedom: A process's pages can be placed in any available frames — they do not have to be adjacent in physical memory. Page 0 of a process might be in frame 5; page 1 might be in frame 1; page 2 might be in frame 14. They are scattered, but the process doesn't know or care.

Why external fragmentation is eliminated: Any free frame anywhere in RAM can hold any page of any process. There are no "holes" that are too small — as long as there are enough free frames in total, any process can be loaded.


Page Size: Why It's Always a Power of 2

Page size is defined by the hardware and is always a power of 2 (e.g., 512B, 4KB, 64KB). This is not arbitrary — it makes address splitting trivially fast using bit operations instead of division.

  • Typical page size: 4KB (4,096 bytes) in modern systems (x86-64 Linux/Windows).
  • Trend: Larger pages (2MB, 1GB "huge pages") are used for performance-critical applications to reduce TLB pressure.

The Logical Address Structure

Since page size is 2n2^n bytes, every logical address is mechanically split into two fields:

Logical Address=ppage numberdpage offset\text{Logical Address} = \underbrace{p}_{\text{page number}} \| \underbrace{d}_{\text{page offset}}

Where:

  • pp (page number): The upper (mn)(m - n) bits of the mm-bit logical address. Used as an index into the page table.
  • dd (page offset): The lower nn bits (where page size = 2n2^n). The position within the page/frame. Preserved unchanged in the physical address.

Example with page size = 282^8 = 256 bytes and a 10-bit logical address:

Logical AddressBit LayoutPage Number (p)Offset (d)
678 (decimal)10 1010011010 = 210100110 = 166
000 0000000000
25500 111111110255 (last byte of page 0)
25601 0000000010 (first byte of page 1)

The Page Table

The page table is a data structure maintained by the OS (one per process) that maps each page number to the frame number where that page is currently stored in RAM.

Page Table for Process P:
┌───────────┬──────────────┐
│ Page No.  │ Frame No.    │
├───────────┼──────────────┤
│     0     │      5       │  ← Page 0 is in physical frame 5
│     1     │      1       │  ← Page 1 is in physical frame 1
│     2     │     14       │  ← Page 2 is in physical frame 14
│     3     │     17       │  ← Page 3 is in physical frame 17
└───────────┴──────────────┘

Physical address computation: Physical Address=(frame number×page size)+offset\text{Physical Address} = (\text{frame number} \times \text{page size}) + \text{offset}

Or equivalently (using bit concatenation, which is how hardware does it): Physical Address=fframe number from tabledoffset (unchanged)\text{Physical Address} = \underbrace{f}_{\text{frame number from table}} \| \underbrace{d}_{\text{offset (unchanged)}}

Worked example: Logical address 678, page size 256B, using the page table above:

  1. p=678÷256=2p = 678 \div 256 = 2 (integer division) → page 2
  2. d=678mod256=166d = 678 \mod 256 = 166 → offset 166
  3. Page table lookup: page 2 → frame 14
  4. Physical address = 14×256+166=3,584+166=3,75014 \times 256 + 166 = 3,584 + 166 = \mathbf{3,750}

Internal Fragmentation in Paging

Paging does not completely eliminate fragmentation — it trades external fragmentation for a small, bounded amount of internal fragmentation:

  • If a process is not a perfect multiple of the page size, the last page will be partially full.
  • The wasted space inside that last frame is internal fragmentation.
  • Maximum waste: Page size − 1 bytes (e.g., with 4KB pages, max waste = 4,095 bytes ≈ 4KB per process).
  • On average: Half a page per process — much smaller than external fragmentation losses.

Hardware Support: Making Paging Fast

The Naive Implementation: Page Table in RAM

The page table is stored in main memory (RAM). The OS keeps a Page Table Base Register (PTBR) pointing to the start of the current process's page table in RAM.

The critical performance problem: Every single logical memory access now requires two physical memory accesses:

  1. Access the page table in RAM to find the frame number.
  2. Access the actual data in RAM at the computed physical address.

This doubles the memory access time — completely unacceptable for a general-purpose OS. The solution is a hardware cache specifically for page table entries.


The Translation Lookaside Buffer (TLB)

The TLB (Translation Lookaside Buffer) is a small, extremely fast associative cache built directly into the CPU (or MMU chip). It stores a small number of recently used (page number → frame number) mappings.

TLB Hit: Page number is found in the TLB → frame number retrieved immediately. → Cost: 1 TLB lookup + 1 RAM access (for data) = ~1 effective memory access

TLB Miss: Page number is not in the TLB → must access page table in RAM. → Cost: 1 TLB lookup + 1 RAM access (page table) + 1 RAM access (data) = ~2 effective memory accesses → After the miss, the mapping is loaded into the TLB for future use (replacing an old entry).


Effective Access Time (EAT): The Key Formula

Effective Access Time (EAT) measures the average time for a memory access, accounting for TLB hits and misses.

Definitions:

  • α\alpha = TLB hit ratio (the fraction of accesses that find the page in the TLB)
  • ϵ\epsilon = TLB lookup time (associative lookup time, often 10–20 ns)
  • mm = Memory access time (time to access RAM, e.g., 100 ns)

Formula: EAT=α×(ϵ+m)+(1α)×(ϵ+2m)\text{EAT} = \alpha \times (\epsilon + m) + (1 - \alpha) \times (\epsilon + 2m)

Expanded: EAT=(ϵ+m)+(1α)×m\text{EAT} = (\epsilon + m) + (1 - \alpha) \times m

  • Hit path: TLB lookup + 1 RAM access (the data)
  • Miss path: TLB lookup + 1 RAM access (page table) + 1 RAM access (the data)

Worked Example:

  • α=0.80\alpha = 0.80 (80% hit ratio), ϵ=10\epsilon = 10 ns, m=100m = 100 ns

EAT=0.80×(10+100)+0.20×(10+200)\text{EAT} = 0.80 \times (10 + 100) + 0.20 \times (10 + 200) =0.80×110+0.20×210= 0.80 \times 110 + 0.20 \times 210 =88+42=130 ns= 88 + 42 = \mathbf{130 \text{ ns}}

Without TLB (always 2 RAM accesses): 10+200=21010 + 200 = 210 ns. With TLB (80% hit rate): 130 ns — a 38% improvement.

Modern TLBs have hit ratios of 95–99% (because of locality of reference), making paging overhead negligible in practice.


Memory Protection: The Valid/Invalid Bit

Each entry in the page table contains more than just the frame number. A critical field is the valid/invalid bit:

  • Valid (1): The page is part of the process's legal address space and is currently in memory.
  • Invalid (0): The page is either not part of the process's address space, or it is currently swapped to disk.

If the CPU generates a logical address whose page table entry has the invalid bit set, the hardware triggers a page fault trap to the OS. The OS then either:

  1. Terminates the process (if the address is illegal — like a null pointer dereference).
  2. Loads the page from disk into a free frame and resumes the process (if the page was swapped — this is the mechanism behind virtual memory, covered in Section 3).

Shared Pages

Paging enables an elegant and important optimization: shared memory between processes without copying data.

Shared Code: If 10 users all run the same text editor, there's no need to have 10 copies of the editor's code in RAM. Each process's page table can map its code pages to the same physical frames containing the editor's code.

Requirement: Shared code must be reentrant (pure code) — it must not modify itself during execution. Only the data pages (stack, variables) need to be private to each process.

Process 1 Page Table:     Process 2 Page Table:
Page 0 → Frame 3 (code)   Page 0 → Frame 3 (code) ← SAME FRAME
Page 1 → Frame 8 (data)   Page 1 → Frame 9 (data) ← DIFFERENT FRAMES

This is the foundation of how modern OS memory mapping and shared libraries work.


Contiguous vs Paging: The Full Comparison

FeatureContiguous AllocationPaging
External Fragmentation❌ Yes✅ None
Internal Fragmentation❌ Yes (fixed partition)⚠️ Last page only
Process must be contiguous in RAM❌ Yes✅ No — any free frames
Address translation hardwareBase + Limit registersPage Table + TLB
Memory access overheadNoneExtra RAM access (mitigated by TLB)
Sharing memory between processes❌ Difficult✅ Easy via shared frames

Translating Logical Address 678 to a Physical Address Using a Page Table

  1. 1
    Step 1

    Page size = 256 bytes (2^8, so n=8 bits for offset). Total logical address space = 10 bits (so m-n = 2 bits for page number, giving 4 pages: 0,1,2,3). Page table for this process: Page 0 → Frame 5, Page 1 → Frame 1, Page 2 → Frame 14, Page 3 → Frame 17. Logical address to translate: 678.

  2. 2
    Step 2

    678 in binary = 10 10100110. Since page size = 256 = 2^8, the address is split as: High 2 bits | Low 8 bits. So: Page Number bits = '10' = 2. Offset bits = '10100110' = 166. The logical address (678) = Page 2, Offset 166.

  3. 3
    Step 3

    Cross-check with arithmetic: Page number p = floor(678 / 256) = floor(2.648) = 2. ✅ Offset d = 678 mod 256 = 678 - (2 × 256) = 678 - 512 = 166. ✅ Both methods confirm: this is byte 166 within page 2.

  4. 4
    Step 4

    The CPU sends page number 2 to the TLB. The TLB does not have an entry for page 2 (TLB miss). The MMU now reads the PTBR (Page Table Base Register) to find the page table in RAM, then accesses RAM at location [PTBR + 2] to read the entry for page 2. The entry reads: Frame = 14.

  5. 5
    Step 5

    Physical Address = (Frame Number × Page Size) + Offset = (14 × 256) + 166 = 3,584 + 166 = 3,750. Equivalently, in bits: concatenate frame number 14 (binary: 001110) with offset 166 (binary: 10100110) → physical address = 001110 10100110 = 3,750. ✅

  6. 6
    Step 6

    The MMU loads the mapping (Page 2 → Frame 14) into the TLB, replacing the least-recently-used entry. The next time this process accesses any address in page 2 (bytes 512–767 in logical space, 3584–3839 in physical space), the TLB will have a hit and no extra RAM access for the page table will be needed. The CPU receives the data from physical address 3,750.

Knowledge Check

Question 1 of 3
Q1Single choice

A system has a page size of 512 bytes and a 16-bit logical address space. A logical address has the value 3,000. What are the page number and the page offset?