Master the fundamental concepts of memory management through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksmmap() establishes a virtual mapping backed by a file or anonymous pages. The kernel creates VMA metadata first; physical pages often arrive on first touch via demand paging.
Typical sequence:
vm_area_struct with prot flags and file offsetFor example, mapping 1 MB read-only at 0x7F00_0000 from a database file lets the OS lazily read 4096-byte pages instead of loading the whole file at mmap time.
mmap() is the same syscall the dynamic linker uses to map shared libraries into a process and that glibc's malloc calls directly once an allocation crosses its mmap threshold, bypassing the heap entirely. Confusing MAP_PRIVATE with MAP_SHARED is a classic production bug: one silently writes your changes back to the underlying file, the other never does.
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 simulate VMA creation and a fault handler that installs mappings on demand. This task asks you to distinguish MAP_PRIVATE copy-on-write behavior from shared mappings.
Simulate how the kernel implements mmap. A mapping only creates a VMA (virtual memory area: a range, its protection, and what backs it). No memory is touched until a page fault. On the first access the fault handler decides what to map. An anonymous page is the shared zero page on a read, or a fresh zeroed page on a write. A file page is read from the file (a major fault). A write to a shared read-only page triggers copy-on-write. An access outside any VMA, or against its protection, raises SIGSEGV, and one past the end of the file raises SIGBUS.
| Command | Meaning |
|---|---|
file NAME PAGES | declare a file with that many 4 KiB pages |
mmap LEN PROT FLAGS anon | anonymous mapping; PROT like rw- or r--; FLAGS is private or shared |
mmap LEN PROT FLAGS FILE PGOFF | file mapping starting at file page PGOFF |
read ADDR / write ADDR | a user access (hex address) |
munmap ADDR LEN | unmap a page-aligned range; may shrink or split VMAs |
maps | list the VMAs |
stats | fault and signal counts |
LEN is rounded up to whole pages. Placement: the lowest address ≥ 0x10000000 with a large enough gap between existing VMAs (first fit). Holes left by munmap are reused.
SIGSEGV (no mapping).w → SIGSEGV (not writable); a read without r → SIGSEGV (not readable).SIGBUS (beyond end of FILE).minor fault, shared zero page;minor fault, new zeroed page;major fault, loaded FILE page K, plus , page dirty for a write to a shared mapping or , then private copy for a write to a private one (which also counts a COW).cow fault, zero page -> private page;cow fault, private copy of FILE page K;hit, page dirty;hit.Each access line starts with read 0xADDR: / write 0xADDR: .
mmap: 0xSTART-0xEND PROT private|shared anon (file mappings end with FILE +PGOFF), or mmap: no such file.munmap 0xS-0xE: ok (or nothing mapped; an unaligned address gives munmap 0xADDR: EINVAL). Unmapped pages stop being resident.maps: START-END PROTp|s OFFSET NAME (R/N resident), as in /proc/self/maps: hex without 0x, the offset in bytes as 8 hex digits (0 for anonymous), [anon] or the file name, and resident pages out of the VMA's pages. Lines are in address order, or (no mappings).stats: faults: minor A, major B, cow C; signals: SIGSEGV D, SIGBUS E.Input:
cLoading…
Output:
cLoading…
munmap handles all four overlaps: whole VMA, head, tail, and middle (split into two, with the second VMA's file offset advanced).Hidden tests cover shared file mappings (dirty pages, no copy), private file mappings (COW on write), splitting a VMA with munmap in its middle, first-fit reuse of a hole, reading a non-readable mapping, and SIGBUS with a non-zero file offset.