Master the fundamental concepts of memory management through this focused micro-challenge.
Demand paging defers physical allocation until a page is accessed. The kernel marks PTEs not-present; the first load or store traps, the fault handler finds a free frame, and returns to user code transparently.
On a demand fault:
For example, malloc returning a 16 KB arena might only consume 1 physical page until the program writes past the first 4096 bytes.
Demand paging is why touching one byte of a 1GB anonymous mmap doesn't cost 1GB of resident memory up front , Linux's memory overcommit accounting and every sparse-array workload depend on exactly this lazy-allocation behavior. Get the present-bit check backwards and every access becomes an unnecessary page fault, or worse, a real fault is silently skipped and you read unallocated memory.
Before you call the implementation done, walk failure modes on purpose. Test empty structures, single-element edge cases, maximum concurrency, and errno paths that must not crash the program. OS code usually fails in production when happy-path tests pass but invariants break under contention or memory pressure.
Keep structures small and name fields after kernel counterparts when possible. That lets you read man pages and kernel source side by side while you work. Print observable events during development; remove noisy logs once tests pass reliably.
You will hook page faults to allocate backing storage lazily. The exercise requires a counter proving physical pages grow only as the program touches virtual ranges.
Implement demand paging simulation.
Requirements:
Test:
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
All starter code and reference implementations are available for your local setup.
View on Github