CS 111 Lecture 14 Scribe Notes: Virtual Memory

by Arvin Nguyen

Contents

File System Robustness (continuation from previous lecture)

We would like our file systems to support atomic updates in the presence of power failure. We used two big ideas:

  1. Commit records
  2. Journaling

A general process for an atomic action implementation:

To the user, all of this will appear as one step.

Variations

Main memory database

We can modify the journals we observed in the previous lecture by keeping the cell data in RAM (caching it) instead of on disk. Changes will be logged to the disk.

Pros:

Cons:

Logging Protocols

We have been discussing "write-ahead" logs. Alternatively, we can use "write-behind" logs. Both work, but they differ in their recovery procedures.

Write-ahead
Write-behind

Cascading Aborts and Compensating Actions

We have two processes, P1 and P2. P1 is scheduled to perform its atomic action before P2.

Cascading aborts are more automatable, but compensating actions are more flexible.

Virtual Memory

We've examined how to protect our data from problems with the hardware such as power outages. Now we'll examine a different form of unreliability that can cause problems: unreliable programs that make bad memory references.

Here are some possible solution:

A Simple Approach

Memory Layout
OS Code Process P1 Process P4 Process P2 OS Code Process P3

When P1 runs, two registers will store the base and bounds of P1's memory. Any memory address M that is accessed by P1 will be checked: P1base <= M < P1bounds.

Downsides to this approach:

New Approach: Segmented Memory

Each process has 8 base-bound pairs for each segment of memory. Examples of the segments are text, data, stack, etc. 32-bit addresses can be split so that the first 3 bits represent the segment number and the rest of the 29 bits represent the offset within the segment.

Pros:

Cons:

Virtual Memory and Paging

Each process is given its own address space of 32 bits, or 4 GB

We split the address space into fixed sizes called pages.

We will split the virtual address number into two sections forming a virtual page number (VPN) and an offset (PO). The first 20 bits will be the virtual page number and the rest of the 12 bits will be the page offset.

Virtual Address (32 bits)
Virtual Page Number (VPN) Page Offset (PO)
20 bits 12 bits

12 offset bits means that each page is 212 bytes long, or 4 KB. The number of pages is then memory_size/page_size = 232/212 = 220

The OS takes first 20 bits of the virtual address space and put it into a function that maps the virtual page number to a physical page number (PPN). The physical page number and the page offset combined gives the physical address of where the data is actually stored. This mapping is done using a page table. The page table lives in RAM and the %cr3 register points to the page table.

Each process has its own page table.

The process table has an entry for each virtual page number (220).

Each entry in the page table is made of 32 bits (4 bytes). Let's assume that we need 20 bits for the physical page number. Then the first 20 bits of the page table entry are for the physical page number. The rest of the 12 bits can be used for flags (such as read/write permissions).

[Page Table Picture]

The page table has an entry for each page 220. The page table size is number_of_entries * entry_size = 220 * 4 bytes = 222 bytes = 4 MiB. That's per process!

Having hundreds of processes means that we quickly use up a lot of space for page tables. To reduce memory usage, we can create another level of indirection by using a multilevel page table.

Two-Level Virtual Address (32 bits)
Page Number 1 Page Number 2 Page Offset (PO)
10 bits 10 bits 12 bits

Click here to see a diagram of two-level page table.

With virtualization and paging, programs can use more than physical memory! However, potential problems that can occur include thrashing. Performance can be really bad if the locality of references are not practical and cause to thrash.

Page Faults

Page faults occur when a process cannot access a page (it doesn't have access privileges, the page is not in RAM, etc.). When a page fault occurs, a trap is generated and the kernel decides how to deal with it. Here is some pseudo-code to give an idea of how page faulting works:

int swapmap(virtual_address, current_process) {
    if invalid address in swap space
        return 0
    else
        return address in swap space
}

void pfault(void * virtual_address, struct proc *current_process, int access_type) {
    if(swapmap(virtual_address, current_process) == 0)
        kill (current_process, SIGSGSV);
    else {
        pick a victim physical page (details in later lecture)
        (vppn, vva) = removal_policy();
        write out vppn to disk
        read in desired page to same physical location
        page_table[vva] = 0;
        page_table[va] = vppn;
        return; // re-execute the instruction that failed
}

External references

Wikipedia - Virtual Memory

Wikipedia - Page Table

Wikipedia - Page Faults