Memory Mapping (Address Translation)
Modern operating systems provide each process with an isolated, private address space through a mechanism known as virtual memory. When a CPU executes an instruction, it operates using virtual addresses (VA), but the actual hardware memory bus requires physical addresses (PA) to access data in RAM.
The core mission of memory mapping is to facilitate this translation. This is a highly coordinated effort between hardware (the Memory Management Unit) and the operating system kernel to ensure that address translation is not only reliable and efficient but also secure through strict isolation and permission enforcement.
To understand how this mechanism works, we must first define the fundamental building blocks:
- Virtual Address (VA): The address used by the CPU and the application software. It provides an abstraction of a large, contiguous memory space.
- Physical Address (PA): The actual hardware address used to access cells in the physical RAM.
- Page: A fixed-size block of the virtual address space. In most modern architectures, the standard page size is 4KB.
- Page Frame: The corresponding fixed-size block in physical memory. A virtual page is mapped to a physical page frame.
- Page Table Entry (PTE): A data structure entry that stores the mapping between a virtual page and a physical page frame, along with metadata like access permissions.
- Memory Management Unit (MMU): The specialized hardware component within the CPU responsible for performing the actual address translation.
- Translation Lookaside Buffer (TLB): A high-speed hardware cache that stores recently used address translations to accelerate the process.
Address Structure and Mathematical Mapping
Memory is not treated as a single monolithic block but is divided into discrete units. Using a 4KB page size as a standard example, the address is split into two distinct parts: the page number and the offset.
Since $2^{12} = 4096$, the lower 12 bits of an address represent the offset within a page. The remaining upper bits represent the page number. The relationship can be expressed as follows:
Virtual Address = Virtual Page Number (VPN) | Page Offset
Physical Address = Physical Page Frame Number (PFN) | Page Offset
During translation, the offset remains unchanged because the relative position of the data within a page is identical to its position within a physical frame. The MMU's primary job is to replace the VPN with the PFN:
PA = (PFN << 12) | offset
In a 32-bit system utilizing a two-level page table hierarchy, the virtual address is typically partitioned into three segments to allow for more efficient memory usage:
[31:22] Page Directory Index (PDE)
[21:12] Page Table Index (PTE)
[11:0] Page Offset
The Address Translation Workflow
When the CPU requests a memory access, the MMU follows a specific sequence to resolve the address:
- CPU Request: The CPU issues a virtual address.
- TLB Lookup: The MMU first checks the TLB.
- TLB Hit: If the translation is found in the TLB, the PFN is retrieved immediately, and the process continues with minimal latency.
- TLB Miss: If the translation is not in the TLB, the MMU must perform a page table walk. It starts from the root page directory (pointed to by a control register like
CR3in x86 orTTBRin ARM). - PTE Retrieval: The MMU traverses the hierarchy to find the final Page Table Entry (PTE).
- Validation: The MMU checks the PTE's valid bit (is the page in RAM?) and permission bits (does the process have the right to read/write/execute?).
- Address Construction: If valid, the PFN is extracted and concatenated with the original offset to form the Physical Address.
- TLB Update: The new translation is cached in the TLB to speed up future accesses to the same page.
- Exception Handling: If the PTE is invalid or permissions are violated, the hardware triggers a page fault or a segmentation fault, handing control to the operating system.
A Concrete Example
Let's trace a specific 32-bit address through a two-level translation process.
Given:
- Virtual Address (VA):
0x00403ABC - Page Size: 4KB
Step 1: Deconstruct the VA
- PDE Index:
(0x00403ABC >> 22) & 0x3FF = 1 - PTE Index:
(0x00403ABC >> 12) & 0x3FF = 3 - Offset:
0x00403ABC & 0xFFF = 0xABC
Step 2: Consult the Tables
Suppose the Page Directory Entry at index 1 points to a page table located at 0x20000000. Within that page table, we look at the entry at index 3.
Assume the value of PTE[3] is 0x00012067.
Step 3: Extract PFN and Construct PA
The lower 12 bits (0x067) are flags (e.g., Present, Writable, User). The remaining bits represent the PFN: 0x00012.
The final Physical Address is:
PA = (0x00012 << 12) | 0xABC
= 0x00012000 | 0xABC
= 0x00012ABC
The virtual address 0x00403ABC successfully maps to the physical address 0x00012ABC.
Performance and Error Handling
The Role of the TLB
The TLB is critical for system performance. Without it, every single memory access would require multiple additional memory accesses just to walk the page tables, effectively crippling the CPU's speed. A high TLB hit rate ensures that address translation happens at near-zero overhead.
Page Faults: The Engine of Demand Paging
A page fault occurs when the CPU cannot resolve a virtual address via the PTE. This is not always a fatal error; it is often a core feature of modern memory management:
- Demand Paging: The OS may mark a page as "not present" to save RAM. When the process tries to access it, a page fault occurs, and the OS loads the data from disk into a new physical frame.
- Swap/Virtual Memory: If physical RAM is full, the OS moves inactive pages to the disk (swap space). A page fault is used to bring them back when needed.
- Copy-on-Write (CoW): When a process forks, the OS maps the same physical pages to both processes but marks them as read-only. A write attempt triggers a fault, allowing the OS to copy the page and give each process its own unique version.
- Invalid Access: If a process attempts to access an address it doesn't own, the OS issues a Segmentation Fault (SIGSEGV), typically terminating the process.
Memory Protection and Security
Address translation is the primary line of defense in modern computing. Every PTE contains permission bits that the MMU enforces at the hardware level:
- Present bit: Indicates if the page is currently in physical RAM.
- Read/Write (R/W) bit: Determines if the page is read-only or writable.
- User/Supervisor (U/S) bit: Controls whether user-mode processes can access the page or if it is reserved for the kernel.
- Execute Disable (NX/XD) bit: Prevents code execution from data pages (a vital defense against buffer overflow attacks).
- Accessed/Dirty bits: Used by the OS to track page usage and determine which pages to swap out.
Practical Observation: The mmap Connection
When a programmer uses the mmap system call, they are essentially telling the kernel: "I want this file or this memory region to be mapped to this range of virtual addresses."
Crucially, mmap is often lazy. The kernel does not immediately allocate physical RAM or load the file into memory. Instead, it simply creates a Virtual Memory Area (VMA) record. The actual physical mapping only occurs when the program first touches the memory, triggering a page fault that the kernel then resolves.
On Linux systems, you can observe these mappings for any running process by inspecting the /proc filesystem:
cat /proc/self/maps
This command reveals the virtual address ranges, their permissions (rwxp), and the files or objects they are mapped to, providing a window into the complex abstraction managed by the MMU.
Summary
Memory mapping and address translation form the bedrock of modern computing. By decoupling the programmer's view of memory from the physical hardware, the system achieves process isolation, efficient memory utilization through demand paging, and robust security through hardware-enforced permissions. The synergy between the MMU's speed, the TLB's efficiency, and the OS's intelligence allows us to run massive, complex applications on limited physical hardware.