Every process thinks it owns memory
Two programs can both use address 0x1000 without clashing, because those are virtual addresses. Memory is split into fixed-size pages (often 4 KB); each process has a page table saying which physical frame holds each page — or that it's on disk.
- page = address ÷ page size, offset = address mod page size
- physical = frame × page size + offset
- Not present → page fault: the kernel loads it from disk (or kills the process)
- Writing a read-only page → protection fault (that's a segfault)
Translating an address
const PAGE_SIZE = 4096;
const TABLE = [
{ present: true, frame: 5, writable: true }, // page 0
{ present: false }, // page 1: on disk
{ present: true, frame: 3, writable: false }, // page 2: read-only (code)
];
function translate(table, address, pageSize, access = "read") {
const page = Math.floor(address / pageSize);
const offset = address % pageSize;
const entry = table[page];
if (!entry || !entry.present) throw new Error(`Page fault at ${address}`);
if (access === "write" && !entry.writable) throw new Error(`Protection fault at ${address}`);
return entry.frame * pageSize + offset;
}