Introduction
Virtual memory separates the logical memory a program sees from the physical memory it occupies, so that a process need not be entirely in memory to run. Programs often contain error-handling code that rarely runs, arrays declared larger than they are used, and features few users touch. Loading only what is referenced lets a program be larger than physical memory, lets more processes share memory, and makes process start-up faster.
The usual implementation is demand paging: Paging, Page Tables and TLB, bringing a page into use when it is first referenced. A reference to a legal page that is not currently mapped/present causes a page fault. A major, disk-backed fault reads backing storage; a soft fault may instead map an already resident frame, and demand-zero allocation supplies a zero-filled page without a backing-storage read. Disk-backed faults are very expensive compared with memory accesses, so keeping their rate tiny matters; excessive paging activity can cause thrashing.
The valid-invalid bit, the page-fault service sequence, effective access time with faults, copy-on-write, frame allocation, the locality and working-set models, and thrashing are the standard facts. Choosing which page to evict is in Page Replacement Algorithms.
Prerequisites
- Paging, Page Tables and TLB: page tables, the valid bit, the TLB and effective access time without faults.
Core concepts
Demand paging and the valid-invalid bit
Each page-table entry has a valid-invalid bit. In this simplified present-mapping model, valid means a legal page is present in this mapping. Invalid means either an illegal address or a legal page whose mapping is absent: it may require a disk read, a mapping to an already resident frame, or demand-zero allocation. A reference to an invalid entry traps to the OS, which looks at its own records (usually in the PCB) to tell the two cases apart.
- Pure demand paging starts a process with no pages in memory; every first reference to a page faults. A process that touches 7 distinct pages with enough frames for all of them takes exactly 7 page faults.
- Prepaging loads some pages ahead of demand, for example the working set of a process being resumed, gambling that they will be used.
- The locality of reference of real programs (a loop runs over a few pages for a while, then moves on) is what makes demand paging work.
Terminology
| Term | Meaning |
|---|---|
| Page fault | Reference to a page whose entry is invalid |
| Major (hard) fault | The page must be read from secondary storage |
| Minor (soft) fault | No backing-storage read is needed: for example, map an already resident frame or supply a zero-filled page |
| Backing store, swap space | The secondary-storage area that holds pages not in memory |
| Free-frame list | Frames available for incoming pages, often zero-filled on demand |
| Dirty (modify) bit | Set on a write; a clean victim need not be written back |
How a page fault is serviced

Restarting the instruction. The hardware must be able to restart any instruction after a fault, as if it had never started. This is hard for an instruction that modifies memory and can fault part-way, such as a block move whose source and destination overlap, or an instruction with auto-increment addressing. Hardware either checks both ends of the operands before starting, or saves enough state to undo the partial effect (Tanenbaum 3.6.3 calls this instruction backup).
Minimum number of frames. The architecture fixes a minimum: every page that one instruction can touch must be in memory at once. A memory-to-memory move instruction whose own bytes, source operand and destination operand can each straddle a page boundary can touch 6 pages, so such a machine needs at least 6 frames per process.
Mathematical explanation
Effective access time with page faults
For this disk-backed-fault cost model, let be the memory access time, the fault service time and the disk-backed-fault rate (faults per memory reference). Then
is dominated by the disk read (and a write-back for a dirty victim): milliseconds, against nanoseconds for , so even a tiny matters.
Example 1. ns, ms ns, :
about 51 times slower than with no faults. To keep the slowdown within 10% (EAT at most 110 ns) we need , that is : fewer than one fault in about half a million references.
Example 2, dirty victims. ns; servicing a fault takes 6 ms when the victim is clean and 15 ms when it is dirty and must be written back first; 40% of victims are dirty. The mean service time is ms ns. For EAT at most 240 ns:
Convention. Some questions write , counting the memory access even on a fault (the restarted instruction does access memory). The difference is , negligible unless is large; use the form the question gives.
TLB and page faults together
Combine the TLB from Paging, Page Tables and TLB with faults. Let the TLB lookup take ns, memory ns, the TLB hit ratio be 0.9, and suppose that 1% of the references that miss the TLB also fault, with ms. State the model: a TLB miss costs for the page-table read; if the page is present, one more for the data; if it faults, and then a restarted reference that hits the now-updated TLB, .
The fault term contributes 2,000.22 of those nanoseconds, although only 0.1% of references fault.
A two-level walk, faults and dirty victims together
Memory access ns, TLB time negligible, a two-level page table, TLB hit ratio 0.95. Of the references that miss the TLB, 0.1% fault; a fault takes 5 ms with a clean victim and 10 ms with a dirty one, and 30% of victims are dirty. After a fault the instruction restarts and hits the TLB.
- TLB hit: ns.
- TLB miss, page present: two table reads and the data, ns.
- TLB miss, fault: two table reads, the service time and the restarted access, , with mean ms.
Counting a population of 2,000,000 references path by path (1,900,000 hits, 99,900 present misses, 70 clean and 30 dirty faults) gives the same 435 ns. Without any faults the EAT would be ns, so 100 faults in 2,000,000 references make it almost four times larger.
Loop order and page faults
int A[128][128] with 4-byte integers, stored row by row, and 512-byte pages, with the array beginning on a 512-byte page boundary, so each row ( bytes) fills exactly one page. The process has one frame for the array, and the array is not in memory at the start.
- Row by row (
for i: for j: A[i][j] = 0): the 128 elements of a page are used together, so there is one fault per row: 128 faults. - Column by column (
for j: for i: A[i][j] = 0): consecutive references are in different rows, hence different pages, so every one of the references faults.
With cold start, no other references/replacement interference, and FIFO or LRU, 2 frames leave the counts unchanged, and 128 frames (the whole array) are required for the column order to drop to 128 faults. These threshold claims are not policy-independent; OPT can obtain hits with fewer frames. Under the stated FIFO/LRU assumptions, loop order drives the difference.
Frame allocation
With free frames and processes of sizes (in pages), equal allocation gives each of processes frames, and proportional allocation gives process
With and sizes 25, 75 and 200 pages, proportional allocation gives 5, 16 and 42 frames (from 5.33, 16 and 42.67); the floors leave 1 frame in the free pool. Equal allocation gives 21 each, also leaving 1. Priority can be mixed in by weighting the sizes.
Global versus local replacement. With global replacement a faulting process may take a frame from any process; throughput is usually better, but a process's fault rate depends on the others. With local replacement it replaces only its own pages, so its behaviour is predictable but memory may sit idle in other processes.
Copy-on-write
In the simple counting model, parent and child retain their shared private writable COW mappings until the first write, with neither unmapping/exiting first; explicitly shared mappings are excluded. After fork(), eligible private writable pages are shared and temporarily write-protected for copy-on-write. The first write by either process to a shared page traps; the OS copies that page into a free frame, maps the copy writable for the writer, and lets the write proceed. Pages never written are never copied, so a child that immediately calls exec() costs almost nothing. If the child writes to 3 distinct pages (several times each) and the parent writes to none, exactly 3 pages are copied. See Process Creation and fork() for the process side.
Thrashing and the working-set model
A process that does not have enough frames for the pages it is actively using faults, evicts a page it will need almost at once, and faults again. It spends more time paging than executing: it thrashes. With global replacement, thrashing spreads: faulting processes steal frames from others, CPU utilisation falls, a naive scheduler admits more processes to raise utilisation, and the fault rate rises further.

