vm
directory
of NACHOS. Your goal is to implement demand-paged virtual memory.
A big difference between this assignment and the previous assignments is that
you are given absolutely no code to start with, so you have to design and
implement it yourself. The main things that you have
to do are summarized as follows.
For this assignment, you will need to read and write data to the backing
store, which should be a file called SWAP
. The swap file should
be accessed using the NACHOS OpenFile
class.
You can use the filesystem stub routines (the default), so that the
SWAP
file is created as a Unix file.
Implement a page fault handler and a page replacement policy of
your choice.
You should test your code under various conditions of system load,
including one process with an address space larger than physical memory,
and several concurrently running processes with combined address spaces
larger than physical memory.
The sort
program in the
test
directory is an example of
a program designed to stress the virtual memory system.
Demand-paged virtual memory makes it possible to run a process with only
a fraction of its address space resident in physical memory. This allows
the address space of a user process to be potentially much larger than
physical memory, and it also affords a greater opportunity for concurrent
execution by allowing more processes to be running at a time.
Demand-paged virtual memory is supported by address translation hardware
that checks each access to main memory to see whether the referenced page
is currently resident in physical main memory. If the page is resident,
the access proceeds in the normal way. If the page is not resident, then
a page fault is generated, and the CPU leaves user mode and
begins executing a kernel routine whose purpose is to handle such exceptions.
This routine, called the page fault handler, must perform the
following tasks:
Helpful Information
The page fault handler requires some auxiliary data structures to accomplish its task:
You will also need to consider synchronization issues. You may need a lock (or at least a ``busy'' flag) for each physical memory page, and possibly also for each virtual memory page. These would be to ensure, for example, that two processes don't try to initiate I/O on the same page at the same time. Keep in mind that any time a process sleeps in the kernel, another process can run, so that when the sleeping process wakes up again things might look very different then when it went to sleep. The bottom line is that two system calls may be processed concurrently and the synchronization is needed.
The sample test programs for this project are
under ~cs170/Spr03-Section1.test/proj3_p1.
You can provide your own test programs. What to Submit
As usual, commit all relevant files via the turnin procedure.
You should also
include a file HW3_WRITEUP
in the "vm" subdirectory that explains how your
virtual memory code works, and how to run tests.
You should also indicate what does not work and explain your efforts in order
to get partial credits.
Page tables were used in assignment 2 to simplify memory allocation
and to isolate failures from one address space from affecting other
programs. In this assignment we will use page tables to tell the
hardware which pages are resident in physical memory and which are
only resident on the disk. If the valid bit in a particular page table
entry is set, the hardware assumes that the corresponding virtual page
is loaded into physical memory in the physical page frame specified by
the physicalPage field. Whenever the program generates an access to
that virtual page, the hardware accesses the physical page. If the
valid bit is not set, the hardware generates a page fault exception
whenever the program accesses that virtual page. Your exception
handler will then find a free physical page frame, read the page in
from the backing store (typically a paging file) to that physical page
frame, update the page table to reflect the new virtual to physical
mapping, and restart the program. The hardware will then resume the
execution of the program at the instruction that generated the
fault. This time the access should go through, since the page has been
loaded into physical memory.Additional Information
To find a free frame, your exception fault handler may need to eject a cached page from its physical page frame. If the ejected page has been modified in the physical memory, the page fault handling code must write the page out to the backing store before reading the accessed page into its physical page frame. The hardware maintains some information that will help the page fault handler determine which steps need to be taken on a page fault. In addition to the valid bit, every page table entry contains a use and a dirty bit. The hardware sets the use bit every time it accesses the corresponding page; if the access is a write the hardware also sets the dirty bit. Your code may use these bits in its page fault handling code. For example, your code can use the dirty bit to determine if it needs to write an ejected page back to the backing store. When a page is read in from disk, the page fault handler should clear the dirty and use bits in its page table entry. If the page is ever ejected, the page fault handler checks its dirty bit. If the dirty bit is still clear, the copy of the page on disk is identical to the copy in physical memory and there is no need to write the page back to disk before ejecting it.
As with any caching system, performance depends on the policy used to decide which things are kept in memory and which are only stored on disk. On a page fault, the kernel must decide which page to replace; ideally, it will throw out a page that will not be referenced for a long time, keeping pages in memory those that are soon to be referenced. Another consideration is that the operating system may be able to avoid the overhead of writing modified pages to disk inside the page fault handler by writing modified pages to disk in advance. The page fault handler can take advantage of the clean physical page frame to complete subsequent page faults more quickly. FIFO replacement policy is the easiest one to implement, so you may want to start from there to test your page swapping mechanism. But in reality, FIFO replacement policy is rarely used due to its bad performance. You will have to implement some other more efficient replacement policy in your final version, such as FIFO with second chance or LRU.
The first step is to read and understand the partial file system we have written for you under filesys subdirectory. Run the program `nachos -f -cp test/small small' for a simple test case of our code - `-f' formats the emulated physical disk, and `-cp' copies the UNIX file `test/small' onto that disk.
The files to focus on are:
Our file system has a UNIX-like interface, so you may also wish to read the UNIX man pages for creat, open, close, read, write, lseek, and unlink (e.g., type "man creat"). Our file system has calls that are similar (but not identical) to these; the file system translates these calls into physical disk operations. One major difference is that our file system is implemented in C++. Create (like UNIX creat), Open (open), and Remove (unlink) are defined on the FileSystem object, since they involve manipulating file names and directories. FileSystem::Open returns a pointer to an OpenFile object, which is used for direct file operations such as Seek (lseek), Read (read), Write (write). An open file is "closed" by deleting the OpenFile object.
Many of the data structures in our file system are stored both in memory and on disk. To provide some uniformity, all these data structures have a "FetchFrom" procedure that reads the data off disk and into memory, and a "WriteBack" procedure that stores the data back to disk. Note that the in memory and on disk representations do not have to be identical.
Your job is to modify the file system to allow the maximum size of a file to be as
large as the disk (128Kbytes). In the basic
file system, each file is limited to a file size of just under 4Kbytes.
Each file has a header (class FileHeader) that is a table of direct
pointers to the disk blocks for that file. Since the header is stored
in one disk sector with 128 bytes, the maximum size of a file is limited by the number
of pointers that will fit in one disk sector. Increasing the limit to
128KBytes will probably but not necessarily require you to implement
doubly indirect blocks.
What to Extend
The second job is to implement extensible files. In the basic file system, the file size is specified when the file is created. One advantage of this is that the FileHeader data structure, once created, never changes. In UNIX and most other file systems, a file is initially created with size 0 and is then expanded every time a write is made off the end of the file. Modify the file system to allow this; as one test case, allow the directory file to expand beyond its current limit of ten files. In doing this part, be careful that concurrent accesses to the file header remain properly synchronized.
Here are some things you should be sure to get right:
Issues to Consider
Notice that for the input program file, you can still use the regular Unix file system to read its content.
Currently, the basic file system code assumes it is accessed by a single thread at a time.
You can still keep this assumption for this part of the assignment while in a real system,
synchronization is needed to allow multiple threads to use file system concurrently.
The sample test programs for this project are
under ~cs170/Spr03-Section1.test/proj3_p2.
You can provide your own test programs. What to Submit
As usual, commit all relevant files via the turnin procedure together when submitting Part I of your code.
You should also
include a file HW3_P2_WRITEUP
in the "filesys" subdirectory that explains how you make this
extension and how to run tests.
You should also indicate what does not work and explain your efforts in order
to get partial credits.
For part of the Nachos program you have modified, you should insert the following lines in your code so TAs can read:
//HW3 Begin of Modification
//HW3 End of Modification