2/21/2007 CS162 Lecture Notes Albert Chae Purpose of Problem Sets: Listening to lectures and writing Nachos code don't necessarily help prepare for exams, but problem sets are good practice because they force you to write out answers. ******************************** Brief recap: - Processes are generally 1 to 1 with segment tables. Protection because you can only address what's addressable by your process. ******************************** Process vs Threads: - A process includes process state and execution through the state. - Threads are multiple execution streams in same state. - Lightweight process is a synonym for thread. - Switching between threads has a lower overhead than switching between processes because there is no need to change address space. Only registers have to be changed. - Switching between processes involves swapping many tables that we haven't even begun to talk about; i.e. open file tables, etc. - Threads are sharing an address space, so they can be considered to be "parallel" computation on same data. - Some problems can be solved by launching multiple threads, instead of doing recursion. Some algorithms are easy to describe in a parallel form. - Threads share open files, processes don't. ******************************** For more information about monitors, read the article by Hoare in the reader. ******************************** More on Segments: - Keep a copy of the segment table somewhere. - If it's small, it can be in PCB, otherwise has to be a separate data structure. - Allocate segments in memory when process starts. Put base and bounds registers in table as well. - Need a memory (core) map. It is a table that maps memory back to segments. - When switching contexts, switch pointer of segment table so you are in a new address space. Put memory back in free storage area when process terminates or releases it. - You can compact memory by moving segments. Just move base and bounds registers. - You can swap a segment out if you need more free memory. - Remember to turn valid bit off. - Expand segment by expanding to free adjacent memory, or move it out. - If process addresses segment not in memory, causes trap. - OS finds space for that segment. - Kicks out other segments if necessary. - Loads segment. - Updates segment table. - Turns on valid bit. - Makes process ready to run. Question: What's a segmentation fault? Answer: Either referencing a segment that doesn't exist, or more likely trying to reference beyond end of segment. There is also a segment fault where segment is on disk, so OS brings it in. The segmentation fault that causes your C programs to crash are where segment shouldn't exist, such as going off the stack or going into a region where it shouldn't be. Problems/Disadvantages of segments: Segments are variable size, causes external fragmentation. Segments can only be as big as physical memory. ******************************** Paging: Paging is the next step after segmentation. Instead of chopping up memory into variable size segments, let's do fixed size pages. Every chunk of VM pages 512 or 16K. The slide is old, nowadays up to 64K size pages. Physical memory is divided into fixed size chunks as well. These chunks are called page frames. - Page frame is physical memory and page is virtual memory. SAME SIZE. Sometimes Professor will say page on accident when he means page frame. - Pages have sizes of power 2. - Paging and segmentation are similar, but fixed size and also some other things get simpler. - Virtual addresses n bits. Then k bits make up page number and n-k bits are byte width. Page Table Entries: .-------------------------------------------------------------------------. | Real Address (page base) | Protection (rwx) | Valid | Dirty | Reference | .-------------------------------------------------------------------------. PTE Fields: Real Address: Where the page frame associated with this page is. Protection bits: Read, Write, Execute permission. Valid bit: Valid if this page has been loaded to memory. Dirty bit: Indicates whether bytes have been modified (have to write back to disk). Reference bit: Turned on whenever this page was last referenced. Useful for page replacement algorithms. Page Table: .-----------------------------------------------. Virtual Addr | V .---------------------------. .---------------------------. | Page Number | Byte Offset | | Real Address | Byte Offset| .---------------------------. .---------------------------. | Page Table | | .----------. | | |__________| | | |__________| | .--------------------->|__________|------------. |__________| |__________| |__________| |__________| Translation Process: - Page number indexes into Page Table. - Since everything is a power of 2, just splice and concatenate. - Memory (core) map still required for page tables. It is simpler because everything is fixed size. - Can index by page frame. Step by step: - Process generates virtual address. - Hardware then takes page number to get the real address. - Checks protection bit depending on opcode (store or load). - Valid bit to see if page exists. - Store turns dirty bit on. When traps to OS, is this page valid or not? - If page is valid, it's out on disk, or it should exist but it's never been created. - Either way, needs to put it in a page frame. - Kicks a page out if there's no empty one. (Core map used for this). Valid checking schemes: - Some programming languages will set up an array, but there will be garbage. - Other languages will fill in a test pattern that it will use as its invalid pattern. Advantages to Page Table: - No external fragmentation. - If you combine it with segmentation, you can have segments that are paged. - Virtual address space much larger than physical address space. - Load pages when you need them. Disadvantages to Page Table: - Internal fragmentation, what you're not using is wasted. - But memory is huge now, so it's not that big a deal. - Hardware for address translation is required. - Hardware/software codesign required. - Real address machine can run faster than comparable virtual memory machine. - But virtual memory is really nice so everyone uses it. - Real address is only used in embedded systems. - Too many page faults is a lot of overhead. - Page replacement algorithm required. - Page tables are too big if you only use one. ******************************** Elaboration of last disadvantage above: If you have 32-bit addr with 4K pages, there is a million (2^20) entries for each page table. If each entry is 4 bytes, then 4Mb for each page table. Because page tables can be big, 1 page table a process is not a good idea. 4 Solutions to Table Space Problem: 1) Page table base register & limit register. Only these pages are valid so only allocate that much of the page table. - Not a popular solution. Hardware needs to be built in and typically in address space you have code, data, and stack. Too much of a hassle. 2) Usual solution: 2 level Page Table 1st level Page Table .____________. |____________|----------. 2nd level Page Tables |____________|--------. | .________. |____________| | .--->|________| |____________| | |________| |____________| | |________| |____________| | |____________| | .________. |____________| .----->|________| .->|____________|--. |________| | |____________| | |________| | | . | | . | | . | | More 2nd level Page Tables | | . | | . | | . | | .________. | .----------->|________| | .---->|________|---. | | |________| | | | | | | | | ._________________| | | | | .____________________. .______V________________. | 10 | 10 | 12 | | Real Address | Offset | | PT1 | PT2 | Offset | |______________|________| |_____|_____|________| ^ |_________________________________________| Higher order bits to index first level of page table. Each entry pages to a different second level page table. It's a tree. This helps save memory because we don't have to allocate all the second level page tables. Only have to allocate ones that exist. Analogy: Taking old word and giving it a new meaning. 3) Page Tables in OS' VM: - Original was a linear page table. - Let's take user's page tables and put them into os' virtual memory. - This still requires 2 levels of mapping, one to get into the virtual memory, the second to get to the page. 4) Hash Table (Inverted Page Table): - Hash the virtual address to get an index into the Page Table. - Need algorithms to dela with collision. - This is faster because it reduces number of lookups. ***************************** Where are Page Tables Located? - Page Tables cannot be accessed by users, otherwise users can tamper and wreak havoc. - They either exist in real memory or in OS' virtual memory. Some other facts about Pages: - OS is paged, otherwise a lot of memory would be required to run it. - Page Tables can be paged out. - If Page Tables are in OS' VM, like in solution 3 above, then OS address must be translated every time virtual address is. Recursive page faults could occur here, so OS Page Tables must be put in real memory or user Page Tables must be in real memory. - Memory that can't be paged out is called "wired" - Code that handles the paging in. - Page fault handlers in OS. - Interrupt and Trap handlers in OS. - OS Page Table (to prevent recursive page fault). - Routines that are sensitive to real time, must be fast. - Pages in the middle of handling I/O must not be paged out or weird effects. - Paging is a great protection scheme for the same reason that segmenting is. **************************** Segmentation and Paging Combined: - Using segments that are paged. - Segment table is used for different segments of program. - "segments of program" meaning segments in the sense of linker/loader. - To be specific: code, data, stack. - Each segment table entry points to a page table. - Similar to 2 level page table, higher order bits for segment table, lower order bits for page tables. - Takes a lot of the good things about segmentation and good things about paging and puts them together in a generally good way. **************************** Segmentation vs Paging: - Segmentation is aid for user, paging is aid for OS. - Segments are variable size, pages are fixed. - Segments visible to programmer, pages aren't. **************************** Sharing Memory between Two Processes: - One way to share is to share a common page. Process 1 Process 2 ._______________. ._______________. |Segment Table 1| |Segment Table 2| |_______________| |_______________| | | | .____________. .____________. | .->|page table 1|-. ._|Page Table 2|<-. |____________| | | |____________| | .___________. | .->|shared page|<-. |___________| - Another way is to share a common segment. - Really they are sharing a page table, which points to a shared segment. ._______________. ._______________. |Segment Table 1| |Segment Table 2| |_______________| |_______________| | | | .____________. | |------------------>| shared |<-------------------| | page table |-. |____________| | | | | .______________. | |shared segment|<-. |______________| - Sharing a segment is better because programmers shouldn't know about pages.