The working set
The working set is the set of distinct pages referenced in the last references up to time (the working-set window). Its size is . If the total demand exceeds the number of frames , some process lacks its working set and the system will thrash; the OS should then suspend a process (swap it out) rather than admit another.
Example. Reference string 1 2 1 3 2 1 4 4 5 4 5 6 5 4 6 6 (times 1 to 16), :
| Time | Last 4 references | WSS | |
|---|---|---|---|
| 6 | 1 3 2 1 | {1, 2, 3} | 3 |
| 7 | 3 2 1 4 | {1, 2, 3, 4} | 4 |
| 10 | 4 4 5 4 | {4, 5} | 2 |
| 16 | 5 4 6 6 | {4, 5, 6} | 3 |
The program moves from a locality {1, 2, 3} to a locality {4, 5, 6}; the working set is largest (4 pages) at the transition. A that is too small misses parts of a locality; one that is too large spans several localities.
Admission. Four processes with working-set sizes 30, 45, 60 and 25 need frames; with 150 frames the system is over-committed and one process should be suspended.
Page-fault frequency
A simpler control measures each process's fault rate directly: above an upper bound the process gets more frames, below a lower bound it loses some. If no frames are free when a process needs more, a process is suspended.
Important properties and observations
- A page fault traps to the OS. In the major, disk-backed path the process blocks during the disk read and the CPU can run another process; soft/resident-frame and demand-zero faults need no backing-storage read.
- In the disk-backed-fault cost model, the fault rate must be very small (around one in hundreds of thousands of references) for paging to be acceptable.
- A dirty victim roughly doubles the service time because of the write-back.
- Thrashing is a lack of frames for the working sets, not a scheduling problem; adding processes makes it worse.
- Copy-on-write makes
fork()cheap and copies only pages that are written.
Common misconceptions.
- "Every invalid entry is an error." An invalid entry may be a legal page that is on disk.
- "More multiprogramming always raises utilisation." Only until the working sets exceed memory.
- "Local replacement prevents thrashing." It confines thrashing to the process that lacks frames, which still runs slowly and also slows the paging device for everyone.
GATE examination perspective
- EAT with faults. Convert milliseconds to nanoseconds, include the write-back fraction for dirty victims, and solve the inequality for the largest fault rate.
- Combined TLB, page table and fault. Write the model (which accesses happen on each path) before writing numbers.
- Working-set tables. Count distinct pages in the window ending at , including itself.
- Thrashing causes and cures. Cause: total working sets exceed frames. Cure: suspend processes, working-set or fault-frequency control.
- Pure demand paging. Faults at least the number of distinct pages referenced.
- Copy-on-write counts. In the simple retained-private-COW model above (neither unmaps/exits first), count one copy per distinct original shared COW page written by either process; this excludes explicitly shared mappings.
Summary
Sources
- A. Silberschatz, P. B. Galvin, G. Gagne, Operating System Concepts, 10th ed., Wiley: Chapter 10 (10.1 Background, 10.2 Demand Paging, 10.3 Copy-on-Write, 10.5 Allocation of Frames, 10.6 Thrashing).
- A. S. Tanenbaum, H. Bos, Modern Operating Systems, 4th ed., Pearson: Chapter 3 (3.3 Virtual Memory, 3.4.8 The Working Set Page Replacement Algorithm, 3.5.1 Local versus Global Allocation Policies, 3.5.2 Load Control, 3.6.2 Page Fault Handling, 3.6.3 Instruction Backup).