Copy-on-write and fork
Explain how private memory can share physical pages after fork, and budget the copies created by later writes.
On this page
The question for today
What you’ll understand
- Distinguish process-private semantics from temporary physical sharing.
- Count distinct pages copied by a simplified write workload.
- Identify fork-related memory and multithreading risks before using worker processes.
Fork makes a new process whose ordinary private memory initially has the parent's contents. Copy-on-write allows much of that content to remain physically shared until a process needs a private change. This is a resource-saving implementation of private-memory semantics, not a promise that workers can modify one common heap or that starting a child consumes no additional memory.
Share frames while preserving private writes
For eligible private mappings, parent and child can initially refer to the same physical frames through mappings that will fault on a write. On a later write, the kernel makes the writing process see a private writable page, copying the old contents when sharing requires it. A protection fault is therefore sometimes a deliberate step in implementing an otherwise legal write. The logical result matters: the parent's private variable does not change merely because the child modifies its corresponding variable. Explicitly shared mappings have different semantics and must be reasoned about separately.
Copy-on-write usually operates at a page or folio-related granularity rather than at the single byte an application intended to change. The exact split or copying behavior for huge mappings can differ from a base-page example. A small metadata update may consequently incur much more data movement than its payload suggests. A page no longer shared may be made writable without copying an entire extra frame. Avoid declaring every write fault to be a physical copy; reference state and implementation choices determine the necessary work.
Cheap logical duplication has real overhead
Creating a child still needs execution state, kernel bookkeeping, and page-table work. A large address space with many populated mappings can therefore make fork expensive before any application page is copied. Summing parent and child resident-set sizes can count their shared frames twice. Proportional-set-size accounting apportions shared pages among their sharers and answers a different question, while cgroup accounting has its own ownership and charging rules. Choose a metric that matches whether you are budgeting host-unique physical usage, one process, or an administrative group.
A preloaded inference service may appear economical when workers only read its model. Later allocator metadata, reference counts, caches, or in-place preprocessing can dirty pages that looked immutable at the application level. Measure the actual post-fork steady state instead of assuming read-mostly high-level objects are physically unchanged. Starting an independent process with exec replaces the address space rather than preserving the inherited heap indefinitely. Process-start methods in language runtimes differ; establish which mechanism a particular deployment uses before applying a fork-based memory estimate.
A fork is not a clean thread-runtime restart
In a multithreaded process, the child contains only the thread that called fork, while memory may still contain locks and runtime state left by other threads. A lock whose owning thread does not exist in the child can become a serious problem. POSIX restricts what the child of a multithreaded process can safely call before exec; use supported process-launch facilities and their documented contracts rather than attempting arbitrary allocator or logging activity in that interval. Copy-on-write addresses page ownership, not these synchronization hazards.
In the probability lab, set n to twenty initially shared pages and p to 0.25. Predict a mean of five copied pages and variance 3.75 pages squared, then raise p to 0.5 and compare the mean. The model samples no actual writes; it displays exact binomial probabilities for independent page-level copy events. Explain why writing twenty bytes packed into one page differs from writing one byte in each of twenty pages. The real workload needs a distinct-page trace, not a byte count substituted into n.
Work it through
One-byte writes can copy whole pages
A parent has 1,024 resident private 4 KiB pages before fork. The child writes one byte in each of 100 distinct pages while the parent retains its original pages. Assume every such write requires one base-page copy.
The original payload is 1,024 × 4,096 = 4,194,304 bytes, or 4 MiB. It is initially physically shared in this simplified model.
The hundred copied pages add 100 × 4,096 = 409,600 bytes, or 400 KiB. The extra payload is not merely the hundred bytes deliberately modified.
Unique resident payload across both processes is now 4,603,904 bytes, approximately 4.391 MiB. Each process can still report a 4 MiB resident mapping, so adding their RSS values would overcount this shared payload.
Track distinct modified pages and shared frames. Fork overhead, new allocations, and page tables are additional costs beyond this copy-only calculation.
The living notebook
Explore the model
Interactive lab · probability
How many shared pages become private?
Use n=20 initially shared pages and independent copy-event probability p=0.25. Predict five expected copied pages, then compare p=0.5. The exact binomial bars do not replay application writes or model huge-page copy behavior.
- Mean · np
- 5
- Variance · np(1−p)
- 2.5
- Total probability
- 1
These are exact binomial probabilities for independent trials with one fixed success probability. Playback tours the distribution; it does not resample outcomes. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forA copy-on-write budget depends on the pages dirtied and the correlation of writes, not only on changed bytes.
Pause & reason
Check your understanding
Your turn
Try it yourself
A child may independently dirty each of forty shared 4 KiB pages with probability 0.1. What are the expected copied pages and extra bytes, and what assumption should be checked?
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Multiply n by p, then multiply the result by page size.
Compare with the solution
The expectation is four copied pages, or 16,384 extra bytes under the one-copy-per-page model. Real writes often cluster by object, allocator arena, or algorithm phase, so independence and equal per-page probability need evidence. The expectation is not an upper bound; the child might dirty all forty pages.
Keep the idea
Take it with you
- Private-memory semantics can be implemented with temporary physical sharing.
- Count distinct copied pages and avoid double-counting shared RSS.
- Fork in a multithreaded runtime needs a separate synchronization and launch-safety argument.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.