This project implements a virtual memory paging system with support for both swap-backed and file-backed pages. It uses a clock (second-chance) page replacement algorithm, supports copy-on-write, and maintains separate page tables for each process. It is designed for a simulated operating system or OS-level coursework environment.
- Pinned Memory: Newly created swap-backed pages initially point to a single read-only zero page until modified.
- Eager Swap Reservation:
vm_createfails and returns-1if insufficient swap space exists.
- Page Fault Handling:
- Triggered when accessing a virtual page with invalid permissions (e.g., R == W == 0).
- Clock Queue (Second Chance):
- Per physical page, maintains:
referenced bitdirty bit
- Per physical page, maintains:
- Arena:
- Each process has an "arena" representing its private virtual address space managed by the pager.
- Swap-backed vs. File-backed Differences:
- File-backed pages may be reloaded from disk, while swap-backed pages must be preserved during eviction.
struct PMB {
bool ref_b; // Referenced bit
bool dirty_b; // Dirty bit
};map_table:hashmap<uint32_t, PMB>— physical memory → reference/dirty infopage_table:page_table_entry_t*— current page tableall_pt:hashmap<pid, unique_ptr<pair<uint, page_table_entry_t*>>>infile_vm:hashmap<page_table_entry_t*, pair<char*, uint>>file_vm_map:hashmap<string, vector<pair<uint, page_table_entry_t*>>>core_map:hashmap<uint, vector<page_table_entry_t*>>— physical page → VM entriesclock_queue:queue<uint32_t>— stores physical page numbers for eviction
bound: arena upper limitpcnt: total physical page countblcnt: total swap block countpined: pinned page countcurr_pid: currently active process
- Initializes the memory system
- Pins the zero page
- Initializes the clock queue and page metadata
- Copies parent’s arena into child
- Allocates new page table
- Duplicates relevant page table entries
- Handles copy-on-write setup
- Switches active process context
- Updates page table base register
- Updates
curr_pidandbound
- Maps a new page:
- File-backed: associates with file and block
- Swap-backed: reserves swap space
- Adds a new page to the current process’s page table
- Sets up file-backed pinning if necessary
- Handles page faults
- Invalid address → error
- Pinned page write → allocate real page and copy
- Copy-on-write → duplicate page
- Infile page → reload from file
- Eviction via clock queue if necessary
- Updates reference/dirty bits
- Frees all physical memory and swap blocks associated with the process
- Cleans up data structures
- Page eviction
- Free page allocation
- Process destruction
- Forking and context switching
- Swap and file write behavior
- Reserve-check for swap-backed pages
- Read pinned pages
- Copy-on-write
- Fault on file not in memory
-
vm_to_stringfault test - Different block, same file
- File not found
- Mapping during multiple phases
- Forking in different phases
- Support for delayed actual memory allocation until access
- Read-only sharing until write
- Handled in
vm_fault - Update page table permissions and metadata
- File-backed page reuse improved
- Ghost page writes flushed correctly
- Dirty/ref bit management fixed
- Filename read permission issues resolved
- Memory leak and page table copy overhead addressed
- Integer overflow guards added
- Only allocate physical memory in
alloc() - Only free memory in
destroy() - Use hashmaps for flexible and dynamic memory tracking
- Ensure IO operations are interruptible for correctness under context switching
- Track corner cases like:
- Mapping while evicting
- Forking during I/O
- Copy-on-write across forked processes
- Check reference and dirty bit correctness on each access
- Log page table changes and core map status
- Use assertion-heavy test cases for edge scenarios
- Simulate frequent context switches to surface IO bugs
- Track memory usage to prevent leaks or overflow