在本实验中,你将为 xv6 文件系统添加大文件和符号链接。
在编写代码之前,你应该阅读xv6手册中的"第8章:文件系统"并研究相应的代码。
获取实验的 xv6 源代码并切换到 util 分支:
$ git fetch $ git checkout fs $ make clean
在本作业中,你将增加 xv6 文件的最大大小。目前 xv6 文件限制为 268 个块,或 268*BSIZE 字节(在 xv6 中 BSIZE 为 1024)。这个限制来自于 xv6 inode 包含 12 个"直接"块号和一个"单次间接"块号的事实,后者引用一个最多容纳 256 个块号的块,总共 12+256=268 个块。
bigfile 命令创建它能创建的最长文件,并报告该大小:
$ bigfile .. wrote 268 blocks bigfile: file is too small $测试失败是因为 bigfile 期望能够创建一个有 65803 个块的文件,但未修改的 xv6 将文件限制为 268 个块。
你将修改 xv6 文件系统代码以支持每个 inode 中的"双重间接"块,包含 256 个单次间接块的地址,每个地址又可以包含最多 256 个数据块的地址。结果是文件将能够由最多 65803 个块组成,或 256*256+256+11 个块(11 而不是 12,因为我们将牺牲一个直接块号用于双重间接块)。
nmeta 70 (boot, super, log blocks 30 inode blocks 13, bitmap blocks 25) blocks 199930 total 200000这一行描述了 mkfs/mkfs 构建的文件系统:它有 70 个元数据块(用于描述文件系统的块)和 199,930 个数据块,总共 200,000 个块。
在磁盘上查找文件数据的代码在 fs.c 中的 bmap() 中。请查看它并确保你理解它在做什么。bmap() 在读取和写入文件时都会被调用。写入时,bmap() 根据需要分配新块来保存文件内容,以及分配间接块来保存块地址(如果需要的话)。
bmap() 处理两种块号。bn 参数是"逻辑块号"——文件内的块号,相对于文件的起始位置。ip->addrs[] 中的块号和 bread() 的参数是磁盘块号。你可以将 bmap() 视为将文件的逻辑块号映射到磁盘块号。
$ bigfile .................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................. wrote 65803 blocks done; ok $ usertests ... ALL TESTS PASSED $
bigfile 至少需要一分半钟来运行。
提示:
在本练习中,你将为 xv6 添加符号链接。符号链接(或软链接)通过路径名引用一个链接文件;当打开符号链接时,内核跟随链接到被引用的文件。符号链接类似于硬链接,但硬链接被限制为指向同一磁盘上的文件,而符号链接可以跨越磁盘设备。虽然 xv6 不支持多个设备,但实现这个系统调用是理解路径名查找如何工作的一个很好的练习。
你将实现 symlink(char *target, char *path) 系统调用,它在 path 处创建一个新的符号链接,引用 target 命名的文件。更多信息请参见 man page symlink。要测试,将 symlinktest 添加到 Makefile 并运行它。当测试产生以下输出(包括 usertests 成功)时,你的解决方案就完成了。
$ symlinktest Start: test symlinks test symlinks: ok Start: test concurrent symlinks test concurrent symlinks: ok $ usertests ... ALL TESTS PASSED $
提示:
>
实验到此完成。确保你通过了所有 make grade 测试。如果本实验有问题,不要忘记将你的答案写入 answers-lab-name.txt。提交你的更改(包括添加 answers-lab-name.txt)并在实验目录中输入 make handin 来提交你的实验。
创建一个新文件 time.txt,在其中放入一个整数,表示你在本实验上花费的小时数。不要忘记 git add 和 git 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 filename 让 git 跟踪你创建的新文件。
如果 make handin 无法正常工作, 尝试修复 curl 或 Git 命令的问题。 或者你可以运行 make tarball。 这将为你生成一个 tar 文件,然后你可以通过我们的网页界面上传。
支持三重间接块。
感谢华盛顿大学 CSEP551(2019年秋季)的团队提供符号链接练习。