cswork / libraryOpen practice workspace

Articles

mmap Interview Questions: Copy-on-Write, File Truncation, and Page Faults

Practise mmap interview questions on copy-on-write, truncation, page faults, and durability, with a safe file fixture and a Linux backing-range timeline.

A mapped pointer can remain inside a valid virtual-address range while the file page behind it no longer exists. That is why “the index is less than the mapping length” is not a complete safety argument for mmap.

Strong mmap interview answers track four boundaries separately: the mapping's address range, the backing object's current extent, visibility of writes, and durability. Copy-on-write answers one of those questions. It does not freeze a file, prevent truncation, or turn memory stores into a database transaction.

This guide uses Linux and POSIX documentation for systems behavior, plus a safe Python exercise for private and shared writes. The truncation example is a Linux-oriented reasoning exercise, not an instruction to crash your current process. For the surrounding storage concepts, see Linux filesystem interview questions.

What does mmap create, and what does it not guarantee?

A file-backed mapping associates a virtual-address range with part of a file. Accesses use ordinary loads and stores, subject to the mapping's protections and the operating system's memory-management behavior. Creating that association does not prove that every page is already resident in physical memory.

For the Linux API, a mapping has a length, protection flags, a mapping type, a file descriptor, and a file offset. Check the return value before using the address. An invalid offset alignment or unsupported flag combination is a setup failure, not a later page-fault mystery. Linux mmap reference

Start an interview explanation by stating the workload: read-only scanning, shared updates, or a private working copy. Then state which process owns resizing the file and how readers coordinate with it. Without that ownership rule, even a correctly created mapping may become unsafe later.

Do not say that mmap is automatically faster than read. Removing an explicit user-space copy can be useful, but fault handling, access locality, working-set size, and operating-system behavior still matter. A performance conclusion needs a representative workload and measurements, not the name of the API.

Does MAP_PRIVATE create an immutable snapshot?

No. MAP_PRIVATE isolates writes made through that private mapping from the underlying file and other mappings. It is a copy-on-write contract for your modifications, not a general snapshot contract for concurrent changes to the backing object.

POSIX does not give you a portable promise that later file modifications will be invisible through an existing private mapping. Avoid building correctness on whichever behavior happened in one experiment. If you require a stable dataset, arrange stability explicitly: immutable file generations, coordinated ownership, or a separately created copy with a defined publication protocol. POSIX mmap specification

This distinction matters in a configuration loader. “Readers use private mappings” does not authorize a writer to truncate and rewrite the same file underneath them. The reader's private changes may be isolated while its backing extent is still being changed by someone else.

Also distinguish logical isolation from physical allocation. Copy-on-write can initially share physical pages and create private copies when writes occur. You cannot infer the exact number of allocated pages from the number of bytes written without considering page boundaries and implementation details.

Work through a private-versus-shared write experiment

Use a throwaway file containing abcd. In the first experiment, a private mapping changes byte zero to X. Reading that mapping should show Xbcd, while reading the file should still show abcd.

In a separate experiment, a writable shared mapping changes byte one to Y. After flushing and closing that mapping, reading the file should show aYcd. Separating the experiments prevents an earlier private modification from confusing the expected result.

Python exposes these access modes as ACCESS_COPY and ACCESS_WRITE. Its documentation describes private-copy writes and file-backed writes, along with context-manager cleanup. Python mmap documentation

import mmap
import tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as directory:
    path = Path(directory) / "mapping-demo.bin"
    path.write_bytes(b"abcd")

    with path.open("r+b") as file:
        with mmap.mmap(file.fileno(), 4,
                       access=mmap.ACCESS_COPY) as private:
            private[0:1] = b"X"
            assert private[:] == b"Xbcd"
            assert path.read_bytes() == b"abcd"

    with path.open("r+b") as file:
        with mmap.mmap(file.fileno(), 4,
                       access=mmap.ACCESS_WRITE) as shared:
            shared[1:2] = b"Y"
            shared.flush()

    assert path.read_bytes() == b"aYcd"

Run this only against the temporary file created by the example. The assertions establish the observed visibility contract for this small fixture. They do not simulate a crash, a filesystem failure, or a concurrent reader. Passing them is not evidence of production durability.

The useful follow-up is: what result would expose a wrong access mode? If the first modification reaches the file, the private-write expectation is broken. If the second cannot be assigned, the mapping's write permissions are wrong. A test should distinguish those faults rather than merely show that mapping creation succeeded.

Why can truncation cause SIGBUS inside the mapping?

Assume a Linux system with 4,096-byte pages for this example. The file initially contains 8,192 bytes, and the reader maps all of it. Another process then truncates the file to 4,096 bytes. The reader accesses offset 6,144.

That offset remains below the original mapping length. However, it lies in the second file page, which is now beyond the backing object's end. Linux documents SIGBUS for accessing a mapped page beyond the file's end. Bounds against the original mapping length have checked the wrong boundary. Linux mmap reference

Initially:
  Mapping: [0, 8192)
  File:    [0, 8192)

