Copy-on-write (COW) lets two processes share the same physical memory pages until one of them writes. The kernel marks the shared pages read-only; the first write triggers a page fault, the kernel copies that page, and each process continues with its own copy. It is why fork is cheap.
Before you start
You should understand virtual memory, pages and page faults. This article explains COW semantics and their practical effects.
Step-by-step walkthrough
Step 1: fork shares mappings, not data
When a process forks, the child gets a copy of the page tables pointing at the same physical frames, marked read-only. No memory is duplicated up front, so fork latency is roughly proportional to the size of the page tables, not the size of the heap.
Step 2: A write copies one page
On the child’s first write to a shared page, the hardware raises a protection fault, the kernel allocates a new frame, copies the page, and remaps the child’s entry as writable. After that, further writes do not fault. Reading from a shared page stays shared, so read-heavy children stay cheap.
Step 3: Read memory accounting with care
A shared page counts once in physical memory but appears in both processes’ reporting. RSS can double-count shared pages, so summing per-process memory overstates real usage. Tools that distinguish shared from private memory are needed for accurate capacity planning.
Worked scenario
After fork, the child edits a variable and the parent’s copy is untouched.
pid_t pid = fork();
if (pid == 0) {
shared_value = 42; // first write copies the page
} else {
wait(NULL); // parent keeps its own value
}Walk through the example
The child’s assignment is the first write to that page, so the kernel copies it before the store lands. The parent’s page was never written, so it still refers to the original frame and shows the old value. A read in the child would not have triggered a copy at all, which is why read-only workloads benefit most.
Common mistake
Assuming fork immediately doubles memory or that a forked child can never affect the parent; COW keeps both true only until a write. Another is misreading container memory, where shared pages make a process look larger than the memory it privately uses.
Verify the behavior
Fork in a loop over a large allocation and confirm latency stays low because no copy occurs. Write to a page in the child and observe increased private memory for the child only. Compare summed RSS with actual physical memory usage to see the double-count.
Interview exercise
Why is a forked worker fast to start, and when does it stop being cheap?
Answer and reasoning
It is fast because fork copies page tables and marks pages COW rather than copying heap data, so startup cost is small regardless of heap size. It stops being cheap once the child writes widely across its address space, because each first write copies a page — a garbage collector or a broad in-memory update can fault in most of the heap and erase the saving.
Continue learning
Compare memory topics in virtual memory and paging and page faults. Read the Linux fork and COW overview and try the Operating systems interview questions.