This lab will implement the mmap
and munmap
system calls for xv6, which relates to concepts including file read/write, page table, page fault handler and system call implementation. It’s definitely a hard and error-prune work😫. (My answer cannot guarantee 100% safety. I listed some safety issues in my implementation below for you to improve.) I finish this task by following the official hints, but there is still something to point out:
mmap()
The core idea in this lab is to implement the mmap VM mapping and the actual page table mapping asynchronously!
Users can have their illusion that the file has been mapped to the returned address and all bytes are available to read or write. But the kernel delays the actual VM mapping and file reading by using page fault handlers.
When the user calls mmap()
, the kernel checks the file permissions and records the mmap area in the process table proc.mmapareas[16]
:
struct vma {
int valid; // is this area struct avaiable for use?
uint64 start; // original address of the mmap area (for calculating the file offset)
uint64 addr; // current address of the mmap area (file offset may have been changed by munmap())
int length; // area size
int permissions; // prot
int shared; // shared or private
struct file *fp; // underlying file
};
struct proc {
...
struct vma *mmapareas[16]; // Virtual Memory-Mapped areas
};
vma
allocation, free, and address searchBut the mmap()
system calls doesn’t map the area in its address space now. So any visit to that area will incur a page fault, even if mmap()
succeeds.
mmap()
Page fault handler will actually do the mapping work:
Each time the instruction incurs a page fault, the kernel only maps the current page not the whole file into address space.
munmap()
Users call munmap()
to remove parts of the mmap area allocated by mmap()
first. The kernel will do the following things: