准备措施
根据指导书里的内容,将文件 Makefile 下的 CPUS 改为 1 并在 QEMUOPTS 前添加语句 QEMUEXTRA $=-$snapshot 以加快xv6创建大文件的速率
1 | |
mkfs.c 文件在初始化文件系统时通过参数 FSSIZE 指定分配数据块的数量
1 | |
所以我们需要将预定义在头文件 param.h 里的 FSSIZE 从 1000 修改为 20000
1 | |
下载 big.c 并将big命令添加至 Makefile 下的 UPROGS 列表;在 xv6 的 shell 里运行 big 观察结果;目前 xv6 的文件系统可分配 140 个数据块
1 | |
1 | |
fs.c/fs.h 相关项解读
inode 定义于头文件 fs.h 内,初始的文件系统含有 13 个直接指针 NDIRECT 和 1 个一级间接指针 NINDIRECT,addrs 数组的最后一项就是间接块的地址;参数 MAXFILE 表征该文件系统所能指向的数据块数目的最大值,当前为12 + 512 / 4 = 140
1 | |
函数 bmap(ip, bn) 负责建立inode与磁盘上存储的数据块间的映射,返回 inode ip 中的第 bn 个数据块号;如果没有这样一个数据块,bmap 就会分配一个;未申请的块用块号 0 表示,当 bmap 遇到 0 时就将它们替换为新的块号
1 | |
我们的主要改动在于 fs.h 指针的重新分配,然后对 bmap 做相应的修改即可
相关修改
首先改动 fs.h 内的指针分配,把一个直接指针替换为二级间接指针 DNINDIRECT,此时文件系统有 11 个直接指针,一个一级间接指针和一个二级间接指针,addrs 数组的倒数第二项是第一个间接块的地址,最后一项为第二个间接块的地址。此时 MAXFILE 的值为 11 + 512 / 4 + (512 / 4)^2 = 16523
1 | |
然后为 fs.c 添加二级间接指针的映射关系,这里唯一需要注意的就是如何计算二级间接指针的逻辑坐标

如图,记 bn 为逻辑上我们需要的数据块号(比如 5000),我们需要知道该块对应的一级间接指针坐标以及逻辑上的二级间接指针坐标,只需要进行如下简单的运算:
- 一级间接指针坐标:bn / 128
- 二级间接指针坐标:bn % 128
以 5000 为例,经计算得到bn位于第 39 个一级间接指针指向的指针块,在该块上的下标为 8。补充完整的 bmap 代码如下:
1 | |
完成修改后重新执行 make qemu,键入 big 命令得到以下结果,可见文件系统成功得到扩充,现在最大可指向 16523 个数据块,大小约为 8.46MB
1 | |