Virtual Memory & Memory Mapping

copy-on-write pages

Copy-on-write is the lazy-copy trick: when two parties should each have their own copy of some data but neither has changed it yet, let them share a single physical copy and only make a real, separate copy at the instant one of them tries to write. It is like two people handed the same shared document marked 'read-only' — as long as both only read, one copy suffices; the moment one wants to scribble on it, they get their own photocopy first.

Mechanically it is built from page-table bits. The shared pages are mapped into both parties' address spaces pointing at the same physical frames, but every such page-table entry is marked read-only even though the data is logically writable. Reads go straight through and are free to share. When either party writes, the read-only bit makes the MMU raise a protection page fault; the OS catches it, allocates a fresh frame, copies the one page's contents into it, points the writer's page-table entry at the new private frame and makes it writable, and restarts the write. Only the pages actually written ever get duplicated — everything untouched stays shared.

The classic user is fork(). A naive fork would copy the parent's entire address space to the child, which could be gigabytes, almost always immediately discarded by a following exec(). Instead, fork() marks all the shared pages copy-on-write, so parent and child instantly share physical memory and only the handful of pages either one modifies get copied. This makes fork() cheap and is why creating a process and then exec-ing a new program is fast. The same mechanism backs shared zero-pages and shared mappings of files.

After fork(), parent and child share the same physical pages read-only. The parent runs x = 5; on a shared page; that write faults, the OS copies just that one page, and now parent and child have separate copies of it — every other page they never wrote stays shared.

Shared until written; only the written page is duplicated.

Copy-on-write makes fork() cheap, but the copies are not free — they are merely deferred to the first write of each page. A child that immediately rewrites a lot of inherited memory triggers a storm of these faults, so 'fork is cheap' holds only when the child writes little before exec().

Also called
COWlazy copying寫時複製