Memory management is the OS subsystem responsible for tracking which memory is in use, allocating memory to processes, and reclaiming it when processes terminate. A key abstraction is the separation between logical addresses (the address a program generates, also called virtual addresses) and physical addresses (the actual location in RAM). Address binding — mapping logical to physical — can occur at compile time, load time, or execution time; execution-time binding via hardware (the Memory Management Unit, MMU) is used by modern systems because it allows the OS to relocate a process freely. The MMU performs address translation on every memory access, enabling isolation and protection between processes.
Trace how a pointer dereference in a C program becomes a physical memory access: compiler generates logical address, MMU translates, physical RAM is accessed. Then explain why two processes can have the same logical address but different physical locations.
When a program runs, it constantly refers to memory addresses — to read variables, call functions, and access data structures. But here is the key insight: the address a program generates (a *logical* address) is not the address where its data actually lives in RAM (the *physical* address). These two address spaces are intentionally kept separate, and the hardware unit that bridges them on every single memory access is the Memory Management Unit (MMU).
Why go to this trouble? Consider what happens when two programs are both running. Both might generate the address `0x4000` in their own code — perhaps both have a variable at the start of their memory. If these addresses referred directly to RAM, the two programs would collide. Instead, the OS configures the MMU with a different mapping for each process: process A's `0x4000` maps to physical address `0x10000`, while process B's `0x4000` maps to `0x20000`. Each process is isolated in its own logical address space, invisible to the other.
Address binding — the act of deciding where in physical memory a logical address maps — can happen at different times. Compile-time binding bakes physical addresses into the binary, which is inflexible and essentially requires the program to always load at the same location. Load-time binding sets addresses when the program is loaded into memory, which is more flexible but still commits to a fixed location for the entire run. Execution-time binding, used by all modern systems, defers the mapping to the MMU hardware and allows the OS to move a process freely at any time. This flexibility is what makes paging, segmentation, and virtual memory possible.
One critical distinction to keep straight: the MMU is hardware, not software. It is a physical chip (integrated into the CPU on modern processors) that intercepts every memory access and performs the logical-to-physical translation at wire speed. The OS *configures* the MMU by writing mapping tables (page tables) into memory, but the translation itself happens in hardware with no software involvement. This is why the overhead of address translation is negligible — the MMU does it in the same clock cycles as the memory access itself.
Memory management is the foundation on which everything else in an OS rests. Paging divides logical and physical memory into fixed-size pages and frames. Segmentation divides by logical region (code, stack, heap). Virtual memory extends these ideas to allow processes to use more address space than physical RAM exists. All of these build on the core abstraction you have just learned: logical addresses are a program's view of memory, physical addresses are reality, and the MMU is what connects them.