After truncation:
  Mapping: [0, 8192)
  File:    [0, 4096)

Read 6144:
  Inside mapped range
  Beyond file backing

Do not use the example's page size as a universal constant. Query the runtime when implementing page-aligned operations. Also do not generalize a partial final page's documented handling into permission to read every mapped page beyond EOF. POSIX distinguishes the partial page from whole pages beyond the object. POSIX mmap specification

Checking file size immediately before a load is not sufficient if a writer can truncate between the check and the load. That is a time-of-check/time-of-use race. The repair is an ownership or synchronization protocol, not another unsynchronized size query.

How would you make a mapped-file reader safe?

First decide whether readers need the latest bytes or a stable generation. Those requirements lead to different designs.

For stable generations, a writer can create and validate a new file, then publish its name according to an explicit protocol. Existing readers continue using their old opened object; new readers open the new generation. A rename changes name resolution, not an existing mapping into a magical view of whichever object now occupies that pathname.

Readers must keep the old generation available for their intended lifetime, and writers must not truncate it while it is still in use. Reference counting, leases, or a coordinated handoff can express that lifetime. Describe failure recovery too: what happens if a reader dies without releasing its reference?

For an in-place mutable file, define who may resize it, how other processes stop accessing affected ranges, and when mappings are recreated. A lock is meaningful only if all participants honor it. Memory-mapping the file does not supply that application protocol for free.

If the interview asks for crash-safe publication, add a separate persistence discussion. Stable-reader ownership solves a different problem from ensuring that a newly published generation survives a machine failure. Do not silently substitute one guarantee for the other.

Is every page fault a disk read?

No. A page fault means an access needs memory-management handling; the required work depends on the page's state. A minor fault can be resolved without I/O. A major fault involves I/O. Linux exposes these categories through process resource usage. getrusage reference

A file page may already be in the page cache but not yet mapped into this process's page tables. Access can then require fault handling without fetching the file from storage. Copy-on-write can also require handling to create a writable private page. Neither explanation is captured by “every fault reads disk.”

Keep a TLB miss separate from a page fault. Missing a cached translation can lead to a page-table lookup that finds a valid mapping. It need not require the operating system to resolve a missing or protected page.

For a scan experiment, record access pattern, file size, memory pressure, warm versus cold conditions, and the measurement interval. Readahead and caching can make simplistic “one major fault per page” predictions wrong. Do not clear system caches on a shared machine just to manufacture a result.

When do shared writes become durable?

Visibility and persistence are different questions. A shared mapping permits updates to the backing object; that does not make every memory store a completed, crash-safe transaction.

Linux msync provides synchronization of modifications in the specified mapped range. With MS_SYNC, it waits for the requested update operation. That is an API-level synchronization behavior, not a complete protocol for atomically publishing multiple records and their metadata. Linux msync reference

Suppose a mapped index contains a payload and a pointer to that payload. If a crash leaves the pointer persisted but the payload incomplete, simply having called a flush somewhere does not establish recovery correctness. Define ordering, validation, and what readers do with an incomplete record. A log, generation marker, checksum, or transactional storage layer may be part of the answer, depending on the requirements.

An interview answer should say what is being guaranteed: another reader can observe bytes, the requested range has been synchronized, or a recoverable application state has been committed. Those are not interchangeable claims. The safe fixture above checks ordinary file readback, not the last guarantee.

Diagnose faults using a four-boundary record

For any failing access, write down the virtual range and protections, the current backing extent, the mapping's sharing mode, and the application's persistence expectations. Add the offset being accessed and the process allowed to change the file.

If the address is outside the mapping or a write violates read-only protection, investigate an address/protection error. If the address is within the mapped range but its file page lies beyond EOF, investigate the backing object and truncation race. If bytes differ across readers, inspect visibility and synchronization before assuming data corruption.

Closing the original file descriptor does not itself invalidate a successful Linux mapping. Conversely, keeping that descriptor open does not prevent another authorized writer from resizing the same object. Name the actual lifetime guarantee instead of treating an open descriptor as a universal safety lock.

This record makes your answer auditable: another engineer can tell which assumption failed and which experiment would confirm it.

Five practice questions for the surrounding boundaries

Practice questionEvidence to produce
Trace Virtual Address Translation Through TLBs, Page Tables, and CachesSeparate a translation-cache miss from a fault that needs operating-system handling.
Explain Virtual Memory Beyond Physical RAMExplain why mapping size and resident memory are different quantities.
Implement the Linux cp Command, Then Explain Its OS and C++ InternalsCompare copying approaches without assuming mmap wins every workload.
Explain and Diagnose a Segmentation FaultClassify address/protection failures separately from the backing-file example.
Design a Durable Key-Value Cache with File-System PersistenceDistinguish write visibility, synchronization, and recoverable commit.

Your next mmap answer should identify the backing object's owner before debating microseconds.

Sources and Further Reading

Sources checked October 4, 2026. The byte-write fixture is safe temporary-file practice; the Linux truncation timeline is a conceptual exercise.