π§ L7: Memory Management & Memory Abstraction
Lecture Goal
Understand how the OS manages memory, why we need logical addresses instead of physical ones, and how contiguous memory allocation works (with all its trade-offs).
The Big Picture
Every process thinks it has the entire RAM to itself. How? The OS creates a convincing illusion through memory abstraction.
π© Part 1: Memory Hardware Basics
ποΈ What is RAM, Really?
Physical RAM is just a giant array of bytes. Each byte has a unique index β its physical address.
Physical Memory (simplified):
βββββββ¬ββββββ¬ββββββ¬ββββββ¬ββββββ¬ββββββ
β 0 β 1 β 2 β 3 β ... β n-1 β
βββββββ΄ββββββ΄ββββββ΄ββββββ΄ββββββ΄ββββββ
β
βββ Physical Address (the actual location)
The Problem
If programs use physical addresses directly, they clash. Process A writes to address 1000, Process B writes to address 1000 β data corruption!
π The Memory Hierarchy
The OSβs job is to make slow, large memory feel fast and well-organized for running processes.
flowchart TD subgraph Hierarchy ["β‘ Speed β | π¦ Size β | π° Cost β"] A["CPU Registers<br/>~1 ns | Bytes"] --- B["Cache L1/L2/L3<br/>~10 ns | MB"] B --- C["Main Memory RAM<br/>~100 ns | GB"] C --- D["SSD<br/>~10 ΞΌs | TB"] D --- E["HDD<br/>~10 ms | TB"] E --- F["Tape/Cloud<br/>~seconds | PB"] end style A fill:#ff9999,stroke:#333,stroke-width:2px style B fill:#ffcc99,stroke:#333,stroke-width:2px style C fill:#ffff99,stroke:#333,stroke-width:2px style D fill:#ccff99,stroke:#333,stroke-width:2px style E fill:#99ffcc,stroke:#333,stroke-width:2px style F fill:#99ccff,stroke:#333,stroke-width:2px
| πΆ Level | β‘ Speed | π¦ Size | π° Cost | π‘ Role |
|---|---|---|---|---|
| CPU Registers | ~1 ns | Bytes | Very expensive | Immediate computation |
| Cache | ~10 ns | ~12 MB | Expensive | Frequently used data |
| RAM | ~100 ns | GBs | Moderate | Active programs |
| SSD | ~10 ΞΌs | TBs | Cheap | Persistent storage |
| HDD | ~10 ms | TBs | Very cheap | Bulk storage |
| Off-line | seconds | PBs | Cheapest | Backup/archive |
The 100x Rule
Each level is roughly 100Γ slower than the one above it. This gap shapes everything the OS does with memory.
ποΈ Part 2: Memory Usage of a Process
πΊοΈ Process Memory Layout
A running process has four distinct memory regions arranged in a specific layout.
flowchart TD subgraph PAS ["Process Address Space"] Stack["Stack<br/>Local Variables / Func Calls"] Gap((Free Space)) Heap["Heap<br/>Dynamic Allocation / malloc"] Data["Data<br/>Global / Static Variables"] Text["Text<br/>Compiled Code / Instructions"] Stack -->|Grows Down| Gap Heap -->|Grows Up| Gap Data --- Text end style Stack fill:#f9f,stroke:#333,stroke-width:2px style Heap fill:#bbf,stroke:#333,stroke-width:2px style Data fill:#bfb,stroke:#333,stroke-width:2px style Text fill:#fbb,stroke:#333,stroke-width:2px
The four segments:
| π Segment | π Contents | π Growth | β³ Lifetime |
|---|---|---|---|
| Stack | Local variables, return addresses | β Grows down | Function scope |
| Heap | malloc(), dynamic data | β Grows up | Until free() |
| Data | Global/static variables | Fixed | Program lifetime |
| Text | Compiled instructions | Fixed | Program lifetime |
Stack vs Heap Collision
If Stack grows down and Heap grows up, they can collide in the middle β Stack Overflow or Out of Memory error!
π Part 3: Memory Abstraction
3.1 The Problem with Physical Addresses
What if programs directly used physical addresses (no abstraction)?
flowchart LR A["Process A<br/>wants address 4096"] --> RAM["Physical RAM<br/>address 4096"] B["Process B<br/>wants address 4096"] --> RAM style A fill:#f99 style B fill:#99f style RAM fill:#ff0
| β Pros | β Cons (fatal!) |
|---|---|
| Simple β no translation needed | Clash: Two processes claim the same address |
| Fast β direct memory access | No Isolation: Process B can overwrite Process A |
| Not Relocatable: Program must always load at same address |
Apartment Analogy
Imagine every apartment building in a city labeling rooms as βRoom 1, Room 2β¦β with no building number. Two families in different buildings both claim βRoom 101β β chaos! We need building numbers (abstraction).
3.2 Fix Attempt 1: Address Relocation (Bad Idea β)
When loading Process B at address 8000, add 8000 to every memory reference in its code.
| Why It Fails |
|---|
| Slow load: Must scan and modify every address |
Ambiguous: Is 4096 an address or a constant? Hard to tell! |
| No protection: Still canβt stop Process B from accessing Process Aβs memory |
3.3 Fix Attempt 2: Base + Limit Registers β
A much better approach using hardware assistance:
flowchart LR LA[Logical Address] --> Check{"LA < Limit?"} Check -- No --> Error[Trap: Memory Violation] Check -- Yes --> Add["+ Base Register"] Add --> PA[Physical Address]
Two hardware registers per process:
| Register | Purpose |
|---|---|
| Base Register | Starting physical address of the process |
| Limit Register | Size of the processβs memory region |
How it works:
- Process generates logical address (starts from 0)
- Hardware checks:
logical_address < limit? - If yes:
physical_address = base + logical_address - If no: Trap to OS β memory violation!
Example
Process with Base = 5000, Limit = 3000:
- Logical address 2800 β Valid (2800 < 3000) β Physical = 5000 + 2800 = 7800
- Logical address 3500 β Invalid (3500 β₯ 3000) β Trap!
Foundation of Segmentation
This is exactly how [β[L8|segmentationβ]] works! Each segment is essentially a generalized base+limit register pair.
3.4 Logical Address β The Processβs View
The logical address is how the process sees its own memory β starting from 0, as if it owns all of RAM.
Process's view (logical): Physical RAM:
ββββββββββββββββ ββββββββββββββββ 0
β 0 β β OS β
β 1 β ββmappingβββΊ ββββββββββββββββ€ 256
β ... β β Process A β
β Limit-1 β ββββββββββββββββ€ ...
ββββββββββββββββ β Process B β
ββββββββββββββββ
The Illusion
Every process thinks it has:
- Its own private memory starting at 0
- The entire address space to itself
- No awareness of other processes
π§± Part 4: Contiguous Memory Allocation
Now we need to decide where in physical RAM to place each process.
4.1 Fixed-Size Partitioning
Physical memory is pre-divided into equal-sized slots. Each process gets one slot.
| π Feature | π Fixed Partitioning |
|---|---|
| β Pros | Simple to manage, fast allocation |
| β Cons | Internal fragmentation β wasted space inside a partition |
Hotel Analogy
A hotel with only king-size rooms. A solo traveler books one, but half the room is unused β internal waste.
Partition view:
ββββββββββββββ¬βββββββββββββ¬βββββββββββββ¬βββββββββββββ
β Part. 0 β Part. 1 β Part. 2 β Part. 3 β
β 64 KB β 64 KB β 64 KB β 64 KB β
β [Process A β [Process B β [empty] β [Process C β
β 40 KB] β 64 KB] β β 20 KB] β
β β β β β β β
β 24 KB β β β 44 KB β
β wasted β perfect! β β wasted β
ββββββββββββββ΄βββββββββββββ΄βββββββββββββ΄βββββββββββββ
4.2 Dynamic (Variable-Size) Partitioning
Partitions are created to exactly fit each process. Free regions are called holes.
| π Feature | π Dynamic Partitioning |
|---|---|
| β Pros | No internal fragmentation, flexible |
| β Cons | External fragmentation β total free memory is enough, but split into unusable pieces |
Parking Lot Analogy
Cars park and leave. After a while, you have many small gaps between cars β too small for a new car, even though total gap space is large.
Dynamic View (over time):
T=0: ββββββββββββββ¬βββββββββββββββββββββββββββββββ
β Process A β Free (large hole) β
ββββββββββββββ΄βββββββββββββββββββββββββββββββ
T=1: ββββββββββββββ¬βββββββββββββ¬βββββββββββββββββββ
β Process A β Process B β Free (smaller) β
ββββββββββββββ΄βββββββββββββ΄βββββββββββββββββββ
T=2: ββββββββββββββ¬βββββββ¬βββββββ¬βββββββ¬βββββββ¬βββββββββββββ
β Process A β A β hole β B β hole β Free β
ββββββββββββββ΄βββββββ΄βββββββ΄βββββββ΄βββββββ΄βββββββββββββ
β External fragmentation!
Total free: enough for new process
But no single hole is big enough
4.3 Allocation Algorithms
When a process needs N bytes, which hole do we choose?
| π§ Algorithm | π― Strategy | π Effect |
|---|---|---|
| First-Fit | Take the first hole β₯ N | Fast, but may waste good early holes |
| Best-Fit | Smallest hole β₯ N | Minimizes waste per allocation, but leaves tiny βsplinterβ holes |
| Worst-Fit | Largest hole β₯ N | Leaves larger leftover holes (potentially more reusable) |
Which is best?
In practice, First-Fit often wins β itβs fast and doesnβt produce significantly more fragmentation than Best-Fit.
π€ Part 5: Buddy System
A smarter dynamic allocation scheme that makes splitting and merging efficient.
5.1 Core Idea
Memory is always split into power-of-2 sized blocks. Splitting produces two equal halves β buddies.
flowchart TD A[512 KB Block] --> B[256 KB L] A --> C[256 KB R] B --> D[128 KB L] B --> E[128 KB R] D --> F[64 KB L] D --> G[64 KB R] style A fill:#f9f style B fill:#bbf style C fill:#bbf style D fill:#bfb style E fill:#bfb style F fill:#fbb style G fill:#fbb
How it works:
- Request for 100 KB β need 128 KB block
- Start with 512 KB, split into 256 + 256
- Split 256 into 128 + 128
- Allocate one 128 KB block β 28 KB wasted (internal fragmentation)
The Bit Trick
For a block of size at address , its buddy is found by flipping the -th bit of . This makes merging incredibly fast!
Example: Block at address 8 (size 4). Its buddy is at address 12.
8 = 0b1000
12 = 0b1100 (flip bit 2)
β Mock Exam Questions
Q1: Address Translation
A process has Base = 5000, Limit = 3000. Is logical address 2800 valid? What is the physical address?
Answer
Check: 2800 < 3000? β Yes, valid!
Physical address: 5000 + 2800 = 7800
Note: If the logical address were 3500, it would be invalid (3500 β₯ 3000).
Q2: Fragmentation Types
What is the difference between internal and external fragmentation?
Answer
Type Where Which Scheme Internal Wasted space inside an allocated partition Fixed partitioning External Wasted space between allocated partitions Dynamic partitioning Remember: Internal = inside, External = outside/between.
Q3: Buddy System Allocation
A system uses the Buddy System starting with a 64 KB block. Requests arrive for: 12 KB, 20 KB, 10 KB. Show the allocation.
Answer
- 12 KB β needs 16 KB (next power of 2)
- 20 KB β needs 32 KB
- 10 KB β needs 16 KB
Starting from 64 KB:
- Split 64 KB β 32 KB + 32 KB
- Split one 32 KB β 16 KB + 16 KB (allocate one 16 KB for request 1)
- Allocate one 32 KB for request 2
- Split remaining 16 KB β 8 KB + 8 KB (not enough! Need another 16 KB from remaining 32 KB)
Total internal fragmentation: 4 KB + 12 KB + 6 KB = 22 KB wasted
β οΈ Common Mistakes to Watch Out For
Internal vs. External Fragmentation
Internal = waste inside (fixed scheme). External = waste between (dynamic scheme). Donβt swap these!
Limit Check
The check is
offset < Limit(strictly less than). Ifoffset == Limit, itβs already out of bounds!
Buddy System Power-of-2
If a request is for 100 bytes, you must allocate 128 bytes. You cannot allocate exactly 100.
Base + Limit Direction
Base is where the process starts in physical memory. Limit is the size of the process. Physical address = Base + Logical address (if logical < Limit).
π Connections
| π Lecture | π Connection |
|---|---|
| L1 | OS structure β memory manager is a core OS component |
| L2 | Memory context β the Text, Data, Stack, Heap regions defined here |
| L5 | Threads β all threads share the same memory context |
| L6 | Synchronization β shared memory regions need coordination |
| L8 | Base+Limit leads to segmentation β multiple base+limit pairs for different memory regions |
| L9 | Logical addresses enable virtual memory β pages can live anywhere, even on disk |
| L10 | Memory vs file management β similar allocation problems, different persistence |
The Key Insight
Memory abstraction solves the fundamental problem: how do multiple programs share one RAM without interfering? The answer β give each program its own private address space, translated by hardware.