Session 4.4 – Segmentation
Understanding segment-based memory management, segment tables, and segmentation with paging
Learning Objectives
By the end of this session, you will be able to:
- Understand the concept of segmentation and its motivation
- Explain the structure and function of segment tables
- Perform segmented address translation
- Analyze protection and sharing mechanisms in segmentation
- Compare segmentation with paging approaches
- Understand combined segmentation with paging systems
Introduction to Segmentation
Segmentation is a memory management technique that supports the logical view of memory as perceived by users and programmers. Unlike paging, which divides memory into fixed-size blocks, segmentation divides memory into variable-size segments that correspond to logical units.
Motivation
- Matches programmer's view of memory
- Logical organization of programs
- Natural protection boundaries
- Easy sharing of code and data
- Support for growing segments
Challenges
- External fragmentation
- Variable-size allocation complexity
- Memory compaction overhead
- Segment table size variations
- Address translation complexity
User's View vs System's View
User's Logical View
Physical Memory
Segmentation Concepts
In segmentation, a logical address space is divided into segments, each representing a logical unit such as a procedure, array, or data structure.
Key Terminology
- Segment: Variable-size logical unit
- Segment Number: Identifies the segment
- Segment Offset: Address within segment
- Segment Base: Starting physical address
- Segment Limit: Size of the segment
- Segment Table: Maps segments to memory
- STBR: Segment Table Base Register
- STLR: Segment Table Length Register
Common Segment Types
| Segment Type | Contents | Access Patterns | Typical Protection |
|---|---|---|---|
| Code | Executable instructions, functions | Read, Execute | Read-Only, Executable |
| Data | Global variables, constants | Read, Write | Read-Write, No Execute |
| Heap | Dynamically allocated memory | Read, Write, Grow up | Read-Write, No Execute |
| Stack | Local variables, function calls | Read, Write, Grow down | Read-Write, No Execute |
| Shared | Libraries, shared data | Read, Execute/Write | Depends on content |
Segment Organization Example
Process Memory Layout
Segment 0: Code Segment (0-5K) - main() function - helper functions - constant strings Segment 1: Data Segment (0-2K) - global variables - initialized data Segment 2: Heap Segment (grows up) - malloc() allocations - dynamic data structures Segment 3: Stack Segment (grows down) - local variables - function parameters
Physical Memory Allocation
Base: 1400, Limit: 5K
Base: 6700, Limit: 2K
Base: 9300, Limit: 3K
Base: 4200, Limit: 4K
Segment Tables
The segment table maintains information about each segment, including its location in physical memory, size, and access permissions.
Segment Table Entry Structure
Segment Table Entry (64-bit): ┌────────────────────┬─────────────────┬──────────────┐ │ Base Address │ Segment Limit │ Control Bits │ │ 32 bits │ 20 bits │ 12 bits │ └────────────────────┴─────────────────┴──────────────┘ Control Bits: ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ │V│R│W│X│G│U│A│D│T│S│ Reserved │ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─────────┘ V = Valid bit (segment is loaded) R = Read permission W = Write permission X = Execute permission G = Growable segment U = User/System access level A = Accessed recently D = Dirty (modified) T = Type (code/data) S = Shared segment
Segment Table Example
| Segment # | Base Address | Limit (Size) | Permissions | Type |
|---|---|---|---|---|
| 0 | 1400 | 5120 (5K) | R-X | Code |
| 1 | 6700 | 2048 (2K) | RW- | Data |
| 2 | 9300 | 3072 (3K) | RW- | Heap |
| 3 | 4200 | 4096 (4K) | RW- | Stack |
Segment Table Storage
- Location: Main memory (typically)
- STBR: Points to table start
- STLR: Number of segments
- Per-Process: Each process has own table
- Size: Varies with number of segments
Access Validation
- Bounds Check: Offset ≤ Segment Limit
- Permission Check: Read/Write/Execute
- Segment Existence: Valid bit check
- Address Range: Base ≤ Address ≤ Base+Limit
- Protection Fault: Violation handling
Address Translation in Segmentation
Address translation in segmentation involves mapping logical addresses (segment number, offset) to physical addresses using the segment table.
Translation Algorithm
Segmented Address Translation: 1. Parse logical address into (segment#, offset) 2. Check if segment# < STLR (segment table length) 3. Calculate segment table entry address: STE_Address = STBR + segment# × entry_size 4. Read segment table entry from memory 5. Validate segment (check valid bit) 6. Check offset ≤ segment limit 7. Verify access permissions (R/W/X) 8. Calculate physical address: Physical_Address = Base + Offset Logical Address Format: ┌─────────────────┬─────────────────────┐ │ Segment Number │ Offset (d) │ │ (s bits) │ (remaining bits) │ └─────────────────┴─────────────────────┘
Address Translation Process
1. Logical Address
Address: (2, 1024) Segment: 2 Offset: 1024 Interpretation: "Byte 1024 in Segment 2"
2. Segment Table Lookup
Segment 2 Entry: Base: 9300 Limit: 3072 Perms: RW- Checks: ✓ 1024 ≤ 3072 ✓ Valid bit = 1 ✓ Read permitted
3. Physical Address
Calculation: Base + Offset = 9300 + 1024 = 10324 Result: Physical address 10324
Error Conditions
Segmentation Fault
- Offset > Segment Limit
- Invalid segment number
- Segment not valid/loaded
- Access permission violation
Fault Handling
- Generate trap/interrupt
- OS handles the fault
- Terminate process or load segment
- Return control or kill process
Protection and Sharing
Segmentation provides natural boundaries for protection and enables efficient sharing of code and data between processes.
Protection Mechanisms
- Automatic Bounds Checking: Hardware enforced
- Access Control: Read/Write/Execute bits
- Privilege Levels: User vs. System segments
- Type Checking: Code vs. Data segments
- Growing Segments: Stack and heap protection
| Segment | Read | Write | Execute |
|---|---|---|---|
| Code | ✓ | ✗ | ✓ |
| Data | ✓ | ✓ | ✗ |
| Stack | ✓ | ✓ | ✗ |
| Heap | ✓ | ✓ | ✗ |
Sharing Mechanisms
- Code Sharing: Multiple processes, one copy
- Shared Libraries: Dynamic linking
- Data Sharing: Inter-process communication
- Copy-on-Write: Efficient forking
- Memory-Mapped Files: File sharing
Shared Code Example: Process A: Segment 0 → Text Editor Code Process B: Segment 1 → Text Editor Code Process C: Segment 0 → Text Editor Code All point to same physical memory: Base Address: 15000 Only one copy loaded
Code Sharing Example
Process A
Process B
Physical Memory
(Single Copy)
Paging vs Segmentation
Both paging and segmentation solve memory management problems but take different approaches with distinct trade-offs.
| Aspect | Paging | Segmentation |
|---|---|---|
| Block Size | Fixed-size pages (4KB, 8KB) | Variable-size segments |
| User View | Invisible to user | Visible, matches logical structure |
| Address Translation | Page number + offset | Segment number + offset |
| Fragmentation | Internal fragmentation only | External fragmentation |
| Protection | Page-level protection | Natural logical boundaries |
| Sharing | Page-level sharing | Logical unit sharing |
| Growing Structures | Difficult (stack, heap) | Natural support |
| Table Size | Large for big address spaces | Small, varies by program |
| Memory Utilization | Good (no external fragmentation) | May waste space |
| Implementation | Simpler hardware | More complex |
When to Use Paging
- Virtual memory systems
- Large address spaces
- Uniform memory access patterns
- Simplified memory management
- Better memory utilization needed
When to Use Segmentation
- Strong protection requirements
- Code/data sharing needs
- Growing data structures
- Logical program organization
- Smaller address spaces
Segmentation with Paging
Modern systems combine segmentation and paging to leverage the benefits of both approaches while minimizing their drawbacks.
Combined Approach
Two-level address translation: Logical → Segment → Pages → Physical
Address Format (Segmented Paging): ┌─────────────┬─────────────┬─────────────────┐ │ Segment # │ Page # │ Page Offset │ │ (s bits) │ (p bits) │ (d bits) │ └─────────────┴─────────────┴─────────────────┘ Translation Process: 1. Use segment# to index segment table 2. Get page table base for this segment 3. Use page# to index page table 4. Get frame# from page table entry 5. Combine frame# + offset = physical address Benefits: - Logical organization (segmentation) - No external fragmentation (paging) - Flexible protection and sharing - Support for large address spaces
Segmented Paging Architecture
Logical Address
Segment: 1 Page: 2 Offset: 1024 Meaning: "Page 2, byte 1024 in Segment 1"
Segment Table
| Seg | PT Base |
|---|---|
| 0 | 2000 |
| 1 | 4000 |
| 2 | 6000 |
Page Table (Seg 1)
| Page | Frame |
|---|---|
| 0 | 5 |
| 1 | 8 |
| 2 | 3 |
Physical Address
Frame 3 found in page table Physical Addr: 3 × 4096 + 1024 = 12288 + 1024 = 13312
Real-World Examples
Intel x86 (Legacy)
- 16-bit segment selectors
- Global/Local Descriptor Tables
- Segment + paging combination
- Protected mode segmentation
Modern x86-64
- Flat memory model
- Segmentation mostly unused
- Focus on paging
- 64-bit linear addresses
Practical Examples
Segmentation Address Translation
Problem:
Given the segment table below and logical address (1, 1500), find the physical address:
| Segment | Base | Limit | Access Rights |
|---|---|---|---|
| 0 | 2000 | 1500 | R-X |
| 1 | 4500 | 3000 | RW- |
| 2 | 8000 | 2500 | RW- |
Additional scenarios:
- (0, 1000) - Read access
- (1, 3500) - Write access
- (2, 1200) - Execute access
Solution: Address (1, 1500): 1. Segment 1: Base = 4500, Limit = 3000 2. Check bounds: 1500 ≤ 3000 ✓ (Valid) 3. Physical address = Base + Offset = 4500 + 1500 = 6000 Address (0, 1000) - Read access: 1. Segment 0: Base = 2000, Limit = 1500, Access = R-X 2. Check bounds: 1000 ≤ 1500 ✓ 3. Check permission: Read allowed ✓ 4. Physical address = 2000 + 1000 = 3000 Address (1, 3500) - Write access: 1. Segment 1: Base = 4500, Limit = 3000, Access = RW- 2. Check bounds: 3500 ≤ 3000 ✗ (SEGMENTATION FAULT!) Address (2, 1200) - Execute access: 1. Segment 2: Base = 8000, Limit = 2500, Access = RW- 2. Check bounds: 1200 ≤ 2500 ✓ 3. Check permission: Execute NOT allowed ✗ (PROTECTION FAULT!)
Memory Layout Analysis
Compare memory usage between paging and segmentation for a typical program:
Program Characteristics
- Code: 12KB
- Data: 8KB
- Stack: 4KB (max)
- Heap: 6KB (current)
System Parameters
- Page size: 4KB
- Physical memory: 1MB
- Address space: 32-bit
Paging Analysis: Pages needed: ⌈12/4⌉ + ⌈8/4⌉ + ⌈4/4⌉ + ⌈6/4⌉ = 3 + 2 + 1 + 2 = 8 pages Internal fragmentation: (8×4) - 30 = 2KB wasted Page table entries: 2²⁰ = 1M entries (for full 32-bit space) Page table size: 1M × 4 bytes = 4MB per process Segmentation Analysis: Segments needed: 4 (code, data, stack, heap) External fragmentation: Depends on allocation history Segment table entries: 4 entries Segment table size: 4 × 12 bytes = 48 bytes per process Memory Efficiency: Paging: 30KB used, 2KB internal fragmentation (6.7% waste) Segmentation: 30KB used, external fragmentation varies Table Overhead: Paging: 4MB (huge overhead for small programs) Segmentation: 48 bytes (minimal overhead)
Session Summary
Key Concepts
- Segmentation: Variable-size logical memory units
- Segment Tables: Base, limit, and permission mapping
- Address Translation: Segment number + offset → physical
- Protection: Natural boundaries and access control
- Sharing: Efficient code and library sharing
- Combined Systems: Segmentation with paging
Trade-offs
- Advantages: Logical organization, protection, sharing
- Disadvantages: External fragmentation, complexity
- vs Paging: Better for protection, worse for utilization
- Modern Use: Combined with paging systems
- Performance: Table size varies with program structure
Next Session Preview
Session 4.5 will cover Swapping and Relocation, exploring how processes can be moved between memory and storage, dynamic address binding, and relocation techniques for efficient memory management.