Lecture 12: managing the page table

Single level page table

At the end of last lecture, we introduced the notion of paging: divide a large virtual address space into many small pages, which can be independently swapped into and out of frames in physical memory.

To do so, we need to keep a data structure (the page table) for each process mapping page numbers to frame numbers.

The simplest method is to put these into an array: the ith entry in the array gives the frame number in which the ith page is stored.

Size of the page table

note: these numbers are typical, but not worth memorizing: the process by which they are derived is more important.

The page table needs one entry per page. Assuming a 4GB (2^32 byte) virtual and physical address space and a page size of 4kB (2^12 bytes), we see that the the 2^32 byte address space must be split into 2^20 pages.

This means the page table must have 2^20 entries.

How large are the entries?

This gives a total of 25 bits per entry. The math is much easier if we round to bytes: each entry is 4 bytes.

Thus the total size of the page table is 2^20 entries * 2^2 bytes/entry = 2^22 bytes = 4MB.

Hierarchical paging / paged page table

4MB of contiguous space per process is a lot. Moreover, if the process is only using a small part of its address space, we will only need to access a small part of the page table.

Just as with the address space, we can solve these problems by paging the page table itself. For convenience, we can make the pages of the page table (POPTs) the same size as the pages of the process's address space. This allows us to use the same set of frames to store either process data or POPTs.

In our example, each POPT holds 2^12 bytes / 4 bytes per entry = 2^10 entries. Since there are 2^20 total entries in the page table, there must be 2^10 POPTs.

Just like we needed a page table when we split up the address space into pages, we will need a second level page table to tell us where the POPTs are stored. In our example, this table must contain 2^10 entries (one for each POPT), each of which is 4 bytes (it contains a 20 bit frame pointer and additional VDRWX bits). Thus the total size of the top-level page table is 2^10 entries * 2^2 bytes per entry = 2^12 bytes = 4kb. This fits in one page, so there is no reason to split it further.

With different numbers, we could have a very large top-level page table. If so, we could repeat this process by paging the top-level page table (thus introducing another layer of page table).