2021-xv6实验记录(四)
本次实验,将进行两个任务
- 在 xv6 文件系统的代码里添加对
大文件
的支持- 实现“符号链接”。
在进行实验前,适当地参考“官方参考书”的第 8 个章节——File System
官方实验指南:https://pdos.csail.mit.edu/6.828/2022/labs/fs.html
官方参考书:https://pdos.csail.mit.edu/6.828/2022/xv6/book-riscv-rev3.pdf
老规矩:实验前先切换分支
1 | git fetch |
任务一:【Large files】
实验描述
xv6 文件系统的一个“文件”在存储设备(一般为外存)上的逻辑结构图
在XV6底层实现中,文件是由 struct dinode
来描述的,其代码结构如下
1 | struct dinode { |
根据图中的解释可以清晰的了解到一个文件索引的大小268KB
了解上述基本知识以后,可以尝试在xv6的终端敲入以下命令
1 | bigfile # 敲入的命令是这条,下面是测试结果 |
其中,bigfile 是一个用户层的测试程序,它尝试在分配 268 个块之后再分配 65803 个块,很明显,这个数值超过了 xv6 文件系统的现有限制,因此,抛出file is too small的错误。
- 本次实验的第一个任务已经浮出水面,就是要让 xv6 文件系统支持大文件的创建,以让上述用户层的测试程序能够正常运行。
实验思路
268KB的存储块可以装个啥?装个锤。因此尝试一下在不修改底层dinode结构体大小的情况下
,
- 修改一个之前包含了直接数据块地址的成员变量【就是上述十二个数据块直接地址变量中的一个】,让其指向一个二级间接块
- 二级间接块同样有
256
个条目,但是每个条目指向的是一个一级间接块 - 一级间接块又包含256个条目,每个条目指向一个直接数据块
根据我在脑海中生成的样子:
一些提示
kernel/fs.c
中的bmap()函数是关键点:主要实现将用户传入的相对的逻辑块号(针对文件的偏移)转为一个绝对的物理块号(针对该设备上的偏移,而一个设备可以包含多个文件);目前bmap仅支持直接块和一级间接块的寻址,你需要添加对二级间接块的寻址- 可以修改一个原本用于“存放直接块地址”的成员变量,让其用于存放二级间接块地址(不能变化 dinode 结构体的大小)
NDIRECT
表示 dinode 里直接块地址的数目,而NINDIRECT
表示的是 dinode 结构体里间接块地址的数目(都在 kernel/fs.h 里定义),所以针对它们的宏定义,可能需要得到相应的修改。修改了 NDIRECT 的值,请重新生成 xv6虚拟机的镜像文件——fs.img,生成的方法是在 xv6 的源码根目录下敲——make clean,它在清理一些临时的编译文件同时,会在主机系统里强制生成最新的fs.img(这个镜像文件里包含着整个 xv6 虚拟机的文件系统)- 还有一个名为
MAXFILE
的宏定义,表示当前文件系统所支持的数据块数目,因需要支持大文件所以也需要修改。 - dinode 是索引节点用于存放在外存上(disk)的结构,其实它在内存中也存在一个特定的版本——名为 inode 结构体(定义在
kernel/risc.h
),所以,当你为了支持大文件或者二级间接块修改了 dinode 之后,也请修改 inode 的结构体的相应的成员变量 - 除了分配块的
bmap()
函数,释放块的函数itrunc()
也需要修改kernel/fs.c
,以支持释放或回收后面加入的二级间接块【可以参考itrunc
是怎么处理一级间接块的】
实验过程
因为需要将一个直接索引变成二级间接索引,因此根据【提示 2 和 提示 3 】对宏定义进行修改,打开kernel/fs.h
文件
1 |
修改 struct dinode
和 struct inode
。【提示 5 】
打开kernel/fs.h
文件修改宏定义以及dinode
因为修改了dinode
所以还要修改inode
,打开文件kernel/file.h
修改kernel/fs.c
文件中的 bmap 函数【提示 1】然后修改itrunc
函数【提示 6】
结果验证
任务二:【Symbolic links】
实验描述
- 第二个任务是为 xv6 的文件增加“符号链接”功能
- 增加一个名为
symlink(char *target, char *path)
的系统调用,以实现创建符号链接的功能。target
指的是被创建符号链接的文件路径(包括文件名),而path
指的是该符号链接创建后存放的路径名(包括符号链接本身文件名)
实验思路
- 创建新系统调用的步骤,为 symlink 提供一个接口/入口,内部 实 现 可 以 暂 时 为 空 ( 需 要 修 改 user/usys.pl、user/user.h 、kernel/sysfile.c 等文件
- 在 kernel/stat.h 中,创建一个名为(T_SYMLINK)文件类型,去代表
symlink()
所创建的符号链接类型 (xv6 原本支持的文件类型有三种,分别是常规文件、目录文件和设备文件,现在有了第四种) - 在 kernel/fcntl.h 中,加入一个标志位——O_NOFOLLOW,用于 open()在打开符号链接时,以表明打开的对象为符号链接本身,而不是该符号链接所指向的目标文件(没有该标志位的话,系统将无法区分上述两种情况,因为 open 函数的内部处理需要返回一个指向 inode 的指针,那么这个指针到底是应该指向符号链接文件本身,还是其所指向的对象文件?
- 可能存在一个嵌套或者递归的情况,你用 open 打开的符号链接,其指向的又是另外一个符号链接……我们最多允许 10次递归,超过就报错
实验过程
- 注册系统调用
symlink
【忘记怎么注册?查看实验二】
- 在文件
kernel/sysfile.c
文件中实现sys_symlink函数
- 修改
sys_open
函数
结果验证
Make Grade测试
- 需要创建
time.txt
文件
1 | touch time.txt |
- 测试时间因机器的性能不同而有所偏差,大部分情况存在因为虚拟机性能不够导致运行时间过长因此报错
解决方法:打开根目录下的grade-lab-fs
文件修改【timeout】的值
- 标题: 2021-xv6实验记录(四)
- 作者: 忘记中二的少年
- 创建于 : 2023-11-14 12:44:00
- 更新于 : 2023-11-14 13:02:23
- 链接: https://github.com/HandsomeXianc/HandsomeXianc.github.io/2023/11/14/xv6实验记录(四)/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。