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.
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: CProcess mapping
page 0: Apage 1: Bpage 2: CBoth 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.
00400000-0040b000r-xpprogram code
01c12000-01c33000rw-pmalloc/brk area
76f41000-76f45000r--pmapped file
76f65000-770b9000r-xpshared library
7efdf000-7f000000rw-pthread 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.