Introduction
Demand paging is a virtual-memory technique where pages of a process are loaded into physical memory only when they are actually referenced, rather than loading the entire process image at start-up. This is a form of lazy loading: a process can begin executing with just a few pages (or even zero) resident, and the OS brings in additional pages on demand as the CPU generates references to them. Demand paging reduces startup latency, reduces memory waste on code/data that is never touched, and allows more processes to fit in physical memory simultaneously.
Cricket analogy: A T20 captain doesn't warm up all 15 squad players before the toss; only the XI actually needed take the field, and reserves are called in only if injury demands it, saving prep time.
Explanation
Every page table entry has a valid/invalid bit (or 'present' bit). When a process is created, all (or most) of its page table entries are marked invalid, even though the pages logically exist in the process's address space -- they simply are not yet loaded into a physical frame; their content resides on secondary storage (the executable file or swap space). Pure demand paging starts a process with no pages loaded at all, so the very first instruction fetch causes a page fault; more commonly, a small set of initial pages is pre-loaded to avoid an immediate fault storm. When the CPU references a page marked invalid, the hardware traps to the OS as a page fault. The page-fault handler performs, in order: (1) check whether the reference was valid (a legitimate but not-yet-loaded page) or truly illegal (a segmentation fault, killing the process); (2) find a free physical frame, invoking a page-replacement algorithm to evict a victim if none are free; (3) schedule a disk read to bring the required page into that frame; (4) while waiting, the OS blocks the process and schedules another one, since disk I/O is far slower than a context switch; (5) once the disk operation completes, update the page table entry to mark the page valid and point it at the new frame; (6) restart the instruction that caused the fault from the beginning (not resume mid-instruction), since the hardware guarantees the faulting instruction can be safely re-executed once the page is present.
Cricket analogy: A scorer's card marks a batter "not yet arrived" until they actually walk to the crease; if the umpire is signaled for a batter not on the list, it's ruled invalid, otherwise the twelfth man is sent to fetch them and play resumes from that ball.
Example
/* Simplified page-fault handler, illustrating demand paging steps */
#include <stdbool.h>
typedef struct {
bool valid; /* is the page currently in a physical frame? */
int frame; /* physical frame number, if valid */
int disk_block; /* location of this page on backing store */
} PageTableEntry;
/* Returns true if the access succeeds (after possibly faulting). */
bool access_page(PageTableEntry *pte, int free_frame_hint) {
if (pte->valid) {
return true; /* page already resident: no fault */
}
/* --- Page fault handling sequence --- */
if (pte->disk_block < 0) {
/* Step 1: reference is outside the process's address space */
return false; /* illegal reference -> SIGSEGV */
}
int frame = find_or_evict_frame(free_frame_hint); /* step 2: replacement */
read_page_from_disk(pte->disk_block, frame); /* step 3: disk I/O */
/* step 4: OS scheduler runs another process while this I/O is pending */
pte->frame = frame; /* step 5: update page table */
pte->valid = true;
return true; /* step 6: caller restarts instruction */
}Analysis
Demand paging trades a small per-fault latency cost (dominated by disk seek/transfer time, typically milliseconds versus nanoseconds for a memory access) for large gains in startup time and physical memory efficiency, since only actively used pages ever occupy a frame. The effective access time can be modeled as (1 - p) * memory_access_time + p * page_fault_time, where p is the fault probability; because page_fault_time is roughly five to six orders of magnitude larger than memory_access_time, even a small fault rate can dominate performance, which is exactly why the frame-allocation and page-replacement policies covered elsewhere in this module (and avoiding thrashing) matter so much in a demand-paged system.
Cricket analogy: A quick single (memory access) takes seconds, but a run-out review via DRS (a page fault) can cost minutes; even a small fraction of contested run-outs can dominate a match's total time if reviews are frequent.
Key Takeaways
- Demand paging loads a page into memory only when it is first referenced, instead of loading the whole process image up front.
- Pages start marked invalid in the page table; a reference to an invalid page triggers a hardware trap (page fault).
- Page-fault handling: validate the reference, obtain a frame (evicting if necessary), read the page from disk, update the page table, restart the instruction.
- Pure demand paging never pre-loads anything, so the first reference to every page always faults once.
- Because disk I/O is so much slower than memory access, even a low fault rate can dominate effective memory access time -- this is why replacement policy and avoiding thrashing matter.
Practice what you learned
1. What does demand paging mean?
2. What causes a page fault in a demand-paged system?
3. After the OS finishes servicing a page fault (page loaded, page table updated), what happens next?
4. In pure demand paging, how many pages are loaded when a process first starts?
5. Why does even a small page-fault rate significantly affect a system's effective memory access time?
Was this page helpful?
You May Also Like
Virtual Memory Concepts
The abstraction that gives each process its own address space, which can be larger than physical RAM.
Page Replacement Algorithms
How an OS decides which page to evict on a page fault when all frames are full, compared via FIFO, LRU, and Optimal.
Thrashing
The state where a system spends more time page-faulting and swapping than executing, and how the working-set model prevents it.