

Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
A part of the lecture notes for cmpsci 377 operating systems course, spring 2009. It discusses the concept of virtual memory, where each virtual address is translated to a physical address, and the benefits of using virtual memory such as process isolation, efficient memory management, and the illusion of having the whole address space for each process. The document also explains how virtual memory uses one level of indirection, memory pages, and the memory management unit (mmu) for translation.
Typology: Study notes
1 / 2
This page cannot be seen from the preview
Don't miss anything!


CMPSCI 377 Operating Systems Spring 2009
Lecturer: Mark Corner Scribes: Bruno Silva,Jim Partan
In modern operating systems, applications do not directly access the physical memory. Instead, they use so-called virtual memory, where each virtual address is translated to a physical address.
Why would one do this? Here are some of the reasons that virtual memory is useful:
Since each program thinks it has the whole memory to itself, programs can use a lot of virtual memory. In fact, a computer might use huge amounts of virtual memory, much more than the amount of actual physical memory available. Most of the time this works fairly well, since processes typically only need to use a small amount of their virtual memory at once, and often a lot can be shared among processes (such as with shared libraries). But if the system gets into a situation where the active virtual memory demands exceed the available physical memory, we will need to use another mechanism, such as “swapping” memory pages to disk.
Virtual memory uses one level of indirection in the translation from virtual addresses to physical addresses.
Applications allocate memory in terms of the number of bytes that they need, but this level of granularity is too fine-grained for the operating system to manage the system memory in this way. Instead, the OS manages the memory in groups of bytes called pages. Pages are typically of 4kb or 8kb. Suppose we decide to use 4kb pages; in a 32-bit machine, it is possible to address at most 2^32 different addresses; if we divide that maximum amount of memory by the size of the page, we see that there can be at most 2
32 212 = 2
(^20) 4kb
pages.
Using pages makes it easier to manage the whole memory, avoiding excessive fragmentation and waste. As an analogy, think of Tetris, but with only square blocks: it is relatively easy to avoid fragmentation in this case. Both the virtual and the physical memory are divided into pages. As an aside, we often refer to physical memory pages as frames.
Every virtual page consists of a range of virtual addresses. Virtual pages are then mapped to physical pages in the physical memory. When an application needs to access a virtual page, the corresponding virtual address is translated into a “real” physical address, and then the actual data might be read and/or written. As a consequence, note that although arrays are contiguous in virtual memory, they may be non-contiguous
13-2 Lecture 13: March 24
in physical memory. Note also that some virtual pages do not map to any actual physical memory address, because not all virtual pages are necessarily being used at any given time. The unused virtual pages are called invalid. If a program ever tries to access an invalid page, it pagefaults.
A typical virtual memory layout includes a stack, a mmap region, a heap, and the code of the program (the “text” section). Since mmap and heap grow towards each other, in the worst case they could smash into each other. The same could happen with the stack: if a program recurses for a large number of times, the stack could grow over the mmap region (“stack overflow”) and in this case something bad and usually unpredictable will happen.
When a program issues a memory load or store operation, the virtual addresses (VAs) used in those operations have to be translated into “real” physical memory addresses (PAs). This translation is the main task of the MMU (Memory Management Unit). The MMU maintains a page table (a big hash table) that maps virtual pages to physical pages. Since memory accesses are happening all the time, the MMU needs to be extremely fast and implemented correctly. For these reasons, MMUs are almost always implemented in hardware. Note that we can’t map every single byte of virtual memory to a physical address; that would require a huge page table. Instead, the MMU maps virtual pages to physical pages. Also, since we want to isolate each program’s address space from the address spaces of other applications, the MMU must keep a separate page table for each process; this implies that different processes could use the same virtual address to refer to different data, and that would not be a problem since these virtual addresses would be mapped into different physical addresses. The page table also marks all virtual pages that are allocated (and therefore are being used), so that it is possible to know which virtual pages have valid mappings into physical pages. All virtual pages that are not being mapped to a physical page are marked as invalid ; segfaults occur when a program tries to reference or access a virtual address that is not valid. In addition to valid bits, page table entries (PTEs) also store a lot of other information, such as “read” and “write” bits to indicate which pages can be read/written.
Virtual addresses are made up of two parts: the first part is the page number, and the second part is an offset inside that page. Suppose our pages are 4kb (4096 = 2^12 bytes) long, and that our machine uses 32-bit addresses. Then we can have at most 2^32 addressable bytes of memory; therefore, we could fit at most 232 212 = 2
(^20) pages. This means that we need 20 bits to address any page. So, the page number in the virtual
address is stored in 20 bits, and the offset is stored in the remaining 12 bits.