operating systems30 min

Virtual Memory

How the OS gives each process the illusion of unlimited memory

0/9Not Started

Why This Matters

Every process on your computer believes it has access to a vast, contiguous block of memory all to itself. In reality, physical RAM is limited and shared by dozens of processes. The OS creates this illusion through virtual memory, a system that translates virtual addresses into physical ones and seamlessly moves data between RAM and disk.

Virtual memory is why your laptop can run a browser with 50 tabs, a code editor, Spotify, and Slack simultaneously without any of them knowing the others exist. It is also why your system slows to a crawl when you open too many applications: the OS starts swapping pages to disk, and disk is thousands of times slower than RAM.

Define Terms

Visual Model

Page 0
Page 1
Page 2
Page 3
Page Table
Frame 0
Frame 1
Frame 2
Frame 3
Page 0
Page 1
Page 2
Page 3

The full process at a glance. Click Start tour to walk through each step.

Virtual address translation: the page table maps virtual pages to physical frames, with page faults when data is on disk.

Code Example

Code
// Simulating virtual memory with page table translation
function createPageTable(numPages) {
  // -1 means page is on disk (not in RAM)
  return Array.from({ length: numPages }, () => ({
    frame: -1,
    valid: false,
    lastAccessed: 0
  }));
}

function accessPage(pageTable, pageNum, physicalFrames, time) {
  const entry = pageTable[pageNum];

  if (entry.valid) {
    // Page HIT: already in RAM
    entry.lastAccessed = time;
    console.log("Page " + pageNum + " -> Frame " + entry.frame + " (HIT)");
    return { hit: true, frame: entry.frame };
  }

  // Page FAULT: must load from disk
  console.log("Page " + pageNum + " -> PAGE FAULT!");

  // Find free frame or evict (LRU)
  let frame = physicalFrames.indexOf(null);
  if (frame === -1) {
    // No free frames: evict least recently used
    let lruPage = -1;
    let lruTime = Infinity;
    for (let i = 0; i < pageTable.length; i++) {
      if (pageTable[i].valid && pageTable[i].lastAccessed < lruTime) {
        lruTime = pageTable[i].lastAccessed;
        lruPage = i;
      }
    }
    frame = pageTable[lruPage].frame;
    pageTable[lruPage].valid = false;
    console.log("  Evicted page " + lruPage + " from frame " + frame);
  }

  // Load page into frame
  physicalFrames[frame] = pageNum;
  entry.frame = frame;
  entry.valid = true;
  entry.lastAccessed = time;
  console.log("  Loaded page " + pageNum + " into frame " + frame);

  return { hit: false, frame: frame };
}

// 8 virtual pages, only 3 physical frames
const pageTable = createPageTable(8);
const frames = [null, null, null];

// Access sequence
[0, 1, 2, 3, 0, 1, 4, 0].forEach((page, t) => {
  accessPage(pageTable, page, frames, t);
});

Interactive Experiment

Try these exercises:

  • Change the number of physical frames from 3 to 4 and re-run the access sequence. Count how many page faults occur now vs before.
  • Try the access sequence [0, 1, 2, 3, 0, 1, 2, 3] with 3 frames. Notice how you get a page fault on every access (this is called thrashing).
  • Add a counter to track the total number of hits vs faults. What is the hit ratio? How does increasing frames improve it?

Quick Quiz

Coding Challenge

Simulate LRU Page Replacement

Write a function called `lruPageReplacement` that takes an array of page access requests and the number of physical frames. Simulate LRU (Least Recently Used) page replacement and return the total number of page faults. When a page fault occurs and all frames are full, evict the page that was accessed least recently.

Loading editor...

Real-World Usage

Virtual memory is foundational to modern computing:

  • Process isolation prevents a bug in Chrome from corrupting your text editor's memory. Each process has its own virtual address space, enforced by the hardware MMU.
  • Memory-mapped files let you treat a file on disk as if it were in memory. Databases like SQLite and LMDB use mmap() for efficient file access without explicit read/write calls.
  • Copy-on-write (COW) is an optimization where forked processes share physical pages until one writes. This makes fork() nearly free, even for processes using gigabytes of virtual memory.
  • Docker containers use virtual memory and namespaces to isolate processes. Each container sees its own memory space despite sharing the host's physical RAM.

Connections