diff options
Diffstat (limited to 'labs/mmap.html')
| -rw-r--r-- | labs/mmap.html | 171 | 
1 files changed, 0 insertions, 171 deletions
| diff --git a/labs/mmap.html b/labs/mmap.html deleted file mode 100644 index 6f779c4..0000000 --- a/labs/mmap.html +++ /dev/null @@ -1,171 +0,0 @@ -<html> -<head> -<title>Lab: mmap</title> -<link rel="stylesheet" href="homework.css" type="text/css" /> -</head> -<body> - -<h1>Lab: mmap</h1> - -<p>In this lab you will use </tt>mmap</tt> on Linux to demand-page a -very large table and add memory-mapped files to xv6. - -<h2>Using mmap on Linux</h2> - -<p>This assignment will make you more familiar with how to manage virtual memory -in user programs using the Unix system call interface. You can do this -assignment on any operating system that supports the Unix API (a Linux Athena -machine, your laptop with Linux or MacOS, etc.). - -<p>Download the <a href="mmap.c">mmap homework assignment</a> and look -it over.  The program maintains a very large table of square root -values in virtual memory. However, the table is too large to fit in -physical RAM. Instead, the square root values should be computed on -demand in response to page faults that occur in the table's address -range.  Your job is to implement the demand faulting mechanism using a -signal handler and UNIX memory mapping system calls. To stay within -the physical RAM limit, we suggest using the simple strategy of -unmapping the last page whenever a new page is faulted in. - -<p>To compile <tt>mmap.c</tt>, you need a C compiler, such as gcc. On Athena, -you can type: -<pre> -$ add gnu -</pre> -Once you have gcc, you can compile mmap.c as follows: -<pre> -$ gcc mmap.c -lm -o mmap -</pre> -Which produces a <tt>mmap</tt> file, which you can run: -<pre> -$ ./mmap -page_size is 4096 -Validating square root table contents... -oops got SIGSEGV at 0x7f6bf7fd7f18 -</pre> - -<p>When the process accesses the square root table, the mapping does not exist -and the kernel passes control to the signal handler code in -<tt>handle_sigsegv()</tt>. Modify the code in <tt>handle_sigsegv()</tt> to map -in a page at the faulting address, unmap a previous page to stay within the -physical memory limit, and initialize the new page with the correct square root -values. Use the function <tt>calculate_sqrts()</tt> to compute the values. -The program includes test logic that verifies if the contents of the -square root table are correct. When you have completed your task -successfully, the process will print “All tests passed!”. - -<p>You may find that the man pages for mmap() and munmap() are helpful references. -<pre> -$ man mmap -$ man munmap -</pre> - - -<h2>Implement memory-mapped files in xv6</h2> - -<p>In this assignment you will implement memory-mapped files in xv6. -  The test program <tt>mmaptest</tt> tells you what should work. - -<p>Here are some hints about how you might go about this assignment: - -  <ul> -    <li>Start with adding the two systems calls to the kernel, as you -      done for other systems calls (e.g., <tt>sigalarm</tt>), but -      don't implement them yet; just return an -      error. run <tt>mmaptest</tt> to observe the error. -       -    <li>Keep track for each process what <tt>mmap</tt> has mapped. -      You will need to allocate a <tt>struct vma</tt> to record the -      address, length, permissions, etc. for each virtual memory area -      (VMA) that maps a file.  Since the xv6 kernel doesn't have a -      memory allocator in the kernel, you can use the same approach has -      for <tt>struct file</tt>: have a global array of <tt>struct -	vma</tt>s and have for each process a fixed-sized array of VMAs -      (like the file descriptor array). - -    <li>Implement <tt>mmap</tt>: allocate a VMA, add it to the process's -      table of VMAs, fill in the VMA, and find a hole in the process's -      address space where you will map the file.  You can assume that no -      file will be bigger than 1GB.  The VMA will contain a pointer to -      a <tt>struct file</tt> for the file being mapped; you will need to -      increase the file's reference count so that the structure doesn't -      disappear when the file is closed (hint: -      see <tt>filedup</tt>). You don't have worry about overlapping -      VMAs.  Run <tt>mmaptest</tt>: the first <tt>mmap</tt> should -      succeed, but the first access to the mmaped- memory will fail, -      because you haven't updated the page fault handler. - -    <li>Modify the page-fault handler from the lazy-allocation and COW -      labs to call a VMA function that handles page faults in VMAs. -      This function allocates a page, reads a 4KB from the mmap-ed -      file into the page, and maps the page into the address space of -      the process.  To read the page, you can use <tt>readi</tt>, -      which allows you to specify an offset from where to read in the -      file (but you will have to lock/unlock the inode passed -      to <tt>readi</tt>).  Don't forget to set the permissions correctly -      on the page.  Run <tt>mmaptest</tt>; you should get to the -      first <tt>munmap</tt>. -       -    <li>Implement <tt>munmap</tt>: find the <tt>struct vma</tt> for -      the address and unmap the specified pages (hint: -      use <tt>uvmunmap</tt>). If <tt>munmap</tt> removes all pages -      from a VMA, you will have to free the VMA (don't forget to -      decrement the reference count of the VMA's <tt>struct -      file</tt>); otherwise, you may have to shrink the VMA.  You can -      assume that <tt>munmap</tt> will not split a VMA into two VMAs; -      that is, we don't unmap a few pages in the middle of a VMA.  If -      an unmapped page has been modified and the file is -      mapped <tt>MAP_SHARED</tt>, you will have to write the page back -      to the file. RISC-V has a dirty bit (<tt>D</tt>) in a PTE to -      record whether a page has ever been written too; add the -      declaration to kernel/riscv.h and use it.  Modify <tt>exit</tt> -      to call <tt>munmap</tt> for the process's open VMAs. -      Run <tt>mmaptest</tt>; you should <tt>mmaptest</tt>, but -      probably not <tt>forktest</tt>. - -    <li>Modify <tt>fork</tt> to copy VMAs from parent to child.  Don't -    forget to increment reference count for a VMA's <tt>struct -    file</tt>.  In the page fault handler of the child, it is OK to -    allocate a new page instead of sharing the page with the -    parent. The latter would be cooler, but it would require more -    implementation work.  Run <tt>mmaptest</tt>; make sure you pass -    both <tt>mmaptest</tt> and <tt>forktest</tt>. -           -  </ul> -   -<p>Run usertests to make sure you didn't break anything. - -<p>Optional challenges: -  <ul> -     -    <li>If two processes have the same file mmap-ed (as -      in <tt>forktest</tt>), share their physical pages. You will need -      reference counts on physical pages. - -    <li>The solution above allocates a new physical page for each page -    read from the mmap-ed file, even though the data is also in kernel -    memory in the buffer cache.  Modify your implementation to mmap -    that memory, instead of allocating a new page.  This requires that -    file blocks be the same size as pages (set <tt>BSIZE</tt> to -    4096).  You will need to pin mmap-ed blocks into the buffer cache. -    You will need worry about reference counts. - -    <li>Remove redundancy between your implementation for lazy -    allocation and your implementation of mmapp-ed files.  (Hint: -    create an VMA for the lazy allocation area.) - -    <li>Modify <tt>exec</tt> to use a VMA for different sections of -    the binary so that you get on-demand-paged executables. This will -    make starting programs faster, because <tt>exec</tt> will not have -      to read any data from the file system. - -    <li>Implement on-demand paging: don't keep a process in memory, -    but let the kernel move some parts of processes to disk when -    physical memory is low.  Then, page in the paged-out memory when -    the process references it.  Port your linux program from the first -    assignment to xv6 and run it. -       -  </ul> -   -</body> -</html> | 
