Copy-on-write (source code)

= Copy-on-write
{wiki}

<Copy-on-write> defers copying until a modification needs private storage. With <paging>, separate <address spaces> can map their <memory pages> to the same <page frames>, using <memory protection> to prevent writes to the common contents. Reads need no copy. A permitted write to a shared <page frame> first separates the writer's storage, so the other <operating-system process> keeps the old contents. Sharing is safe because the common contents remain unchanged while shared; the logical private copies can still evolve independently.<Operating Systems: Three Easy Pieces by Remzi H. Arpaci-Dusseau and others/Complete Virtual Memory Systems>[pp. 7–8: protected sharing, copying on a write, and fork/exec motivation]{ref}

Consider a <fork (system call)>-like model with parent A and child B. Each has a separate <page table>, with three inherited private, logically writable <memory pages>. Both initially map virtual page numbers `0x12`, `0x13`, `0x14` to <page frames> F0, F1, F2. The <page table entries> temporarily deny writes for <copy-on-write>; a read of `x` at offset `0x34` in virtual page `0x12` returns 7 in either <address space>. Separate <page tables> do not imply separate stored <bytes>.

\Image[/copy-on-write-shared-page-mappings.png]
{title=Before a write: two <page tables> map six <memory pages> to three shared <page frames>}

Now B writes `x = 42`. In this model, <copy-on-write fault handling> allocates F3, copies all of F0's contents into F3, redirects only B's <page table entry>, enables its write, and retries the store. A still reads 7 through F0; B reads 42 through F3 at the same <virtual address>. F1 and F2 remain shared. The <reference counting> labels count mappings in this example: F0 drops from two to one, while F3 starts at one. Updating one <byte> can therefore copy a whole <memory page>.

\Image[/copy-on-write-private-page-after-write.png]
{title=After B writes: one new <page frame>, one whole-page copy, and independent contents at the same <virtual address>}

The attraction is avoiding work that may never be needed. If B only reads, this model makes no data copies; if B replaces its program and discards these mappings, copying them beforehand would have been wasted. <Copy-on-write> trades eager copying for protected sharing and later <page faults>. The <page tables>, <reference counting>, and <operating-system process> records still cost time and <computer memory>.<Operating Systems: Three Easy Pieces by Remzi H. Arpaci-Dusseau and others/Complete Virtual Memory Systems>[pp. 7–8: a subsequent exec can discard most of the inherited address space]{ref}

For a concrete <operating system> contract, the `fork(2)` manual for the <Linux kernel> documents <copy-on-write>, while its `mmap(2)` manual distinguishes `MAP_PRIVATE` from `MAP_SHARED`. Writes through `MAP_PRIVATE` are not propagated to other mappings or the underlying <file>; writes through `MAP_SHARED` are visible to other <operating-system processes> mapping that region. An inherited shared mapping therefore retains shared-write behavior. For a private <memory-mapped file>, visibility of later changes to the underlying <file> is unspecified: private writes alone do not guarantee a frozen snapshot of the <file>. <fork(2) — Linux manual page>{ref}<mmap(2) — Linux manual page>{ref}

Nor does <fork (system call)> make every resource independent. With the <Linux kernel>, inherited <file descriptors> refer to the same <open file descriptions>, including shared file positions. Special mapping policies can omit a region from inheritance or zero it in the child. Thus the diagrams describe ordinary inherited private <memory pages>, not every resource reachable by a parent. <fork(2) — Linux manual page>{ref}