The Software · Chapter 9.c
How does each program get its own memory?
Transcript
How does each program get its own memory? Two programs both write to address three. Both expect their own value back.
I figured each program is built to use different addresses. But run the same app twice, and both copies use address three.
So every address is split in two: a page, and an offset inside it. Address three is page zero, offset three. Each program gets its own page table. A's table says page zero lives in frame five. Keep the offset: frame five, offset three, is cell eighty-three. The offset never changes; only the page is swapped for a frame. B's table sends page zero to frame eight instead. Same address three, two tables, two different cells.
So each gets its own memory through its own table! Two programs can use the same address without ever meeting.
Slide an address below across a page boundary, and watch where each program's copy lands.
- The browser
- The network
- Software and languages
- The CPU
- Memory
- Arithmetic
- Logic gates
- The switch
The operating system runs many programs, each as a process in the sense of Chapter 9, on the one memory of Chapter 4, and each must believe that memory is its own. If they all used real addresses, two programs that both wanted address 3 would collide, and a careless or hostile one could read or overwrite another’s data. The fix is a layer of translation called virtual memory. Each program uses virtual addresses, numbered from zero as if it had the machine to itself. Every access passes through a page table that maps the program’s virtual pages to the physical frames it may access. In this example the two programs get disjoint frames. Real systems can also map a frame into several processes intentionally, for example to share data or read-only code.
Protection requires more than the translation formula. The operating system must control the tables, and user code must be unable to edit them or bypass the translation. Our Python functions trust the table and memory passed by the caller; they demonstrate mappings under those assumptions, not an enforced security boundary. Real page-table entries also carry access permissions.
9.c.1 Translation
A virtual address splits into two parts: a page number and an offset within that page. The page table turns the page number into a frame number; the offset rides through untouched. Figure 9.c.2 translates one address.
Example 9.c-1. Translating through a page table
def translate(page_table: dict, virtual: int) -> int: """Translate a virtual address to a physical one through a page table. The page number selects a frame; the offset within the page is unchanged.""" page, offset = divmod(virtual, PAGE_SIZE)1 if page not in page_table: raise PageFault(f"virtual page {page} is not mapped")2 frame = page_table[page] return frame * PAGE_SIZE + offset3
- split the virtual address into its page number and the offset inside the page
- a page the table does not map raises a page fault in this model; no physical address can be returned for it
- otherwise the physical address is the frame times the page size, plus the offset carried straight through
A real page fault can report a forbidden access, but it can also ask the kernel to complete valid work: allocate a page lazily, make a private copy before a write, or restore data moved to storage. The handler decides whether to supply a mapping and resume execution or reject the access. This model simply raises an exception for an absent entry.
9.c.2 Isolation
With trusted tables that map to disjoint frames, two programs can use the very same virtual address without meeting. This is the address-space mapping discussed in Chapter 9: a real context switch can select another table without copying memory. Our translator is separate from that chapter’s scheduler, which switches whole memory-list references. Figure 9.c.3 gives both programs virtual address 3; one table sends it to frame 5, the other to frame 8, so the two writes land in different physical cells.
9.c.3 Virtual memory, run
Running ftb.vm gives two programs page tables that map their pages to different frames, has both write to virtual address 3, and shows where each lands.
page size 16 cells
program A's table: {0: 5, 1: 2}
program B's table: {0: 8, 1: 9}
both programs write to virtual address 3:
A's 3 -> physical 83
B's 3 -> physical 131
A reads back 42, B reads back 99
Same virtual address, different memory: neither touched the other.
Both programs wrote to what each called address 3, yet A’s value went to physical 83 and B’s to physical 131, and each read back exactly its own. The page table makes that separation possible under the stated assumptions. If the Python caller changes A’s page 0 mapping from frame 5 to frame 8, A can read B’s 99; translation alone does not stop that change. In a real process, heap allocations live inside its virtual pages: the allocator hands out address ranges, and the table decides where they land. Our allocator and translator illustrate those two jobs separately.
The next chapter turns from memory that vanishes with the power to storage that does not: files.
Exercises
- Map a third page in one program’s table, and translate an address that falls inside it.
- Translate an address whose page is not mapped, and catch the page fault.
