Virtual memory Implementations
Base and Bound Registers
Maps a contiguous virtual address region to a contiguous physical address region
- Add
BASE value to virtual address
Protection and Isolation
- If translated address is bigger than
BASE + BOUND,
then Raise Protection Exception
Implementation details
BASE and BOUND are protected
- Only code in Ring 0 can modify
BASE and BOUND
- Prevents processes from modifying their
BASE and BOUND
- Each CPU has one
BASE and BOUND register
BASE and BOUND must be saved and restored during context switch
Advantages
- Simple implementation
- Processes can be loaded at arbitrary fixed addresses
- Protection and Isolation
Limitations
- Processes can overwrite their own code
- No sharing memory
- Even executing same process, load all process on memory
- Process memory cannot grow dynamically
- Lead to internal fragmentation
Internal Fragmentation
- Empty space leads to internal fragmentation
- What if we don't allocate enough?
- Increasing
BOUND after the process is running doesn't help
- It doesn't move the stack from the heap
Segmenation
Having a single BASE and BOUND means
- Code, stack and heap are all in one memory region
- Leads to internal fragmentation
- Prevents dynamically growing the stack and heap
Idea
- Give each process several pairs of base/bounds
- Each pair = Segment
Details
- A process get split into several segments
- Support >3 segments per process (code, heap and stack)
- Each process views its segments as a contiguous region of memory
- But in physical memory, segments can be placed in arbitrary locations
Segments and Offsets
- Split virtual addresses into a segment indes and an offset
- Ex) 14-bit addresses

- Segment size is 212= 4KB
- 4 possible segments per process
Separation
- OS manages segments and indexes
- Creates segments for new processes
- Builds a table mapping segments indexes to base address and bounds
- Swaps out the tables and segment registers during context switches
- Free segments when process is terminated
- CPU translates virtual address to physical address
Example
Segment permissions
- Permissions on segments (r, w, x)
x86 segments
- segment : offset notation
mov [ds:eax], 42 // move 42 to the data segment, offset by the value in eax
Segmentaiton Fault
- Try to read/write memory outside a segment
- Example
char buf[5];
strcpy(buf, "Hello World");
return 0;
- When we call func, we save return address
Hello World can overwrite the return address
So that can cause segmentation fault
Sharing memory
- If the code and shared data are the same,
can share by setting base and bound same
Advantages
- All the advantages of base and bound
- Better support for sparse address spaces
- Segment sizes are variable
-> Prevents internal fragmentation
- Support shared memory
- Per segment permissions
External Fragmentation
Variable size segments can lead to external fragmentation
- Even there is enough free memory to start a new process,
memory is fragmented
- Compaction can fix the problem, but it is expensive
Paging
Segments lead to external fragmentation
Idea
- Physical memory is divided into frames of fixed sizes
Example 1)
- 64-byte virtual address space
- 16 byte per page

Example 2)
- 32-bit address space & page size = 4KB
- How many pages?
- 232/212=220=1M
- How many bits to select the physical page?
- Page table entry is 4 bytes large
- Each process needs 4MB of page table
- 100 processes = 400MB of page tables
Problems
- Majority of page table is empty = The table is sparse
Page table Implementation
- OS creates the page table for each process
- Page tables are stored in kernel memory
- OS stores a pointer to the page table in register in the CPU (CR3 register in x86)
- On context switch, OS swaps the pointer
- CPU translates virtual address into physical address
x86 Page Table Entry

- PTE are 4 bytes
- W - writable bit - writable or read-only?
- U/S - user/supervisor bit - can user processes access?
- Bits related to swapping
- P - present bit - is in physical memory?
- A - accessed bit - has read recently?
- D - dirty bit - has written recently?
Copy on Write
- Recall
fork() is too slow
- Rather than copy all of parents,
create a new page table for the child that maps to all of the parents
- Mark all pages as read-only
- If parent or child writes a page, exception will be triggered
- OS catches the exception, makes a copy of the target page, then restarts the write operation
- All unmodified data is shared
- Mark all pages read-only
- Child try to write on stack,
Exception occurs and OS makes a copy of the target page,
Parent page table is modified into other region that copied original stack
Advantages
- All the advantages of segmentation
- Better for sparse address spaces
- Each page is small
- Limits internal fragmentation
- All pages are the same size
- Prevents external fragmentation
Problems
- Page tables are huge
- and the majority of the PTE are empty or invalid
- Page tables are slow

- 4 instructions are read from memory
- 1 memory access writes in memory
- 5 page table lookup
- Each memory access must be translated
- And the page tables are in memory