实验:mmap

mmapmunmap 系统调用允许 UNIX 程序 对其地址空间进行精细控制。它们可用于 在进程之间共享内存、将文件映射到进程地址空间, 以及作为用户级缺页方案的一部分,例如 课堂讨论的垃圾回收算法。 在本实验中,你将向 xv6 添加 mmapmunmap, 重点是内存映射文件。

获取实验的 xv6 源代码并切换到 mmap 分支:

  $ git fetch
  $ git checkout mmap
  $ make clean

手册页 (运行 man 2 mmap)显示了 mmap 的这个声明:

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

mmap 可以用多种方式调用, 但本实验只需要其与内存映射文件相关的 功能子集。你可以假设 addr 始终为零,表示 内核应决定映射文件的虚拟地址。 mmap 返回该地址,失败时返回 0xffffffffffffffff。 length 是要映射的字节数;它可能与 文件的长度不同。 prot 指示内存是否应被映射为 可读、可写和/或可执行;你可以假设 protPROT_READPROT_WRITE 或两者兼有。 flags 将是 MAP_SHARED, 表示对映射内存的修改应 写回文件,或者是 MAP_PRIVATE, 表示不应写回。你不需要实现 flags 中的其他位。 fd 是要映射的文件的打开文件描述符。 你可以假设 offset 为零(它是文件中 开始映射的起始位置)。

映射同一个 MAP_SHARED 文件的进程共享物理页面是可以的。

munmap(addr, length) 应移除指定地址范围内的 mmap 映射。如果进程修改了该内存并且 将其映射为 MAP_SHARED,则修改应首先 写回文件。munmap 调用可能只覆盖 mmap 区域的一部分,但你可以假设它要么 在起始处取消映射,要么在结尾处取消映射,要么取消整个区域(但不会在 区域中间打孔)。

你应该实现足够的 mmapmunmap 功能,以使 mmaptest 测试程序能够运行。如果 mmaptest 没有使用某个 mmap 特性,你就不需要实现 该特性。

完成后,你应该看到以下输出:

$ mmaptest
mmap_test starting
test mmap f
test mmap f: OK
test mmap private
test mmap private: OK
test mmap read-only
test mmap read-only: OK
test mmap read/write
test mmap read/write: OK
test mmap dirty
test mmap dirty: OK
test not-mapped unmap
test not-mapped unmap: OK
test mmap two files
test mmap two files: OK
mmap_test: ALL OK
fork_test starting
fork_test OK
mmaptest: all tests succeeded
$ usertests
usertests starting
...
ALL TESTS PASSED
$ 

以下是一些提示:

运行 usertests 以确保一切仍然正常工作。

提交实验

实验到此完成。确保你通过了所有 make grade 测试。如果本实验有问题,别忘了在 answers-lab-name.txt 中写下你的 答案。提交你的更改 (包括添加 answers-lab-name.txt)并在实验 目录中输入 make handin 来提交你的实验。

花费时间

创建一个新文件 time.txt,在其中放入一个整数,即 你在本实验上花费的小时数。别忘了 git addgit commit 该文件。

提交

你将使用
提交 网站提交你的作业。在提交任何作业或实验之前, 你需要从提交网站请求一次 API 密钥。

在提交你对实验的最终更改后,输入 make handin 来提交你的实验。

$ git commit -am "ready to submit my lab"
[util c2e3c8b] ready to submit my lab
 2 files changed, 18 insertions(+), 2 deletions(-)

$ make handin
tar: Removing leading `/' from member names
Get an API key for yourself by visiting https://6828.scripts.mit.edu/2020/handin.py/
Please enter your API key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 79258  100   239  100 79019    853   275k --:--:-- --:--:-- --:--:--  276k
$
make handin 会将你的 API 密钥存储在 myapi.key 中。如果你需要 更改 API 密钥,只需删除此文件并让 make handin 重新生成(myapi.key 不能包含换行符)。

如果你运行 make handin 时有未提交的更改或 未跟踪的文件,你将看到类似于以下的输出:

 M hello.c
?? bar.c
?? foo.pyc
Untracked files will not be handed in.  Continue? [y/N]
检查上述行并确保你的实验解决方案所需的 所有文件都被跟踪,即不在以 ?? 开头的行中列出。 你可以使用 git add filenamegit 跟踪你创建的新文件。

如果 make handin 无法正常工作, 请尝试修复 curl 或 Git 命令的问题。 或者你可以运行 make tarball。 这会为你制作一个 tar 文件,然后你可以通过我们的 网页界面上传。

可选挑战