Copy-on-write 2026-10-13
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.[ref]
Complete Virtual Memory Systems. pp. 7–8: protected sharing, copying on a write, and fork/exec motivation
Consider a fork-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.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.After B writes: one new page frame, one whole-page copy, and independent contents at the same virtual address
. Details. 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.[ref]
Complete Virtual Memory Systems. pp. 7–8: a subsequent exec can discard most of the inherited address space
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. [ref][ref]Nor does fork 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. [ref]
DMA address 2026-10-13
An address supplied to a device for DMA, in the device's address system. The Linux kernel's mapping interface returns this separately from the CPU's virtual address; an IOMMU can translate it to a physical address. [ref]
https://docs.kernel.org/core-api/dma-api-howto.html. Linux kernel documentation, Dynamic DMA mapping Guide: CPU and DMA addresses
DMA buffer synchronization 2026-10-13
Coordinating CPU and device access to a DMA buffer, including any required memory cache maintenance and ordering. A completed device write must be made visible before the CPU consumes it. The Linux kernel distinguishes coherent mappings from streaming mappings needing synchronization at ownership changes; even coherent mappings can require ordering of writes. [ref]
https://docs.kernel.org/core-api/dma-api-howto.html. Linux kernel documentation, Dynamic DMA mapping Guide: types of DMA mappings and using streaming DMA mappings
[ref]https://docs.kernel.org/core-api/dma-api.html. James E. J. Bottomley, Linux DMA API, part Ia: coherent buffers and write ordering
ext4 2026-10-13
A Linux kernel file system whose documented file-system journaling modes provide the implementation examples here. The diagrams specify a simpler abstract protocol, not its full on-storage format.
File-system journaling 2026-10-13
File-system journaling makes a group of related file system updates recoverable after a crash by recording them in a journal before changing their final storage locations. The useful promise is file-system crash consistency: after journal replay, a protected file-system transaction has taken effect completely or has not taken effect. File-system transaction durability adds a different promise: an acknowledged update survives the crash. The protected group can contain only file metadata, or both file metadata and file data blocks, depending on the file-system journaling mode.
Consider a tiny file containing
ABCD in four-byte file data block 7. Its inode records size 4 and a reference to block 7. Appending EFGH in previously free block 9 requires three new stored records: , the inode with size 8 and references to blocks 7 and 9; , the block allocation bitmap marking block 9 allocated; and , file data block 9 containing EFGH. An inode reference to a block still marked free lets a later allocation overwrite live contents; allocating a block without recording its owner can leak space. Even mutually consistent file metadata can expose stale contents if has not reached storage. Chapter 42 of Crash Consistency: FSCK and Journaling (section 42.1, pp. 2–4) develops this three-record append problem; the names, block numbers and tiny contents here are original teaching choices.The first diagram protects all three records with write-ahead logging. Each journal payload record identifies a final destination and its complete new contents. A storage flush makes the complete journal payload durable before a separate journal commit record is written and made durable. Only then may a journal checkpoint copy the records to their final locations. The journal remains available until those copies have themselves passed a storage flush; it can then be retired and its space reused. Journal replay repairs an interrupted journal checkpoint using the retained new contents.[ref]
Write-ahead logging separates durable journal commit records from journal checkpoints and safe journal reuse
. Details. These are persistence dependencies, not a claim that issuing writes in this order is sufficient. A device can report completion while its volatile memory cache still holds the only copy. The Linux kernel documents both flushing earlier completed requests and making completion of a particular request depend on persistence. The timeline uses separate storage flushes to make the dependencies explicit; an implementation can use equivalent device-supported operations. A commit write can persist before its storage flush returns: recovery uses the actual durable marker, while acknowledgment waits for successful completion.[ref]
The appeal is that recovery knows exactly which updates to finish. It does not have to infer a user's intended contents from contradictory inodes and block allocation bitmaps. The cost includes writing the journal payload as well as its final copies and waiting for persistence boundaries. The journal records a recent transition, not a historical collection of recoverable files; file-system journaling is not a file-system backup.
File-system transaction durability 2026-10-14
An acknowledged file-system transaction remains recoverable after a crash under the stated storage assumptions. In the full-data timeline, durable journal payload and a durable journal commit record suffice even before the journal checkpoint. A crash before durable commit can lose the append while still preserving file-system crash consistency. A successful ordinary write may only have reached a buffer cache; an application requiring persistence must use its documented interface and check errors. On Linux kernel-based systems, fsync on a file descriptor persists the associated file contents and file metadata, but persisting a newly created name also requires fsync on the containing file-system directory.[ref]
Fork (system call) 2026-10-14
A system call creating a child operating-system process from a parent. The Linux kernel documents copy-on-write for ordinary inherited private memory pages, with separate address spaces but shared open file descriptions for inherited file descriptors. [ref]
Interrupt 2026-10-13
An interrupt redirects CPU execution to an interrupt handler in response to an event. Here the main case is an asynchronous hardware interrupt: a timer or device requests attention independently of the instruction currently being executed. A device completing a receive operation can announce that its data is ready while the CPU is running another program. Interrupt-driven input-output illustrates this with an explicit timeline. [ref]
https://pages.cs.wisc.edu/~remzi/OSTEP/cpu-mechanisms.pdf. Arpaci-Dusseau and Arpaci-Dusseau, OSTEP chapter 6, section 6.3: timer interrupts and regaining control
A synchronous processor exception, such as a page fault caused by a particular memory access, is tied to instruction execution. A system call is an intentional program request for an operating-system kernel service. These routes can share entry machinery, and an instruction named a software interrupt can implement a system call, but this does not make that request an asynchronous device event. For example, the Linux kernel on x86 documents separate entries for external interrupts, divide exceptions,
syscall and int 0x80. [ref]https://docs.kernel.org/arch/x86/entry_64.html. Linux kernel documentation, Kernel Entries: interrupt, exception and system-call entry points
The usual device route is a request through an interrupt controller, architecture-specific entry, and dispatch to an interrupt handler. In the Linux kernel, generic handling separates controller operations from flow handling and device driver callbacks. Requests can arrive through a pin or a message, and several devices can share a request source. Routing, priorities and interrupt masking determine which requests can be delivered; notification therefore need not mean immediate execution of the interrupt handler. [ref]
https://docs.kernel.org/core-api/genericirq.html. Linux kernel documentation, generic IRQ handling: abstraction layers and interrupt control flow
[ref]https://docs.kernel.org/core-api/irq/concepts.html. Linux kernel documentation, What is an IRQ?: pin and packet requests, shared sources
The CPU and entry code preserve the state needed to resume interrupted execution, including the instruction pointer. Handling may enter a higher processor privilege level when interrupting ordinary program execution, but an interrupt can also arrive while privileged code is already running. The protected entry route and handler placement depend on the architecture and operating system; a microkernel need not place all device driver work where a monolithic kernel does. An interrupt entry is also distinct from a context switch to another operating-system process. [ref]
https://pages.cs.wisc.edu/~remzi/OSTEP/cpu-mechanisms.pdf. Arpaci-Dusseau and Arpaci-Dusseau, OSTEP chapter 6, sections 6.2–6.3: protected entry, saved state and switching
[ref]https://docs.kernel.org/arch/x86/entry_64.html. Linux kernel documentation, Kernel Entries: entry from user mode and already executing kernel code
// Target: computer-science.bigb
Interrupt controller 2026-10-13
Hardware managing and routing interrupt requests to a CPU, with architecture-dependent masking and priority rules. The Linux kernel encapsulates its operations separately from generic flow handlers. [ref]
https://docs.kernel.org/core-api/genericirq.html. Linux kernel documentation, generic IRQ handling: chip-level hardware encapsulation
// Destination: computer-science.bigb
Interrupt-driven input-output Created 2026-10-13 Updated 2026-10-24
In interrupt-driven input-output, a device signals an interrupt when attention is needed, letting the CPU avoid repeatedly checking an idle device. The interrupt handler determines what happened and arranges the required work; notification itself does not move the payload. DMA can supply that separate data-transfer mechanism.
For a toy comparison, let events occur at times . Ideal interrupt notification happens at those same times, while polled input-output at detects them at . The polling delays are ; ideal notification delays are all zero. Events are assumed to remain pending, with a simultaneous event visible to a poll. The chart is a model, not a measurement: it excludes interrupt delivery and dispatch latency, interrupt handler service time, and polling overhead. Its zero-delay row is not a real-hardware guarantee.
The useful idea is to spend attention when something changes. Sparse events can leave long stretches for useful CPU work instead of busy checks. At high event rates, repeated entry and service overhead can consume that saving. Batching notifications can reduce their frequency while delaying some events; switching to polled input-output during active periods is another option. No strategy is universally faster. [ref]
https://pages.cs.wisc.edu/~remzi/OSTEP/file-devices.pdf. Arpaci-Dusseau and Arpaci-Dusseau, OSTEP chapter 36, section 36.4: interrupt costs and coalescing
The Linux kernel's NAPI mechanism is a concrete combination: an interrupt normally schedules event processing, which polls for work with a receive budget. Further interrupts remain masked during that polling, and are enabled again when polling finishes. NAPI also supports busy polling; the exact processing context and configuration vary. This is a documented Linux kernel design, not a requirement on every operating system. [ref]
https://docs.kernel.org/networking/napi.html. Linux kernel documentation, NAPI: basic operation, datapath API, scheduling and IRQ masking
Interrupt handler 2026-10-13
Code entered to handle an interrupt. It identifies and acknowledges relevant device state and arranges service, possibly deferring work. The Linux kernel's generic flow layer and device driver callback have distinct responsibilities. [ref]
https://docs.kernel.org/core-api/genericirq.html. Linux kernel documentation, generic IRQ handling: interrupt control flow and default flow implementations
Linux buffer head 2026-10-14
The Linux kernel's per-block state structure, which can be attached to a Linux folio. Its reference counting is distinct from its dirty and valid state.
Memory-mapped file 2026-10-13
A memory-mapped file makes a range of a file accessible through an operating-system process's virtual memory address space. Once the mapping exists, ordinary loads and stores address its contents instead of explicitly reading them into a separate application buffer. This is attractive for jumping between records in a large file: an offset becomes an address calculation, and demand paging can supply the needed memory pages. It removes the application's explicit read-and-copy step; it does not promise that every access avoids copying, input-output, page faults or overhead, or that mapping is universally faster.
The backing file, page cache contents and each operating-system process's page table play different roles. For ordinary buffered Linux kernel mappings, the page cache holds reusable file contents; normal reads and writes also use it. A valid mapping can exist before this operating-system process has a usable page table entry. A first load can therefore trigger a page fault even when another reader has already brought the contents into computer memory. If the contents are absent, servicing the page fault can require input-output; if present, the handler can install an address translation without that read. Special paths that bypass the page cache are outside this explanation.[ref]
Page Cache by The kernel development community. Page Cache, opening paragraph: normal reads, writes and mmaps go through the page cache; bypass paths exist
The following example and diagrams are an original toy model, not an actual benchmark or a trace of a running operating system. They assume ordinary buffered file mappings, successful accesses, two cooperating operating-system processes, no concurrent resizing, and explicitly ordered actions. Memory-mapped file offset translation explains where the accesses land; shared file mappings and private file mappings explain whose contents change; memory-mapped file synchronization explains the separate persistence boundary.
Memory-mapped file offset translation 2026-10-14
Let be the memory page size, the aligned starting file offset, the mapping length and its base virtual address. A valid displacement with corresponds to file offsetHere is the relative memory page index, the floor function selects its integer part, and Euclidean division gives the within-page displacement . The backing page begins at . This identifies file contents; the page table separately selects a resident page frame and enforces permissions.
Take , and bytes in a file of at least 12288 bytes. A has a shared file mapping at . B has a shared file mapping at and a private file mapping at . These bases are illustrative chosen results, not requested fixed addresses. All three mappings cover the same two backing pages: file offsets 4096–8191 and 8192–12287. Displacement selects relative page 1, within-page displacement 37 and file offset . Thus A's
0x10001025, B's shared 0x20001025 and B's private 0x30001025 initially identify the same byte. The adjacent displacement 4134 identifies file offset 8230. Different virtual addresses can reach the same backing contents.Two operating-system processes map two backing pages at different virtual addresses; displacement 4133 identifies file offset 8229
. Details. To access a requested file offset that is not aligned, choose and displacement . Mapping enough bytes to cover that displacement plus the requested length makes the desired data start inside the aligned mapping. Do not pass the unaligned directly as the Linux kernel
mmap offset. For example, uses and displacement 37; that one-page start differs from our two-page mapping's . Memory-mapped file synchronization 2026-10-14
There are two distinct questions: whether another operating-system process can observe shared contents, and whether those contents survive a crash. In the timeline, persistent storage deliberately remains while the shared page cache contains . No background page writeback occurs in this toy interval. Real page writeback may persist some contents earlier; shared visibility alone cannot tell the reader which contents are durable.
For the covered shared range,
msync(base, length, MS_SYNC) requests page writeback and waits for completion; check its return value. MS_ASYNC is not a durable completion acknowledgment, and on modern Linux kernel versions it is a no-op because dirty contents are already tracked. The address must be aligned, so synchronizing our changed second page uses base + 4096, length 4096, rather than base + 4133. Unmapping alone is not a guarantee of completed writeback.[ref]msync(2) — Linux manual page by Linux man-pages project. DESCRIPTION, RETURN VALUE, ERRORS and VERSIONS: covered range, MS_SYNC versus MS_ASYNC, page-aligned address, and Linux MS_ASYNC behavior since 2.6.19
For persistence of the file and associated file metadata, fsync on an open file descriptor is a broader interface; a new directory entry needs separate synchronization of its file-system directory. Retain a suitable file descriptor if the persistence protocol needs it after mapping. Successful storage completion still relies on the file system and device honoring their persistence contracts.[ref]
fsync(2) — Linux manual page by Linux man-pages project. DESCRIPTION, RETURN VALUE and ERRORS: file data and metadata, directory entry, completion and reported failures
Neither fsync nor msync supplies mutual exclusion, an atomic storage write for several memory pages, or an application-wide file-system transaction. Stop or coordinate writers before deciding which update a completion acknowledges. A crash during page writeback can leave a mixture of old and new contents unless a separate recovery protocol provides file-system crash consistency. The last timeline row assumes successful synchronous completion, honored storage flush semantics and no subsequent writer; it illustrates a persistence boundary, not a promise about arbitrary hardware failures.
mmap 2026-10-14
The POSIX mapping interface. Ordinary Linux kernel file mappings require a positive length and an aligned file offset. A null address lets the operating-system kernel choose an aligned base; length need not be aligned. Check for
MAP_FAILED. After success the file descriptor may be closed without invalidating the mapping; munmap or process termination removes it.[ref]mmap(2) — Linux manual page. DESCRIPTION: address, length, offset and descriptor lifetime; munmap; RETURN VALUE
Mapping does not extend the backing file. Under POSIX, for an initially partial last memory page, the tail beyond the file's end is zero-filled and is not written back as file data; accesses to whole mapped memory pages beyond the end raise
SIGBUS. POSIX leaves access to portions added or removed by later resizing unspecified. Establish the required file size first and coordinate resizing with readers; a mapping's length is not proof that those bytes exist in the file.[ref]mmap — POSIX.1-2024. POSIX.1-2024, DESCRIPTION: partial end page, whole pages beyond the object, and changed file size; RATIONALE: references beyond the end do not extend the object
The Linux kernel documents a tail-cache exception: modified beyond-end bytes can survive in the page cache and appear in later mappings, although never written to the file. Do not use that tail as reliable storage.[ref]
mmap(2) — Linux manual page. BUGS: modified contents beyond the object end can remain in the page cache
Multi-level page table 2026-10-14
A hierarchy of page tables indexed by successive groups of virtual page number bits. Unused regions can omit lower-level tables.
The useful omission is an entire lower-level array, not merely an invalid page table entry. One absent upper-level entry can represent a large unmapped interval of the address space. The Linux kernel's documented hierarchy uses this idea to avoid allocating tables for unused regions; its software levels can also be folded to match the hardware. [ref]
Page Tables by The kernel development community. Page Tables: opening hierarchy discussion, paragraph beginning "One could of course imagine"; Page Table Folding
Page cache 2026-10-14
Caching file contents in units based on memory pages, commonly by a file mapping and an offset, rather than necessarily by the device-and-block buffer cache key used above. A file's offset must be mapped to storage before device access; the two naming systems describe different layers. How page cache and buffer cache storage relate depends on the operating system and file system. A separate duplicate copy at each layer is not a universal requirement.
For the Linux kernel interfaces documented in Buffer Heads by The kernel development community, per-block state can be attached to larger cached memory units called Linux folios;
mark_buffer_dirty also marks the backing page dirty in the page cache. The documented reclamation checks include dirty state, pending buffer cache writeback and elevated reference counts. That documentation deprecates Linux buffer heads for new file systems in favour of iomap. These are platform-specific interfaces, not a definition that every page cache has Linux buffer heads or that every buffer cache has its own disjoint allocation. [ref]



