Day 6: Copy-on-write, paging & file systems
The trick that makes containers cheap
Recall virtual memory from Day 3: every process has its own address space, mapped by the kernel to physical RAM. Paging is how that mapping is actually implemented — memory is divided into fixed-size chunks called pages, and the kernel maps virtual pages to physical page frames via a page table. Demand paging takes this further: a page isn't loaded into physical RAM until the process actually touches it, not when it's first requested.
Copy-on-write (COW)
When a process calls fork() to create a child process, the naive approach would be to duplicate all of the parent's memory immediately — slow and wasteful if the child barely touches most of it. Instead, the kernel makes the child share the *same* physical pages as the parent, marked read-only. Only when either process tries to write to a shared page does the kernel actually copy it — 'copy on write'.
This is why container layers and `fork()` are cheap
Starting a new container doesn't copy its entire filesystem image — it stacks a thin writable layer on top of shared, read-only image layers (Phase 5's OverlayFS is a filesystem-level version of exactly this idea). A fork()-ed process is cheap for the same reason: the OS shares first, copies only what actually changes.
File systems: inodes and journaling
A traditional filesystem stores a file's metadata (permissions, owner, size, timestamps, and pointers to its actual data blocks) in a structure called an inode — the filename itself is just an entry in a directory that points to an inode number. This indirection is why you can have multiple filenames (hard links) pointing at the same underlying data.
Journaling filesystems (ext4, XFS) write a short log of the change they're *about* to make before actually making it. If the system crashes mid-write, the journal lets the filesystem replay or roll back cleanly on reboot instead of ending up in a corrupted, half-written state.
Payoff, later
OverlayFS (the union filesystem behind Docker images, Phase 5) is a direct descendant of this idea: multiple read-only layers plus one writable layer, stacked and merged — the same 'don't copy until you must' philosophy as copy-on-write, applied to a whole filesystem.
Phase 0 capstone: narrate the ladder
In your own words (out loud or written — the roadmap's Track A suggests turning this into a short public writeup), explain: a program runs, allocates an object on the heap, that memory is backed by physical RAM via paging, and when it forks a child process, copy-on-write means the child doesn't get its own copy of that memory until something writes to it. This exact chain — heap → paging → copy-on-write → containers — is what the rest of Phase 5 and 6 will build on directly.
The Four Questions: the CFS scheduler (or copy-on-write)
Worked example for Docker (from the roadmap): dependency hell → consistent runtime environments → VMs too heavy → shared kernel, weaker isolation. Apply the same four-question shape to CFS or copy-on-write before moving to Phase 1.
Key terms
- Paging
- Dividing memory into fixed-size pages and mapping virtual pages to physical page frames via a page table.
- Demand paging
- Loading a page into physical RAM only when it's actually accessed, not when first requested.
- Copy-on-write (COW)
- Sharing physical memory between processes until one of them writes to it, at which point only that page is copied.
- Inode
- A filesystem structure holding a file's metadata and pointers to its data blocks; filenames are just directory entries pointing at an inode.
- Journaling filesystem
- A filesystem that logs pending changes before applying them, so a crash mid-write can be recovered cleanly.
Phase 0 complete — you should now be able to
Why is starting a new container fast even though it "has" a full filesystem image?