A process calls mmap() to map a large file and then reads the first byte of the mapped region for the first time. What happens?
AThe kernel immediately reads the entire file into physical memory before returning from mmap()
BA page fault occurs, the kernel reads the corresponding file page into a physical frame, updates the page table, and returns control to the process
CThe operating system copies the data into a user-space buffer, just like read() would
DNothing happens until the process calls msync() to load the data
mmap() sets up page table entries for the address range but loads nothing. The first access triggers a page fault — the CPU sees a valid but not-yet-present mapping. The kernel's fault handler recognizes the backing file, reads the relevant page from disk into the page cache (a physical frame), updates the page table to point to it, and resumes the process transparently. This lazy loading is what makes memory-mapped I/O efficient: pages are only fetched when accessed, not pre-loaded speculatively.
Question 2 Multiple Choice
Two processes memory-map the same file with MAP_SHARED. Process A writes to the mapped region. When does Process B see the change?
ANever — each process gets its own private copy of the file data when it calls mmap()
BOnly after Process A calls msync() and Process B calls munmap() and remaps the file
CImmediately, because both processes share the same physical pages in the page cache
DAfter the kernel's writeback daemon flushes the changes to disk and Process B re-reads from disk
MAP_SHARED means both processes map to the same physical pages in the page cache. A write by Process A modifies those pages directly, and since Process B's virtual addresses map to the same physical frames, it sees the change immediately — no IPC mechanism, no disk roundtrip, no explicit synchronization needed. This shared-page-cache mechanism is why memory-mapped files are used for high-performance inter-process communication in databases and servers.
Question 3 True / False
Memory-mapped file I/O can achieve zero-copy reads because the process accesses file data directly in the page cache, avoiding an extra copy into a separate user-space buffer.
TTrue
FFalse
Answer: True
With the traditional read() system call, the kernel reads file data from disk into a kernel buffer, then copies it into the user-space buffer provided by the application — two copies total. With mmap(), the process's virtual page is mapped directly to the physical frame in the page cache. The process reads from that frame without any intermediate copy. For large files or databases performing random index lookups, eliminating this extra copy produces a measurable performance improvement.
Question 4 True / False
Memory-mapped I/O is typically faster than read()/write() and should be preferred for most file access patterns.
TTrue
FFalse
Answer: False
For sequential reads of small files, read()/write() can be faster or comparable — the system call overhead is negligible, and the kernel may apply read-ahead buffering more aggressively. Memory mapping also consumes virtual address space, complicates error handling (disk errors arrive as SIGBUS signals instead of error codes), and provides weaker durability guarantees (dirty pages may not be flushed before a crash without explicit msync()). mmap is best suited for large files, random access patterns, or shared-memory IPC — not universally superior.
Question 5 Short Answer
Explain how the kernel handles a page fault when a process accesses an address in a memory-mapped file region that hasn't been loaded yet, and why this mechanism is preferable to loading the entire file up front.
Think about your answer, then reveal below.
Model answer: When a process accesses an unmapped address in the mmap'd region, the CPU raises a page fault. The kernel's fault handler checks the page table entry, recognizes it is backed by a file (not anonymous memory), reads the corresponding file block into a page cache frame, updates the page table to map the virtual page to that frame, and resumes the faulting instruction. Loading on demand is preferable because large files are rarely accessed in their entirety; only fetching pages that are actually touched avoids loading gigabytes into RAM for a query that touches a few blocks.
The lazy-loading behavior also enables efficient random access: processes can 'open' a multi-gigabyte file via mmap and access any offset directly without first seeking and reading sequentially. The kernel manages the working set automatically — frequently accessed pages stay in the page cache; rarely accessed ones are evicted. This is exactly why database engines use mmap for index structures: they can navigate a large B-tree by following pointers, and the OS transparently loads only the pages traversed.