Share on LinkedInBack to deep dives

Linux memory

mmap() Deep Dive

The core idea

mmap() creates a virtual memory mapping. Instead of asking for bytes through read(), a program can map a file or anonymous memory into its address space and then access it with normal loads and stores.

The important part is this: mmap maps address space first; physical memory usually arrives later on first touch. That makes it a close cousin of demand paging and copy-on-write.

Playground 2

Mapping is cheap, first touch does the work

mmap() creates a virtual mapping. The file data usually arrives page-by-page as the program reads or writes.

page 0not presentpage 1not presentpage 2not presentpage 3not present
virtual mapping: 16KBresident pages: 0minor faults: 0

File-backed mappings

With a file-backed mapping, virtual pages correspond to bytes in a file. When the program first reads a mapped page, the CPU faults, the kernel finds or loads the relevant file page in the page cache, and the page table is updated.

After that, reading the mapped memory can be as simple as reading RAM. The file abstraction is still there, but the program is using regular memory instructions.

Playground 1

MAP_PRIVATE vs MAP_SHARED

Both modes can read file-backed pages. The difference appears when a process writes.

File page cache

page 0: Apage 1: Bpage 2: C

Process mapping

page 0: Apage 1: Bpage 2: C

Both mappings start by reading the same file-backed page cache.

MAP_PRIVATE vs MAP_SHARED

MAP_PRIVATE gives copy-on-write behavior. Reads can come from the file-backed page cache, but writes become private to the process. The file is not changed by those private writes.

MAP_SHARED makes writes visible through the shared mapping. The modified page can later be written back to the file, either through msync() or normal kernel writeback.

Playground 3

/proc/<pid>/maps visualizer

A process address space is a set of virtual memory areas. mmap adds one more VMA to that list.

text00400000-0040b000r-xp

program code

heap01c12000-01c33000rw-p

malloc/brk area

file mmap76f41000-76f45000r--p

mapped file

libc76f65000-770b9000r-xp

shared library

stack7efdf000-7f000000rw-p

thread stack

What shows up in /proc maps

Every process is made of virtual memory areas, or VMAs. Code, heap, stack, shared libraries, anonymous mappings, and file-backed mappings all appear as ranges in /proc/<pid>/maps.

This is one of the best debugging tools for mmap problems. It shows address ranges, permissions, sharing mode, offsets, and the mapped file path when one exists.

Minimal mmap shape

int fd = open("data.bin", O_RDWR);
char *p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

p[0] = 'X';      // regular store, but backed by mapped file page
msync(p, len, MS_SYNC);
munmap(p, len);
close(fd);

The pointer returned by mmap() is just a virtual address. The kernel keeps the mapping metadata; the MMU and page table do the translation when the program touches the memory.

What to remember

  • mmap creates VMAs: it reserves virtual address ranges with permissions and backing information.
  • First touch matters: page faults populate the mapping with real frames.
  • MAP_PRIVATE: writes create private copies and do not update the underlying file.
  • MAP_SHARED: writes affect the shared mapping and can be flushed back to the file.
  • /proc maps: use it to see what your process has mapped and with what permissions.