Session 4.1: Memory Management Fundamentals
Understanding memory hierarchy, address spaces, allocation strategies, and the foundation of memory management systems
Learning Objectives
By the end of this session, you will be able to:
- Understand the memory hierarchy and its impact on system performance
- Distinguish between logical and physical address spaces
- Explain different memory allocation strategies and their trade-offs
- Understand memory protection and sharing mechanisms
- Analyze address binding and program loading processes
- Explain the role and operation of the Memory Management Unit (MMU)
- Understand dynamic loading and linking concepts
- Calculate memory utilization and fragmentation metrics
Key Concept
Memory management is the process of controlling and coordinating computer memory, assigning portions called blocks to various running programs to optimize overall system performance. It involves both hardware and software components working together to provide an abstraction of unlimited, fast memory to applications.
Why Memory Management Matters
Performance
Efficient memory usage directly impacts system speed and responsiveness
Protection
Prevents processes from accessing unauthorized memory regions
Sharing
Enables safe sharing of memory between cooperating processes
Abstraction
Provides illusion of large, contiguous memory space to applications
Memory Hierarchy
Computer systems use a memory hierarchy to balance cost, speed, and capacity. Understanding this hierarchy is crucial for effective memory management.
The Memory Pyramid
Memory Hierarchy (Top = Fastest, Bottom = Largest)
Detailed Memory Characteristics
| Memory Type | Access Time | Typical Size | Cost per GB | Volatility | Management |
|---|---|---|---|---|---|
| CPU Registers | 0.1-1 ns | 32-64 registers | Very High | Volatile | Compiler/CPU |
| L1 Cache | 1-2 ns | 16-64 KB | Very High | Volatile | Hardware |
| L2 Cache | 3-10 ns | 256 KB - 2 MB | High | Volatile | Hardware |
| L3 Cache | 10-30 ns | 4-32 MB | High | Volatile | Hardware |
| Main Memory (RAM) | 50-100 ns | 4-128 GB | Medium | Volatile | OS Memory Manager |
| SSD Storage | 0.1-1 ms | 256 GB - 8 TB | Low | Non-volatile | File System |
| HDD Storage | 5-20 ms | 1-20 TB | Very Low | Non-volatile | File System |
Memory Management Focus
Operating system memory management primarily deals with main memory (RAM), which serves as the working space for active processes. The OS must efficiently allocate, protect, and manage this limited but crucial resource.
Performance Impact
Memory Access Time Comparison: - CPU Register: 1 cycle (baseline) - L1 Cache: 3-4 cycles (3-4x slower) - L2 Cache: 10-20 cycles (10-20x slower) - L3 Cache: 30-50 cycles (30-50x slower) - Main Memory: 200-300 cycles (200-300x slower) - SSD: 100,000+ cycles (100,000x+ slower) - HDD: 10,000,000+ cycles (10M+ slower) Example: If CPU register access = 1 second - L1 Cache access = 3-4 seconds - Main Memory access = 3-5 minutes - SSD access = 1-2 days - HDD access = 4-6 months
Address Spaces
An address space defines the range of valid addresses that a process can use. Understanding different types of address spaces is fundamental to memory management.
Types of Address Spaces
Logical Address Space
- Definition: Addresses generated by the CPU during program execution
- Also called: Virtual addresses
- Range: 0 to max (determined by CPU architecture)
- Visibility: Seen by the running program
- Example: 32-bit system: 0x00000000 to 0xFFFFFFFF
Physical Address Space
- Definition: Actual addresses in main memory hardware
- Also called: Real addresses
- Range: 0 to max physical memory
- Visibility: Hidden from programs
- Example: 8GB RAM: 0x00000000 to 0x1FFFFFFFF
Address Space Layout
Typical Process Address Space Layout
Logical Address Space
Physical Memory Layout
Address Space Segments Explained
Text Segment
- Content: Executable code (machine instructions)
- Properties: Read-only, shareable between processes
- Size: Fixed at compile time
- Location: Usually at low addresses
Data Segment
- Content: Initialized global and static variables
- Properties: Read-write, process-specific
- Size: Fixed at compile time
- Example:
int global_var = 42;
BSS Segment
- Content: Uninitialized global and static variables
- Properties: Initialized to zero by OS
- Size: Fixed at compile time
- Example:
int uninitialized_array[1000];
Stack Segment
- Content: Function calls, local variables, return addresses
- Properties: LIFO structure, grows downward
- Size: Dynamic, limited by stack limit
- Management: Automatic (compiler-generated code)
Heap Segment
- Content: Dynamically allocated memory (malloc, new)
- Properties: Grows upward, managed by programmer/runtime
- Size: Dynamic, limited by available memory
- Management: Explicit allocation and deallocation
Address Space Example
C Program Example:
#include <stdio.h>
#include <stdlib.h>
int global_initialized = 100; // Data segment
int global_uninitialized; // BSS segment
static int static_var = 50; // Data segment
void function_example() { // Text segment
int local_var = 10; // Stack segment
static int static_local; // BSS segment
int *heap_ptr = malloc(sizeof(int) * 100); // Heap segment
printf("Addresses:\n");
printf("Code (function): %p\n", function_example);
printf("Global init: %p\n", &global_initialized);
printf("Global uninit: %p\n", &global_uninitialized);
printf("Local var: %p\n", &local_var);
printf("Heap memory: %p\n", heap_ptr);
free(heap_ptr);
}
Typical Output (addresses will vary):
Code (function): 0x400526
Global init: 0x601040
Global uninit: 0x601044
Local var: 0x7fff5fbff6ac
Heap memory: 0x1c3e010
Analysis:
- Code addresses are low (0x400000 range)
- Global variables in middle (0x601000 range)
- Stack addresses are high (0x7fff... range)
- Heap addresses vary (allocated by memory manager)
Memory Allocation Strategies
Memory allocation determines how the operating system assigns memory blocks to processes. Different strategies have varying trade-offs in terms of efficiency, fragmentation, and implementation complexity.
Contiguous Memory Allocation
Contiguous Allocation
Each process is allocated a single contiguous block of memory. Simple but can lead to fragmentation issues.
1. Fixed Partitioning
Fixed Partition Scheme
Equal-Size Partitions
Unequal-Size Partitions
Advantages
- Simple implementation
- Fast allocation/deallocation
- No external fragmentation
- Predictable memory layout
Disadvantages
- Internal fragmentation
- Limited number of processes
- Poor memory utilization
- Fixed partition sizes
2. Dynamic Partitioning
Variable-Size Partitions
Partitions are created dynamically based on process requirements. Eliminates internal fragmentation but introduces external fragmentation.
Dynamic Allocation Algorithms
First Fit
Strategy: Allocate the first hole that is big enough
Advantage: Fast allocation
Disadvantage: May waste large holes
Algorithm: 1. Start from beginning 2. Find first hole ≥ size 3. Allocate from that hole 4. Split if hole > size Time: O(n)
Best Fit
Strategy: Allocate the smallest hole that is big enough
Advantage: Minimizes wasted space
Disadvantage: Slower, creates small holes
Algorithm: 1. Search entire list 2. Find smallest hole ≥ size 3. Allocate from that hole 4. Split if necessary Time: O(n)
Worst Fit
Strategy: Allocate the largest hole
Advantage: Leaves large remaining holes
Disadvantage: Wastes large holes quickly
Algorithm: 1. Search entire list 2. Find largest hole 3. Allocate from that hole 4. Split remaining space Time: O(n)
Allocation Algorithm Comparison
Example: Memory with holes of sizes [100KB, 500KB, 200KB, 300KB, 600KB] Request: Allocate 212KB First Fit: - Check 100KB: Too small - Check 500KB: ✓ Fits! Allocate here - Result: [100KB, 288KB remaining, 200KB, 300KB, 600KB] Best Fit: - Check all holes: 100KB(no), 500KB(yes), 200KB(no), 300KB(yes), 600KB(yes) - Best fit: 300KB (smallest that fits) - Result: [100KB, 500KB, 200KB, 88KB remaining, 600KB] Worst Fit: - Check all holes: 100KB(no), 500KB(yes), 200KB(no), 300KB(yes), 600KB(yes) - Worst fit: 600KB (largest available) - Result: [100KB, 500KB, 200KB, 300KB, 388KB remaining] Performance Analysis: - First Fit: Fastest allocation, moderate fragmentation - Best Fit: Slowest allocation, least wasted space per allocation - Worst Fit: Slow allocation, may preserve large holes longer
Fragmentation Analysis
Internal Fragmentation
Definition: Wasted space within allocated memory blocks
Cause: Allocated block larger than requested
Example: Process needs 18KB, gets 20KB partition → 2KB internal fragmentation
External Fragmentation
Definition: Free memory scattered in small, unusable holes
Cause: Allocation and deallocation patterns
Example: Total free space = 50KB, but largest hole = 15KB
Compaction
Memory Compaction
Process of moving allocated blocks to eliminate external fragmentation
Memory Compaction Process
Before Compaction
After Compaction
Compaction Benefits
- Eliminates external fragmentation
- Creates large contiguous free space
- Improves memory utilization
- Enables larger allocations
Compaction Costs
- High CPU overhead
- Requires relocatable programs
- Temporary system pause
- Complex implementation
Memory Protection and Sharing
Memory protection ensures that processes cannot access memory outside their allocated regions, while sharing mechanisms allow controlled access to common resources.
Hardware Protection Mechanisms
Base and Limit Registers
Base Register: Contains starting physical address of process
Limit Register: Contains size of process memory
Protection Check:
if (logical_address >= limit_register)
generate_trap(SEGMENTATION_VIOLATION);
else
physical_address = base_register + logical_address;
Base-Limit Protection
Base: 300KB
Limit: 120KB
Valid Range: 300KB - 420KB
Memory Sharing
Shared Memory Benefits
Multiple processes can access the same physical memory region, enabling efficient communication and resource sharing while reducing memory usage.
Code Sharing
- Read-only program code
- Shared libraries (DLLs)
- System utilities
- Reduces memory footprint
Data Sharing
- Shared data structures
- Inter-process communication
- Requires synchronization
- Read-write access control
Library Sharing
- Dynamic link libraries
- Runtime linking
- Version management
- Memory efficiency
Address Binding and Program Loading
Address binding determines when logical addresses are mapped to physical addresses. Different binding times offer various trade-offs between flexibility and performance.
Types of Address Binding
Compile-Time Binding
When: During compilation
Addresses: Absolute addresses generated
Flexibility: None - fixed memory location
Use Case: Embedded systems, MS-DOS .COM files
Example: mov ax, [1000h] ; Fixed address jmp 2000h ; Fixed jump target Pros: Fast execution Cons: No relocation
Load-Time Binding
When: During program loading
Addresses: Relocatable code adjusted
Flexibility: Can load at different locations
Use Case: Traditional operating systems
Example: mov ax, [R+100h] ; Relocatable jmp R+200h ; R = base address Pros: Relocatable Cons: Fixed during execution
Execution-Time Binding
When: During program execution
Addresses: Dynamic translation via MMU
Flexibility: Can move during execution
Use Case: Modern virtual memory systems
Example:
mov ax, [100h] ; Logical address
; MMU translates to physical
Pros: Full flexibility
Cons: Hardware overhead
Program Loading Process
Loading Process Steps
1. Load
Copy program from storage to memory
2. Allocate
Assign memory space for program
3. Link
Resolve external references
4. Relocate
Adjust addresses for actual location
Logical vs Physical Addresses
Logical Address
- Generated by CPU during execution
- Also called virtual address
- Seen by the running program
- Independent of physical memory
- Range: 0 to max logical space
Physical Address
- Actual address in memory hardware
- Also called real address
- Hidden from programs
- Limited by physical memory size
- Range: 0 to max physical memory
Address Translation
Physical Address = Base Register + Logical Address
Address Translation Example: Process Information: - Base Register: 14000 - Limit Register: 3000 - Logical Address: 346 Translation Process: 1. Check bounds: 346 < 3000 ✓ (valid) 2. Calculate physical: 14000 + 346 = 14346 3. Access memory at physical address 14346 If logical address ≥ limit register: - Generate segmentation fault - Terminate process or handle exception
Memory Management Unit (MMU)
The MMU is a hardware component that handles address translation and memory protection, enabling efficient virtual memory systems.
MMU Functions
Address Translation
- Converts logical to physical addresses
- Uses translation tables
- Hardware-accelerated process
- Transparent to programs
Memory Protection
- Enforces access permissions
- Prevents unauthorized access
- Generates protection faults
- Supports privilege levels
MMU Operation
MMU Address Translation Process
Dynamic Loading and Linking
Dynamic loading and linking allow programs to load code and link libraries at runtime, improving memory efficiency and flexibility.
Dynamic Loading
Concept
Routines are loaded into memory only when they are called, reducing memory usage and startup time.
Advantages
- Reduced memory usage
- Faster program startup
- Better memory utilization
- Support for large programs
Disadvantages
- Runtime loading overhead
- Complex implementation
- Potential loading delays
- Dependency management
Dynamic Linking
| Aspect | Static Linking | Dynamic Linking |
|---|---|---|
| Link Time | Compile/build time | Runtime |
| Library Code | Included in executable | Separate library files |
| Memory Usage | Higher (duplicate libraries) | Lower (shared libraries) |
| Executable Size | Larger | Smaller |
| Dependencies | Self-contained | Requires library files |
| Updates | Requires recompilation | Library updates sufficient |
| Flexibility | Less flexible | More flexible (can update modules independently) |
| Performance | Faster startup, possible higher memory use | Slower on first use, but more efficient overall |
Compaction Example
Before Compaction
Total Free: 90KB, Largest: 40KB
After Compaction
Total Free: 90KB, Largest: 90KB
Compaction Challenges: 1. Cost: Must relocate all processes and update address references 2. Time: System may be unavailable during compaction 3. Complexity: Need to update all pointers and addresses 4. Frequency: When to perform compaction? Solutions: - Hardware relocation registers (base + limit) - Virtual memory systems (eliminate need for compaction) - Garbage collection techniques - Non-contiguous allocation methods
Memory Protection and Sharing
Memory protection ensures that processes cannot access memory outside their allocated regions, while memory sharing allows controlled access to common resources.
Memory Protection Mechanisms
1. Base and Limit Registers
Hardware Protection Scheme
CPU with Protection Hardware
CPU Registers:
┌─────────────────┐
│ Base Register │ → 300400
├─────────────────┤
│ Limit Register │ → 120900
├─────────────────┤
│ Logical Address │ → 346
└─────────────────┘
Protection Check:
if (logical_address >= limit)
trap to OS (segmentation fault)
else
physical_address = base + logical_address
Memory Layout
Protection Algorithm
Hardware Protection Check (performed on every memory access): 1. CPU generates logical address (LA) 2. Check: if (LA >= Limit Register) - Generate trap/interrupt - OS handles segmentation violation - Typically terminates process 3. If valid: Physical Address = Base Register + LA 4. Access memory at physical address Example: Base = 300400, Limit = 120900 Logical Address = 346 Check: 346 < 120900? ✓ Valid Physical Address = 300400 + 346 = 300746 Invalid Example: Logical Address = 130000 Check: 130000 < 120900? ✗ Invalid → TRAP
2. Memory Protection Bits
| Protection Bit | Meaning | Operations Allowed | Example Use |
|---|---|---|---|
r-- |
Read Only | Load instructions | Code segment, constants |
rw- |
Read-Write | Load, store instructions | Data segment, stack |
r-x |
Read-Execute | Load, jump instructions | Code segment |
rwx |
Read-Write-Execute | All operations | Self-modifying code |
--- |
No Access | None (trap on access) | Guard pages, freed memory |
Memory Sharing
Shared Memory Benefits
- Efficiency: Reduce memory usage by sharing common code/data
- Communication: Fast inter-process communication mechanism
- Consistency: Single copy ensures data consistency
- Performance: Avoid copying large data structures
Types of Memory Sharing
Code Sharing
Scenario: Multiple processes using same program
Requirements:
- Code must be reentrant (read-only)
- No self-modifying code
- Position-independent or same virtual addresses
Example: Text Editor - 3 users running same editor - Code segment: 2MB - Without sharing: 3 × 2MB = 6MB - With sharing: 1 × 2MB = 2MB - Memory saved: 4MB (67% reduction)
Data Sharing
Scenario: Processes sharing data structures
Requirements:
- Synchronization mechanisms needed
- Consistent virtual addresses
- Proper access control
Example: Shared Database Buffer - Multiple database processes - Shared buffer pool: 100MB - Synchronization: Semaphores/locks - Benefits: Consistent cache, reduced I/O
Shared Memory Implementation
Shared Memory Layout
Process A Address Space
Process B Address Space
Physical Memory
Protection Violations and Handling
Common Protection Violations:
1. Segmentation Fault (SIGSEGV):
- Access outside allocated memory
- Write to read-only memory
- Execute non-executable memory
2. Bus Error (SIGBUS):
- Misaligned memory access
- Access to unmapped memory
3. Stack Overflow:
- Stack grows beyond limit
- Infinite recursion
OS Response to Violations:
1. Hardware generates trap/interrupt
2. OS trap handler invoked
3. Identify violating process
4. Check if violation is recoverable:
- Recoverable: Expand stack, load page
- Non-recoverable: Terminate process
5. Send signal to process (SIGSEGV, SIGBUS)
6. Process can handle signal or be terminated
Example Handler:
void segfault_handler(int sig) {
printf("Segmentation fault detected!\n");
printf("Cleaning up resources...\n");
exit(1);
}
signal(SIGSEGV, segfault_handler);
Address Binding and Program Loading
Address binding is the process of mapping program addresses to actual memory locations. This can happen at different times during program execution.
Types of Address Binding
Compile Time
When: During compilation
Characteristics:
- Absolute addresses generated
- Program must load at specific location
- Fast execution (no translation)
- Inflexible memory placement
Example:
Source: int x = 10;
Compiled: LOAD 0x401000
STORE 0x401004
Fixed at address 0x401000
Load Time
When: When program is loaded
Characteristics:
- Relocatable code generated
- Addresses adjusted at load time
- More flexible than compile-time
- Still fixed during execution
Example:
Relocatable: LOAD R+0
STORE R+4
At load time: R = 0x500000
Result: LOAD 0x500000
STORE 0x500004
Execution Time
When: During program execution
Characteristics:
- Dynamic address translation
- Process can move during execution
- Requires hardware support (MMU)
- Most flexible approach
Example:
Logical: LOAD 0x1000
STORE 0x1004
Runtime: Base = 0x300000
Physical: LOAD 0x301000
STORE 0x301004
Program Loading Process
From Source Code to Execution
Detailed Loading Steps
Step-by-Step Loading Process
1. Compilation Phase: - Source code → Object code - Symbols marked for relocation - External references noted 2. Linking Phase: - Combine multiple object files - Resolve external references - Create symbol table - Generate executable file 3. Loading Phase: a) Allocate memory space b) Copy program from disk to memory c) Relocate addresses (if needed) d) Initialize program counter e) Transfer control to program Example Executable File Structure: ┌─────────────────────┐ │ Header │ ← File format info ├─────────────────────┤ │ Text Segment │ ← Executable code ├─────────────────────┤ │ Data Segment │ ← Initialized data ├─────────────────────┤ │ Symbol Table │ ← Debug information ├─────────────────────┤ │ Relocation Info │ ← Address fixup data └─────────────────────┘
Dynamic Linking and Loading
Dynamic vs Static Linking
Static linking includes all library code in executable. Dynamic linking loads libraries at runtime.
Static Linking
Process: All libraries included at link time
Advantages:
- Self-contained executable
- No runtime dependencies
- Faster program startup
- Predictable behavior
Disadvantages:
- Large executable files
- Memory waste (duplicate libraries)
- Must relink for library updates
Dynamic Linking
Process: Libraries loaded at runtime
Advantages:
- Smaller executable files
- Shared libraries save memory
- Easy library updates
- Plugin architecture support
Disadvantages:
- Runtime dependencies
- Slower program startup
- Version compatibility issues
Shared Libraries Implementation
Dynamic Library Loading Process:
1. Program Startup:
- OS loader examines executable
- Identifies required shared libraries
- Checks if libraries already in memory
2. Library Loading:
- If not loaded: Load library into memory
- If already loaded: Map to process address space
- Update process page tables
3. Symbol Resolution:
- Resolve function/variable addresses
- Update program's jump tables
- Perform relocations if necessary
Example: Linux Shared Library (.so)
Program: myapp
Library: libmath.so.1
Loading sequence:
1. execve("myapp")
2. Loader reads ELF header
3. Finds dependency: libmath.so.1
4. Searches library paths: /lib, /usr/lib, LD_LIBRARY_PATH
5. Maps library into process address space
6. Resolves symbols (sqrt, sin, cos, etc.)
7. Updates Procedure Linkage Table (PLT)
8. Transfers control to main()
Memory Layout After Loading:
┌─────────────────────┐ ← High addresses
│ Stack │
├─────────────────────┤
│ Shared Libraries │ ← libmath.so, libc.so
├─────────────────────┤
│ Heap │
├─────────────────────┤
│ BSS │
├─────────────────────┤
│ Data │
├─────────────────────┤
│ Text │
└─────────────────────┘ ← Low addresses
Position Independent Code (PIC)
Position Independent Code
Code that can execute correctly regardless of its absolute address in memory. Essential for shared libraries.
Non-PIC Code (Position Dependent):
mov eax, [0x401000] ; Absolute address
call 0x402000 ; Absolute function address
PIC Code (Position Independent):
mov eax, [ebx+offset] ; Relative to base register
call function@PLT ; Through procedure linkage table
PIC Implementation Techniques:
1. Relative Addressing:
- Use PC-relative addressing modes
- Calculate addresses relative to current instruction
2. Global Offset Table (GOT):
- Table of addresses for global variables
- Accessed via base register
3. Procedure Linkage Table (PLT):
- Indirect function calls
- Allows lazy binding of function addresses
Example PIC Function:
get_global_var:
call get_pc ; Get current PC
get_pc:
pop ebx ; EBX = current PC
add ebx, offset_to_GOT ; EBX = GOT base
mov eax, [ebx+var_offset] ; Load variable address
ret
Benefits of PIC:
- Shared libraries can load at any address
- Multiple processes can share same library code
- Reduces memory usage
- Enables ASLR (Address Space Layout Randomization)
Logical vs Physical Addresses
Understanding the distinction between logical and physical addresses is crucial for memory management systems.
Address Types Comparison
| Aspect | Logical Address | Physical Address |
|---|---|---|
| Definition | Address generated by CPU during execution | Actual address in physical memory |
| Also Known As | Virtual address | Real address, absolute address |
| Generated By | CPU/Program | Memory Management Unit (MMU) |
| Visibility | Visible to user program | Hidden from user program |
| Address Space | Logical address space | Physical address space |
| Range | 0 to max (CPU architecture) | 0 to max (physical memory size) |
| Modification | Can be changed by user | Cannot be changed by user |
Address Translation Process
Logical to Physical Address Translation
Simple Address Translation Schemes
1. Direct Mapping (Compile-time Binding)
One-to-One Mapping
Characteristics: - Logical and physical addresses are identical - Used in simple systems, embedded systems - No address translation overhead - Limited flexibility Example: Logical Address: 0x1000 Physical Address: 0x1000 (same) Memory Layout: ┌─────────────────────┐ 0xFFFF │ Available Memory │ ├─────────────────────┤ 0x2000 │ Process Memory │ ├─────────────────────┤ 0x1000 │ Operating System │ └─────────────────────┘ 0x0000
2. Base Register Translation
Base + Offset
Hardware Requirements: - Base register (relocation register) - Adder circuit in MMU Example: Base Register: 0x14000 Logical Address: 0x0346 Physical Address: 0x14000 + 0x0346 = 0x14346 Translation Process: 1. CPU generates logical address (0x0346) 2. MMU adds base register value (0x14000) 3. Result is physical address (0x14346) 4. Memory access at physical address Benefits: - Simple hardware implementation - Supports process relocation - Protection through limit register - Fast translation (single addition)
Address Space Examples
32-bit System Example
Logical Address Space:
- Size: 2^32 = 4 GB
- Range: 0x00000000 to 0xFFFFFFFF
- Per-process: Each process sees 4GB
Typical Layout:
0xFFFFFFFF ┌─────────────────┐
│ Kernel Space │ 1GB
0xC0000000 ├─────────────────┤
│ User Space │ 3GB
│ │
│ Stack │
│ ↓ │
│ │
│ ↑ │
│ Heap │
│ BSS │
│ Data │
│ Text │
0x00000000 └─────────────────┘
Physical Memory:
- Actual RAM: 512MB, 1GB, 2GB, etc.
- Managed by OS memory manager
- Shared among all processes
64-bit System Example
Logical Address Space:
- Size: 2^64 = 16 EB (exabytes)
- Range: 0x0000000000000000 to
0xFFFFFFFFFFFFFFFF
- Practical: Usually 48-bit (256TB)
Typical Layout:
0xFFFFFFFFFFFFFFFF ┌─────────────┐
│ Kernel │
0xFFFF800000000000 ├─────────────┤
│ Unused │
0x00007FFFFFFFFFFF ├─────────────┤
│ User Space │
│ │
│ Stack │
│ ↓ │
│ │
│ ↑ │
│ Heap │
│ BSS │
│ Data │
│ Text │
0x0000000000000000 └─────────────┘
Advantages:
- Huge address space
- No address space exhaustion
- Better security (ASLR)
- Future-proof design
Address Translation Performance
Translation Overhead Analysis
Performance Considerations: 1. Translation Frequency: - Every memory access requires translation - Instruction fetch: ~1 per instruction - Data access: 0-2 per instruction - Total: 1-3 translations per instruction 2. Hardware Translation (Base + Limit): - Time: 1-2 CPU cycles - Overhead: ~5-10% performance impact - Implementation: Simple adder circuit 3. Software Translation: - Time: 10-100 CPU cycles - Overhead: 50-200% performance impact - Implementation: OS routine call 4. Optimization Techniques: - Translation Lookaside Buffer (TLB) - Caching recent translations - Parallel translation and memory access - Specialized MMU hardware Example Performance Impact: Without MMU: 100 MIPS (Million Instructions Per Second) With MMU: 90-95 MIPS (5-10% overhead) Memory Access Pattern: Instruction: LOAD R1, [R2+100] 1. Fetch instruction: Translate PC → Physical 2. Decode instruction 3. Calculate address: R2+100 (logical) 4. Translate data address: Logical → Physical 5. Access memory at physical address 6. Load data into R1 Total translations: 2 (instruction + data)
Memory Management Unit (MMU)
The Memory Management Unit (MMU) is a hardware component responsible for translating logical (virtual) addresses generated by the CPU into physical addresses in main memory. It also enforces memory protection, isolation, and access control between processes.
Key MMU Functions
- Address Translation: Converts virtual addresses to physical addresses using hardware mechanisms (e.g., base-limit registers, page tables).
- Memory Protection: Prevents processes from accessing memory regions outside their allocation.
- Access Control: Enforces permissions (read, write, execute) on memory regions.
- Isolation: Ensures that processes cannot interfere with each other's memory.
- Support for Virtual Memory: Enables features like paging and segmentation.
MMU Operation Diagram
MMU translates virtual addresses to physical addresses and enforces protection.
Base-Limit Register Example
if (logical_address >= limit) {
// Address out of bounds: trap to OS
raise_exception("Segmentation Fault");
} else {
physical_address = base + logical_address;
// Access memory at physical_address
}
- Base Register: Start of process memory in physical RAM
- Limit Register: Size of process memory
- Protection: Any access outside [base, base+limit) is trapped
MMU with Paging
Virtual Address (VA) = [Page Number | Offset] Physical Address (PA) = [Frame Number | Offset] Translation Steps: 1. Extract page number from VA 2. Use page number to index into page table 3. Get frame number from page table entry 4. Combine frame number with offset to form PA 5. Access memory at PA
- Page Table: Data structure mapping virtual pages to physical frames
- TLB (Translation Lookaside Buffer): Cache for recent address translations to speed up access
MMU Performance Considerations
- Address translation can add overhead to every memory access
- Hardware optimizations (e.g., TLB) minimize performance impact
- Page faults (when a page is not in memory) cause significant delays
Summary Table: MMU Features
| Feature | Description |
|---|---|
| Address Translation | Virtual → Physical address mapping |
| Protection | Prevents illegal memory access |
| Isolation | Separates process address spaces |
| Access Control | Enforces read/write/execute permissions |
| Support for Virtual Memory | Enables paging, segmentation, and swapping |
Dynamic Loading
Dynamic loading is a technique where a program loads routines or modules into memory only when they are needed, rather than loading everything at program startup. This approach helps reduce the initial memory footprint and can improve overall system efficiency.
How Dynamic Loading Works
- When a program starts, only the main routine is loaded into memory.
- Other routines (e.g., error handlers, infrequently used features) are kept on disk.
- When the program needs a routine, it loads it from disk into memory at runtime.
- This is typically managed by the operating system or a dynamic loader within the program.
Benefits:
- Reduces memory usage by loading only what is needed.
- Allows for larger programs to run on systems with limited memory.
- Enables updates or patches to routines without recompiling the entire program.
Key Concept
Dynamic loading is especially useful for large applications and operating systems, where not all features are used all the time. It is a foundation for advanced techniques like dynamic linking and shared libraries.
Example: Dynamic Loading in C
// Example: Using dlopen() and dlsym() for dynamic loading (POSIX)
#include <dlfcn.h>
void *handle = dlopen("libmath.so", RTLD_LAZY);
if (handle) {
double (*cosine)(double) = dlsym(handle, "cos");
if (cosine) {
printf("cos(2.0) = %f\n", cosine(2.0));
}
dlclose(handle);
}
This code loads a math library at runtime and calls the cos function only if needed.
Dynamic Loading vs. Static Loading
| Aspect | Static Loading | Dynamic Loading |
|---|---|---|
| When Loaded | At program start | At runtime, when needed |
| Memory Usage | Higher (all routines loaded) | Lower (only needed routines loaded) |
| Flexibility | Less flexible | More flexible (can update modules independently) |
| Performance | Faster startup, possible higher memory use | Slower on first use, but more efficient overall |
Session Summary
Key Takeaways:
- Memory Hierarchy: Understanding the speed-capacity trade-offs from registers to storage
- Address Spaces: Distinction between logical and physical addresses and their management
- Memory Allocation: Fixed vs dynamic partitioning, allocation algorithms, and fragmentation
- Protection Mechanisms: Base-limit registers, protection bits, and access control
- Address Binding: Compile-time, load-time, and execution-time binding strategies
- MMU Operations: Hardware-based address translation and protection enforcement
- Dynamic Loading: On-demand loading for improved memory efficiency
Study Tips:
- Practice address translation calculations
- Understand fragmentation types and solutions
- Work through memory allocation examples
- Analyze performance trade-offs
- Review MMU hardware concepts
Critical Concepts:
- Memory Hierarchy: Cache → RAM → Storage performance gaps
- Address Translation: Logical to physical mapping mechanisms
- Fragmentation: Internal vs external fragmentation causes and solutions
- Protection: Hardware-enforced memory access control
- Sharing: Code and data sharing between processes
Practical Applications:
- Operating system memory managers
- Virtual memory systems
- Embedded system memory optimization
- Database buffer management
- Application memory profiling
Next Session:
Session 4.2: Paging and Virtual Memory
Page-based memory management, virtual memory concepts, and demand paging systems