Lab mmap: Memory-mapped files

This is one of the project options.

The mmap and munmap system calls allow UNIX programs to exert detailed control over their address spaces. They can be used to share memory among processes, to map files into process address spaces, and as part of user-level page fault schemes. In this lab you’ll add mmap and munmap to xv6, focusing on memory-mapped files.

To start the lab, update your repository and create a new branch for your solution:

$ git fetch origin
$ git checkout -b mmap origin/xv6-21au
$ make clean

The manual pages for mmap/munmap (run man 2 mmap) shows this declaration for mmap:

void *mmap(void *addr, size_t length, int prot, int flags,
           int fd, off_t offset);

mmap can be called in many ways, but this lab requires only a subset of its features relevant to memory-mapping a file. You can assume that addr will always be zero, meaning that the kernel should decide the virtual address at which to map the file. mmap returns that address, or 0xffffffffffffffff if it fails. length is the number of bytes to map; it might not be the same as the file’s length. prot indicates whether the memory should be mapped readable, writeable, and/or executable; you can assume that prot is PROT_READ or PROT_WRITE or both. flags will be either MAP_SHARED, meaning that modifications to the mapped memory should be written back to the file, or MAP_PRIVATE, meaning that they should not. You don’t have to implement any other bits in flags. fd is the open file descriptor of the file to map. You can assume offset is zero (it’s the starting point in the file at which to map).

It’s OK if processes that map the same MAP_SHARED file do not share physical pages.

munmap(addr, length) should remove mmap mappings in the indicated address range. If the process has modified the memory and has it mapped MAP_SHARED, the modifications should first be written to the file. An munmap call might cover only a portion of an mmap-ed region, but you can assume that it will either unmap at the start, or at the end, or the whole region (but not punch a hole in the middle of a region).

More generally, you should implement enough mmap and munmap functionality to make the mmaptest test program work. If mmaptest doesn’t use a mmap feature, you don’t need to implement that feature.

When you’re done, you should see this output:

$ mmaptest
mmap_test starting
mmap_test OK
fork_test starting
fork_test OK
mmaptest: all tests succeeded
$ usertests
usertests starting
test reparent2: OK
...
test bigdir: OK
ALL TESTS PASSED
$

Here are some hints about how you might go about this lab:

Run usertests to make sure everything still works.

Optional challenges: