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]
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.
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]
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]
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]
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]
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]
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]
Private file mapping 2026-10-14
With MAP_PRIVATE, copy-on-write initially reuses backing page cache contents. In our model, a private store raises a protection page fault, copies the affected memory page to a private page frame, installs a writable page table entry and retries. The other memory page can remain shared. This page fault needs no storage read.
In B's private file mapping, storing copies relative page 1, including its neighbor . Next, A stores through its shared file mapping. After coordination outside the mapped data, B's shared reads give , while its detached private page gives . The untouched first memory page remains backed by the file; this is not a frozen snapshot of the whole file. Neither page writeback of shared contents nor msync publishes B's private 99. To save those private contents, the application needs a separate explicit file update.
Figure 1.
Toy shared file mapping and copy-on-write timeline: visible shared changes precede the chosen durable completion; private changes remain separate
. Details.
Shared file mapping 2026-10-14
With MAP_SHARED, updates are visible to other operating-system processes mapping the same region and are carried through to the backing file. With MAP_PRIVATE, updates instead stay private, and later backing file changes have unspecified visibility in that mapping.[ref]
In the toy model, both shared file mappings initially read backing bytes at file offsets 8229 and 8230. Both memory pages have been accessed, so their translations are installed. A shared store changes the common page cache contents and creates a dirty memory page eligible for page writeback. That change can be observed before it reaches persistent storage. Cooperating readers need synchronization to know when an update is ready; MAP_SHARED alone supplies no mutual exclusion or indivisible multi-field update.