Multistep Processing of a Program
- compile time: translate source code to machine code
- load time: link the program and load it into memory
- execution time: run the program
Address Binding Timing
- Compile Time
- compiler translates symbolic code into absolute code
- if starting location changes → recompile
- Load Time
- compiler translates symbolic code into relocatable code(
.BS+0x1234)
- when loading, translate to physical address(
0xABCD)
- if starting location changes → reload the code
- Execution Time
- compiler translates symbolic code into logical addresses (virtual-address) code(
0x18)
- even when loading, keep using logical addresses(
0x18)
- special hardware, Memory Management Unit (MMU), is used to map logical to physical addresses
- even CPU don't know the physical address, only use logical address
Memory-Management Unit (MMU)
- hardware device that maps logical addresses to physical addresses
- the user program deals with logical addresses; it never sees the physical addresses
- Divide physical memory into fixed-size blocks called frames
- Divide logical memory into blocks of the same size called pages
- to run a program of size
n pages, need to find n free frames and load the program
- Benefits
- non-contiguous allocation
- no external fragmentation
- limited internal fragmentation
- provide shared memory/page
- Page Table: maps the base of each page (page number) to the base of each frame
- page table only includes pages owned by a process
- a process cannot access memory outside its allocated pages (mem protection)
- page number
p: base address of a page
- frame number
f: base address of a frame
- logical address = page number (
p) + page offset (d)
N bits of p -> can allocate at most 2N pages -> 2N×page size
M bits of d -> page size=2M bytes
- physical address = frame number (
f) + page offset (d)
- Address Translation
p + d; p --MMU-> f; f + d
# of pages: determine the logical memory size of a process
# of frames: depending on the size of physical memory
- free frame linked list: maintained by OS
- Page Size: a power of 2, 512 ~ 16MB, typically 4KB
- too small -> large page table, more pages per process -> more I/O ops for loading pages
- too large -> internal fragmentation
- Page Table
- kept in memory
- PTBR (Page-Table Base Register): the physical address of the page table (used by MMU)
- store in PCB (Process Control Block) during context switch
- With PTBR, each memory reference requires
2 memory accesses -> solved by TLB
- TLB (Translation Lookaside Buffer)
- associative memory: parallel search O(1)
- limited entries: 64 ~ 2048
- cached (page number, frame number) pairs when MMU translating addresses
- TLB hit: get frame number from TLB
- TLB miss: use original by PTBR (2 memory accesses), then update TLB
- flush TLB during context switch
- EMAT (Effective Memory Access Time)
- example: 20ns for TLB lookup + 100ns for memory access
- 70% TLB hit ratio: EMAT=0.7×(20+100)+0.3×(20+2
- Memory Protection: each page is associated with a set of protection bits
- e.g. valid/invalid bit
- valid: the page/frame is in the process's logical/physical address space
- invalid: the page/frame is not in the process's logical/physical address space
- PTLR (Page-Table Length Register): indicates the size of the page table (used by MMU)
- Shared Pages
- reentrant code (pure code): never change during execution, can be shared
- only one copy in physical memory
- multiple virtual addresses map to the same physical address
Page table would be huge and difficult to be loaded. e.g. 4GB (232) logical memory with 4KB (212) page would have 1 million (220) pages table entries. Three solutions:
Hierarchical Paging
- break the page table into multiple levels
- Two-level paging (32-bit address with 4KB page size)
- 10 bits for outer page number → 1K (210) page table entries
- 10 bits for inner page number → 1K (210) page table entries
- 12 bits for offset
d -> 4KB (2) page size
Hashed Page Tables
- commonly-used for address > 32 bits
- virtual page number is hashed into a hash table
- hash table size varies; larger -> smaller chains in each entry
- each entry
- (virtual page number, frame number, next pointer)
- pointer waste memory & traverse linked list waste time
Inverted Page Tables
- no page table per process
- maintains a frame table for the whole memory (one entry per frame)
- each entry: (PID, virtual page number)
- increases memory access time
- each access needs to search the whole frame table
- solution: use hashing for the frame table
- hard to support shared pages !!! Critical