the page table
Think of the building manager's master directory: one row per room number in a tenant's blueprint, each row saying where that room really is — or 'not built yet' — plus who is allowed in. The page table is exactly this directory for a program: a lookup table that, for each virtual page, records which physical frame holds it and what may be done there. It is the single source of truth the hardware consults to translate addresses.
Concretely, the page table is indexed by virtual page number. Take the virtual address, drop the offset bits, and use the remaining page number as an index into the table; the entry you land on (a page-table entry) holds the physical frame number plus control bits — a valid bit (is this page in memory?), protection bits (read/write/execute), and usually a dirty bit and a reference bit. Each running program has its own page table, and the OS switches which table is 'active' (by loading its base address into a special register, called the page-table base register) on every context switch — which is precisely why two programs can use identical virtual addresses safely.
Why it matters: the page table is where relocation, protection, and presence all live, and it is owned and maintained by the OS while consulted by the hardware — the cleanest example of hardware/OS co-design. The honest problem: a flat page table mapping a whole 64-bit address space would itself be enormous (far bigger than RAM), so real systems never store it flat; they use multilevel (hierarchical) page tables or inverted page tables, and cache hot entries in the TLB so most translations skip the table entirely.
A tiny page table: page 0 -> frame 90 (valid, read/write); page 1 -> frame 12 (valid, read-only); page 2 -> (invalid, on disk). Accessing page 2 finds the valid bit clear and triggers a page fault.
One row per virtual page: frame number plus valid and protection bits.
The page table lives in physical memory itself, so a naive translation would need a memory access just to read it — doubling memory traffic. The TLB exists to cache these entries so the common case avoids that extra access.