Introduction to Linux Memory Management: Summary of Christopher Lameter (Jump Trading) Talk
MM101: Introduction to Linux Memory Management
This post provides a comprehensive, structured summary of the talk “MM101: Introduction to Linux Memory Management” by Christopher Lameter from Jump Trading LLC.
In this talk, Christopher goes back to the absolute basics of operating system memory management, explaining the physical and logical architectures underneath the Linux kernel. This covers everything from page frame mappings, page faults, process memory layouts, swap space mechanics, overcommit settings, to high-performance low-latency engineering optimization guidelines.
1. The Fundamental Unit of Memory: Physical RAM & Pages
The Linux kernel does not deal with physical memory as a single linear address range. Instead, it divides RAM into fixed-size chunks called pages.
- Pages and Page Frame Numbers (PFN)
- Page Frame: A physical slot in RAM, typically 4KB in size. Think of physical RAM as a giant file cabinet, and each drawer slot is a 4KB page frame.
- Physical PFN (Page Frame Number): A unique index (from 0 to N, depending on memory size) representing each page frame in physical memory. A physical address is specified by the PFN combined with an offset within that page (e.g., page frame 12, offset 10).
- Frame Count Scale: A machine with 4GB of RAM contains approximately 1 million ((4 \times 10^9 / 4096)) page frames. In modern systems with terabytes of memory, managing hundreds of millions of page frames becomes a major scalability challenge for the kernel.
- Page Sizes
- Intel x86/x86_64 Architecture: Has historically defaulted to 4KB pages since the 1970s and 80s.
- Other Architectures: IBM POWER and some ARM platforms support much larger page sizes (e.g. 64KB), which drastically reduces the page count and mitigates metadata management overhead.
2. Virtual Memory & Page Tables
To enforce security, isolate applications, and overcome physical limitations, the Memory Management Unit (MMU) in hardware cooperates with the operating system to create Virtual Memory.
[Virtual Address Space]
(Process A) ---> [Page Table A] --+---> [Physical Memory (RAM)]
(Process B) ---> [Page Table B] --|---> (Isolated PFN mappings)
+---> (Shared pages point to same PFN)
- Process Isolation via Page Tables
- Each running process gets its own logical, private address space.
- The mapping between a process’s virtual addresses and actual physical PFNs is stored in a data structure called a Page Table.
- Since page tables are process-specific, Process A and Process B can refer to the exact same virtual memory address (e.g.,
0x400000) but end up pointing to completely different physical page frames (e.g., PFN 6 vs PFN 90). This prevents processes from interfering with each other and forms the foundation of modern OS security.
- On-Demand Paging
- When a program starts, the kernel does not load the entire binary file into physical RAM. Instead, page table entries (PTEs) are left empty.
- Physical memory is only allocated when the CPU actually attempts to execute or read from a specific virtual address. This is called on-demand paging.
mmapMemory Allocation Timing: Callingmmap()does not allocate physical memory immediately. It merely reserves a range of virtual addresses and maps it to a file. The physical pages are only allocated dynamically (via demand paging) when the process first accesses the mapped region.
- Page Fault Mechanics
- The Trap: When the CPU tries to access a virtual address that has no valid mapping in the process’s page table, the hardware MMU raises a Page Fault interrupt, halting the CPU and transferring control to the kernel.
- Major Page Fault: Occurs when the requested data is not present in RAM and must be read from disk (either from the original binary file or from the swap partition). This involves slow disk I/O.
- Minor Page Fault: Occurs when the data is already in RAM (e.g., in the kernel’s page cache or allocated during a fresh memory request) but has not yet been mapped into the process’s page table. The kernel simply populates the page table entry, which is a fast memory-only operation.
3. Process Memory Maps & Page Sharing
Every process is allocated a standard virtual address layout composed of distinct segments managed by the OS.
- Process Memory Layout
- Binary/Code (Text Segment): Holds the executable CPU instructions. This mapping is read-only.
- Stack: Grows downward (from high to low addresses) to store local variables, function arguments, and return addresses.
- Heap: Grows upward to support dynamic memory allocation (via
malloc,brk, etc.). - Shared Libraries: The memory area where shared library binaries (e.g.,
glibc) are mapped.
- Page Sharing
- If multiple processes run the same executable or use the same shared libraries, the kernel saves RAM by loading only a single copy of the code pages into physical memory.
- Each process’s page table points to these shared physical pages. To prevent corruption, these pages are marked as read-only.
- Independent Permissions on Shared Pages: Even when multiple processes’ virtual addresses point to the same physical page frame (PFN), the permission flags (R/W/X) in their respective Page Table Entries (PTEs) can differ. For instance, Process A can map a shared page as
Read/Writewhile Process B maps it asRead-only. If Process B attempts to write to it, the CPU will trigger a page fault due to the permission violation.
- Copy-on-Write (COW)
- Concept: If a process attempts to write to a shared read-only page, the MMU triggers a fault.
- Action: The kernel intercepts this, allocates a brand new physical page, copies the original data into it, updates the writing process’s page table to point to this new page, and grants write permissions. The other processes continue using the original shared page.
- Permission Violation & Exception Handling: The CPU’s hardware MMU checks page table permissions in real time. If a process attempts an operation that violates these permissions (e.g. writing to a Read-only page), the MMU raises a hardware exception, transferring control to the kernel. The kernel then decides whether to: 1) perform a Copy-on-Write (COW) and assign write access, 2) allocate a page via normal demand paging, or 3) terminate the process with a
SIGSEGVsignal if the access was illegal. - Fork Optimization: This is heavily utilized when a process calls
fork(). Instead of duplicating the entire memory space of the parent, the kernel simply copies the page tables and marks all pages as read-only (COW). Memory is only allocated when either process actually modifies a page, reducing memory footprint and maximizing speed.
4. Swapping & Memory Reclamation
When physical RAM runs low, the operating system must free up pages to satisfy incoming allocation requests. This process is called Memory Reclamation.
- Reclamation Strategies by Page Type
- File-backed Pages: Pages mapped directly to a file on disk (such as binary code or page cache data). Since their source is stored on disk, the kernel can safely invalidate the page table mapping and discard the page immediately. If the process touches it again, it is re-read from disk via a page fault.
- Anonymous Pages: Pages that have no file backing (such as heap allocations, program stacks, or modified private data). These cannot be discarded. To reclaim them, the kernel must write their contents to a dedicated storage area before freeing the physical RAM.
- Swapping
- The process of writing anonymous pages to a dedicated storage device (the Swap Space) on disk and invalidating their page table entries to reclaim physical memory.
- If the process accesses swapped-out memory, a page fault occurs, forcing the kernel to pause execution and read the data back into RAM (Swap In).
- Excess swapping severely degrades system performance due to disk I/O speeds, leading to thrashing, where the system spends all its time reading and writing to swap rather than executing code.
- The Zero Page Optimization
- Programs often allocate massive chunks of memory (e.g., gigabytes) and initialize them to zero.
- Rather than dedicating physical pages of zeros immediately, Linux maps all these virtual pages to a single, read-only physical page of zeros: the Zero Page.
- The system only allocates real physical memory (via Copy-on-Write) when the program actually writes a non-zero value to a specific page. This allows a process to successfully map 5GB of zeroed arrays while consuming only 4KB of physical RAM.
5. Page Cache & Dirty Pages
To bridge the speed gap between CPU and storage, the Linux kernel uses RAM as a cache buffer for file access, managed through the Page Cache.
- Read Optimization: Page Cache & Read-Ahead
- Page Cache: Once a file is read from disk, its pages are stored in RAM. Subsequent reads to the same file are served instantly from memory, avoiding disk I/O.
- Read-Ahead: When a program reads a section of a file, the kernel assumes it will continue reading sequentially. It proactively reads ahead (often fetching 512KB at once) in the background. This dramatically reduces latency on physical disks by grouping reads and reducing disk head movement.
- Write Optimization: Dirty Pages & Writeback
- Dirty Page: A page in the Page Cache that has been modified by an application but has not yet been synchronized to the underlying storage device.
- Writeback: The background daemon (e.g., flusher threads) periodically scans the page cache, identifies dirty pages, writes them back to disk, and marks them as clean.
mmapModified Data Writeback: Modifying memory values within a shared file mapping immediately marks the corresponding physical pages as dirty in the page cache. The kernel’s background writeback threads eventually sync these pages to disk via filesystems and storage drivers.- Sync Commands: If a power failure occurs before dirty pages are written back, data is lost. Applications use the
sync,fsync, ormsyncsystem calls to force the kernel to flush all dirty pages to disk immediately, ensuring data consistency for databases and filesystems.
6. System Memory Monitoring: /proc/meminfo Deep Dive
The virtual filesystem /proc/meminfo is the primary source of memory metrics on Linux, utilized by tools like free, top, and vmstat.
| Metric | Description | Key Insight |
|---|---|---|
| MemTotal | Total physical RAM available. | The absolute amount of RAM detected by the kernel. |
| MemAvailable | An estimate of how much memory is available for starting new applications. | Calculated by summing free memory and immediately reclaimable page caches, representing the true usable headroom. |
| Cached | Memory footprint of the Page Cache. | RAM spent storing file data from disk. Most of this can be immediately freed if applications need memory. |
| SwapCached | Memory that has been written to swap but is still present in physical RAM. | If RAM becomes tight, these pages can be evicted instantly without requiring another write to disk, optimizing reclamation. |
| Active / Inactive | Recently used memory vs. memory untouched for a long period. | Managed via an LRU-like list. Inactive pages are the first targets for swap-out or reclamation. If an inactive page is accessed, the kernel promotes it back to the Active list. |
| PageTables | Memory consumed by the page table structures themselves. | For large programs mapping terabytes of virtual memory, the page table hierarchy itself (PTE overhead) can consume hundreds of megabytes of RAM. |
| Dirty | Total memory waiting to be written to disk. | A non-zero value indicates uncommitted writes. Emergency shutdowns during high Dirty values risk data corruption. |
| Writeback | Memory actively being written back to disk. | Temporarily spikes during large file copies or sync operations. |
7. Process-Level Memory Monitoring & Resource Limits
Tracking how individual processes utilize memory is critical for debugging and resource allocation.
/proc/<PID>/statusMemory Fields- VMPeak: The peak virtual memory size the process has occupied during its lifecycle.
- VMSize: The current virtual memory size mapped by the process.
- VMLck: The amount of memory locked in physical RAM (using
mlock), preventing it from being swapped out. - VMRSS (Resident Set Size): The actual amount of physical RAM the process is consuming.
- VMAnon: The physical RAM consumed by anonymous memory (heaps/stacks) belonging to this process.
- VMSwap: The amount of this process’s memory currently residing on the swap partition. A high value suggests the process is bottlenecked by swap activity.
- Accurate Process Memory Footprint Measurement (smaps & PSS)
- RSS Limitations: Because RSS (Resident Set Size) includes shared pages (such as shared libraries like
libc.so), simply adding up the RSS of all processes will result in a sum much larger than the actual physical memory occupied. - PSS (Proportional Set Size): A metric that scales the size of shared pages proportionally among all processes sharing them. For instance, if a 4MB physical page is shared by 4 processes, PSS attributes 1MB of that page to each process. Monitoring PSS via
/proc/<PID>/smapsprovides the most accurate estimation of a process’s true physical memory footprint.
- RSS Limitations: Because RSS (Resident Set Size) includes shared pages (such as shared libraries like
- Resource Constraints via
ulimit- To prevent runaway processes from consuming all system RAM (and triggering the Out-of-Memory / OOM killer), shell administrators use
ulimit. - Administrators can limit virtual memory size, locked memory limits (
ulimit -l), stack sizes, and CPU runtimes to enforce strict multi-tenant isolation.
- To prevent runaway processes from consuming all system RAM (and triggering the Out-of-Memory / OOM killer), shell administrators use
8. Kernel Virtual Memory Tuning & Overcommit
The behavior of the Linux memory subsystem is highly configurable via virtual files located in /proc/sys/vm/.
- Overcommit Configuration (
/proc/sys/vm/overcommit_memory)- Controls how the kernel responds when a process requests virtual memory that exceeds available physical RAM and swap combined.
0(Heuristic Overcommit - Default): The kernel heuristically evaluates whether the request is “reasonable” based on standard process memory usage, denying extreme over-allocations while permitting moderate overcommit.1(Always Overcommit): The kernel accepts all memory requests blindly. A process can map 100GB on a 4GB system. The system will run normally until the process actually writes to those pages, causing the system to crash or thrash to a halt.2(Strict Don’t Overcommit): Strict enforcement. The total virtual memory allocated cannot exceed[Swap Size] + ([Physical RAM] * overcommit_ratio / 100). Allocations that cross this limit immediately fail with an out-of-memory error inside the application (mallocreturnsNULL).
- Background Flush Controls
dirty_writeback_centisecs: How often the background writeback daemon wakes up (measured in hundredths of a second) to write dirty pages to disk (e.g.200centiseconds = 2 seconds).dirty_background_ratio: The percentage of total system memory that can be dirty before background writeback begins (typically set to 5–10%).dirty_ratio: The maximum percentage of memory that can be dirty before the process generating the writes is blocked and forced to write back its own pages to disk before continuing (typically 40–60%).
9. Low-Latency Memory Optimization & Q&A Tips
Christopher Lameter concludes the session by sharing specialized optimizations for low-latency systems (e.g., electronic trading) to bypass OS-induced jitter.
mmapvs. Standard File I/O (fwrite/write)- File I/O: Induces context switches to kernel space and involves data copies between user-space and kernel-space buffers.
mmap: Directly maps the file into the process’s address space. Reading and writing to the file becomes a simple pointer operation. If the data is already in the page cache, it bypasses the OS entirely, avoiding system call overhead.- Conditional Speed (Fast vs. Slow):
mmapis extremely fast when target pages are already loaded in RAM (Page Cache Hits) because it completely bypasses system call overhead. However, if the page is missing and triggers a Page Fault, it forces disk I/O and kernel intervention, creating a significant latency spike.
- Preventing Latency Spikes: Pre-allocation (
MAP_POPULATEandmlock)- Page faults during runtime introduce unpredictable latency spikes.
MAP_POPULATE: Instructs the kernel to populate the page table entries and load the file into RAM at the time of themmapcall, ensuring all page faults are handled upfront rather than during critical path execution.mlock/mlockall: Locks the specified memory pages in physical RAM. This guarantees the pages are never swapped out or evicted, ensuring constant access times.
- Direct Memory Access (DMA)
- How It Works: DMA is a hardware mechanism that allows peripherals to transfer data directly to and from system RAM without CPU intervention. The CPU issues a command to the device controller, the device handles the transfer, and then notifies the CPU via an interrupt when finished. This frees up the CPU from copying data byte-by-byte.
- Common DMA Devices: Modern high-speed devices (NICs, NVMe/SSD controllers, GPUs) default to DMA for efficiency. CPU-driven copying or Polling is only used in niche legacy drivers.
- TLB (Translation Lookaside Buffer) Caching
- Hardware Address Cache: Looking up translation entries in RAM-based page tables for every virtual address is slow. The CPU caches recent virtual-to-physical translations in a hardware cache called the TLB.
- TLB Hit vs. Miss: Address translation is nearly instant on a TLB Hit, but a TLB Miss forces the CPU to walk the page tables in RAM and update the TLB, introducing latency.
- Huge Pages (HugeTLB): To prevent frequent TLB misses in memory-intensive applications, developers use Huge Pages (HugeTLB) in 2MB or 1GB increments instead of 4KB. This decreases the number of translation mappings, keeping more entries cached inside the TLB.
10. Summary: End-to-End Virtual Memory Flow
This sequence diagram illustrates the lifecycle of mapping, accessing, faulting, modifying, and flushing files back to storage.
sequenceDiagram
autonumber
actor App as Application
participant MMU as Hardware (MMU)
participant Kernel as Linux Kernel (OS)
participant Cache as Page Cache (RAM)
participant Disk as Disk (Storage)
Note over App, Disk: 1. Initial Mapping and Access
App->>Kernel: Invoke mmap() system call (reserves virtual address space)
Kernel-->>App: Return mapped address (no physical RAM allocated yet)
App->>MMU: Attempt to read from mapped address
MMU->>Kernel: Entry not present in Page Table -> Page Fault triggered
Note over Kernel, Disk: 2. Fault Handling and Disk I/O
Kernel->>Cache: Look up page in Page Cache
alt Page not in cache (Major Page Fault)
Kernel->>Disk: Request block read from storage to RAM (DMA)
Disk-->>Cache: Load block into page frame
else Page already in cache (Minor Page Fault)
Note over Cache: Mark page ready for mapping
end
Note over Kernel, MMU: 3. Page Table Mapping and TLB Update
Kernel->>Kernel: Map physical Page Frame Number (PFN) to process Page Table
Kernel->>MMU: Load PTE into TLB (Update translation cache)
Kernel-->>App: Resume interrupted instruction
App->>MMU: Access memory (TLB Hit -> High-speed address translation)
Note over App, Disk: 4. Data Modification and Asynchronous Writeback
App->>MMU: Attempt to write to mapped address
MMU->>Cache: Modify memory value & mark page as Dirty
Note over Kernel: Dirty limit/expiration reached (triggers background writeback)
Kernel->>Disk: Issue writeback sync command
Disk->>Cache: Transfer data via DMA and write to storage
Kernel->>Cache: Re-mark page status as Clean
Leave a comment