Home/Learn/Operating Systems/Page Faults & Demand Paging

Page Faults & Demand Paging

Intermediate
Memory Management

A page fault occurs when a process accesses a virtual page not currently in physical RAM, triggering the OS to load it from disk — demand paging loads pages only when first accessed.

Overview

Demand paging is the strategy of not loading a page into RAM until it is actually accessed. When the executable starts, none of its pages are loaded; only the first few that get executed are brought in. Every time the process accesses a virtual address whose page is not in RAM, the MMU raises a page fault exception. The OS page fault handler takes over, finds the page on disk (in the swap area or as a file-backed page), allocates a free physical frame, loads the page, updates the page table entry, and restarts the faulting instruction. Minor page fault: the page is in memory but the page table entry was not set up (e.g., a recently forked child sharing COW pages) — no disk I/O needed. Major page fault: the page truly needs to be loaded from disk — catastrophic for latency since one disk I/O equals millions of CPU cycles.

Page Fault Handler Steps

When a page fault fires, the CPU switches to kernel mode and saves process state. The handler checks whether the faulting address is a valid virtual address for this process (not a null dereference or buffer overflow). If valid, it locates the page on disk (swap or memory-mapped file), finds a free frame (possibly evicting another page), loads the data, marks the PTE valid, and restarts the instruction. If the address is invalid, the process receives SIGSEGV — in Java this appears as a NullPointerException or ArrayIndexOutOfBoundsException.

Pseudocode — OS page fault handler with minor vs major fault distinction
// Page fault handler (OS pseudocode)
void handlePageFault(Process p, long virtualAddress) {
    // 1. Validate: is this address in the process's valid VMA (virtual memory area)?
    if (!p.isValidAddress(virtualAddress)) {
        sendSignal(p, SIGSEGV);  // → Java NullPointerException / OOBE
        return;
    }
    // 2. Check if minor fault (page in memory, PTE not set)
    if (isPageInMemory(virtualAddress)) {
        updatePageTableEntry(p, virtualAddress);  // no disk I/O
        return;  // minor fault handled
    }
    // 3. Major fault: find a free frame (or evict a page)
    int frame = findFreeFrame();
    if (frame == -1) frame = evictPage();   // page replacement algorithm
    // 4. Load page from disk (swap or file)
    loadPageFromDisk(p, virtualAddress, frame);  // ~5ms disk I/O
    // 5. Update PTE: mark valid, set frame number
    p.pageTable[getPageNumber(virtualAddress)] = frame | VALID_BIT;
    // 6. Restart the faulting instruction
}

// Java: triggering page faults deliberately (warm-up vs cold start)
// Cold start: JVM reads class files → major page faults on each new class loaded
// After warm-up: all hot pages in RAM → no page faults → fast execution

Java Memory-Mapped Files and Page Fault Performance

Memory-mapped files rely entirely on demand paging — accessing any part of the mapped region that is not yet in RAM triggers a major page fault. This makes initial access slow but subsequent reads fast. For large files (multi-GB), only the accessed pages consume RAM. Java NIO's MappedByteBuffer is the primary API. OutOfMemoryError in Java is not a page fault — it means the JVM heap allocator cannot grow further (heap limit reached or native memory exhausted).

Java — MappedByteBuffer cold vs warm access showing page fault latency
// Measuring page fault impact on memory-mapped file access
Path path = Path.of("large-dataset.bin");

long startMap = System.nanoTime();
try (FileChannel fc = FileChannel.open(path, StandardOpenOption.READ)) {
    MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
    long mapTime = System.nanoTime() - startMap;
    System.out.printf("Mapping time: %.2f ms (just reserves VA space)%n",
        mapTime / 1e6);

    // First access — triggers major page faults (disk I/O)
    long startRead = System.nanoTime();
    int firstByte = buf.get(0);  // page fault → load 4KB from disk
    long faultTime = System.nanoTime() - startRead;
    System.out.printf("First access (major fault): %.2f ms%n", faultTime / 1e6);

    // Second access to same page — already in RAM, no fault
    startRead = System.nanoTime();
    int sameByte = buf.get(1);   // same 4KB page → no fault
    long hotTime = System.nanoTime() - startRead;
    System.out.printf("Second access (no fault):   %.3f µs%n", hotTime / 1e3);
}
// Ratio: major fault ~1-5ms vs hot access ~100ns = 10,000x difference

Key Points to Remember

  • 1Demand paging loads pages only when first accessed — program starts instantly without loading everything.
  • 2Minor page fault: page is in memory but PTE not set — handled without disk I/O.
  • 3Major page fault: page must be loaded from disk — costs ~1–10 ms (millions of CPU cycles).
  • 4The page fault handler validates the address, allocates a frame, loads from disk, updates PTE, and restarts.
  • 5Java OutOfMemoryError means heap limit reached — not a page fault (that would be transparent to Java).
  • 6Memory-mapped files use demand paging — only accessed pages consume RAM, ideal for large datasets.

Interview Questions

Sign in to ask Aria
1

What is the difference between a minor and a major page fault?

MediumGoogle
2

What steps does the OS take when handling a major page fault?

MediumAmazon
3

Why is a Java application slow on the first request after deployment?

EasyNetflix
4

How does demand paging allow a process to use more memory than physical RAM?

MediumFlipkart

Ask Aria about Page Faults & Demand Paging

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…