xv6实验记录(四)

xv6实验记录(四)

本次实验,将进行两个任务

  1. 在 xv6 文件系统的代码里添加对大文件的支持
  2. 实现“符号链接”。

在进行实验前,适当地参考“官方参考书”的第 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

老规矩:实验前先切换分支

$ git fetch
# 使用上述fetch的时候系统告诉你要缓存或者提交?那你不会commit?
# git commit -m"实验三缓存"
$ git checkout fs
$ make clean

任务一:【Large files】

实验描述

xv6 文件系统的一个“文件”在存储设备(一般为外存)上的逻辑结构图

image-20231113153800593

在XV6底层实现中,文件是由 struct dinode来描述的,其代码结构如下

struct dinode {
  short type;           // 文件类型
  short major;          // 主设备号(当文件类型是设备的时候)
  short minor;          // 从设备号(当文件类型是设备的时候)
  short nlink;          // 表示有多少个目录指向该索引节点
  uint size;            // 文件大小(字节)
  uint addrs[NDIRECT + 1];   // 数据块地址
};

根据图中的解释可以清晰的了解到一个文件索引的大小268KB

了解上述基本知识以后,可以尝试在xv6的终端敲入以下命令

image-20231113153852899

$ bigfile				# 敲入的命令是这条,下面是测试结果
..
wrote 268 blocks
bigfile: file is too small
$

其中,bigfile 是一个用户层的测试程序,它尝试在分配 268 个块之后再分配 65803 个块,很明显,这个数值超过了 xv6 文件系统的现有限制,因此,抛出file is too small的错误。

  • 本次实验的第一个任务已经浮出水面,就是要让 xv6 文件系统支持大文件的创建,以让上述用户层的测试程序能够正常运行。

实验思路

268KB的存储块可以装个啥?装个锤。因此尝试一下在不修改底层dinode结构体大小的情况下

  1. 修改一个之前包含了直接数据块地址的成员变量【就是上述十二个数据块直接地址变量中的一个】,让其指向一个二级间接块
  2. 二级间接块同样有256个条目,但是每个条目指向的是一个一级间接块
  3. 一级间接块又包含256个条目,每个条目指向一个直接数据块

根据我在脑海中生成的样子:

image-20231113153644623

一些提示
  1. kernel/fs.c中的bmap()函数是关键点:主要实现将用户传入的相对的逻辑块号(针对文件的偏移)转为一个绝对的物理块号(针对该设备上的偏移,而一个设备可以包含多个文件);目前bmap仅支持直接块和一级间接块的寻址,你需要添加对二级间接块的寻址
  2. 可以修改一个原本用于“存放直接块地址”的成员变量,让其用于存放二级间接块地址(不能变化 dinode 结构体的大小)
  3. NDIRECT 表示 dinode 里直接块地址的数目,而 NINDIRECT 表示的是 dinode 结构体里间接块地址的数目(都在 kernel/fs.h 里定义),所以针对它们的宏定义,可能需要得到相应的修改。修改了 NDIRECT 的值,请重新生成 xv6虚拟机的镜像文件——fs.img,生成的方法是在 xv6 的源码根目录下敲——make clean,它在清理一些临时的编译文件同时,会在主机系统里强制生成最新的fs.img(这个镜像文件里包含着整个 xv6 虚拟机的文件系统)
  4. 还有一个名为 MAXFILE 的宏定义,表示当前文件系统所支持的数据块数目,因需要支持大文件所以也需要修改。
  5. dinode 是索引节点用于存放在外存上(disk)的结构,其实它在内存中也存在一个特定的版本——名为 inode 结构体(定义在kernel/risc.h),所以,当你为了支持大文件或者二级间接块修改了 dinode 之后,也请修改 inode 的结构体的相应的成员变量
  6. 除了分配块的 bmap()函数,释放块的函数itrunc()也需要修改kernel/fs.c,以支持释放或回收后面加入的二级间接块【可以参考 itrunc 是怎么处理一级间接块的】

实验过程

因为需要将一个直接索引变成二级间接索引,因此根据【提示 2 和 提示 3 】对宏定义进行修改,打开kernel/fs.h文件

#define NDIRECT 11 // 减少一个直接索引,增加一个二级间接索引
#define NINDIRECT (BSIZE / sizeof(uint))
#define NDINDIRECT NINDIRECT * NINDIRECT // 二级间接索引提供的块
#define MAXFILE (NDIRECT + NINDIRECT + NBI_INDIRECT)//总数据块的数量

修改 struct dinodestruct inode。【提示 5

打开kernel/fs.h文件修改宏定义以及dinode

因为修改了dinode所以还要修改inode,打开文件kernel/file.h

image-20231113154833044

修改kernel/fs.c文件中的 bmap 函数【提示 1】然后修改itrunc函数【提示 6

image-20231113154555188

结果验证

image-20231113153438723

任务二:【Symbolic links】

实验描述

  • 第二个任务是为 xv6 的文件增加“符号链接”功能
  • 增加一个名为symlink(char *target, char *path)的系统调用,以实现创建符号链接的功能。target指的是被创建符号链接的文件路径(包括文件名),而path指的是该符号链接创建后存放的路径名(包括符号链接本身文件名)

实验思路

  1. 创建新系统调用的步骤,为 symlink 提供一个接口/入口,内部 实 现 可 以 暂 时 为 空 ( 需 要 修 改 user/usys.pl、user/user.h 、kernel/sysfile.c 等文件
  2. 在 kernel/stat.h 中,创建一个名为(T_SYMLINK)文件类型,去代表 symlink()所创建的符号链接类型 (xv6 原本支持的文件类型有三种,分别是常规文件、目录文件和设备文件,现在有了第四种)
  3. 在 kernel/fcntl.h 中,加入一个标志位——O_NOFOLLOW,用于 open()在打开符号链接时,以表明打开的对象为符号链接本身,而不是该符号链接所指向的目标文件(没有该标志位的话,系统将无法区分上述两种情况,因为 open 函数的内部处理需要返回一个指向 inode 的指针,那么这个指针到底是应该指向符号链接文件本身,还是其所指向的对象文件?
  4. 可能存在一个嵌套或者递归的情况,你用 open 打开的符号链接,其指向的又是另外一个符号链接……我们最多允许 10次递归,超过就报错

实验过程

  • 注册系统调用symlink【忘记怎么注册?查看实验二】

image-20231113162939169

  • 在文件kernel/sysfile.c文件中实现sys_symlink函数

image-20231113161311951

  • 修改sys_open函数

image-20231113161535075

结果验证

image-20231113163247065

Make Grade测试

  • 需要创建time.txt文件
touch time.txt
vim time.txt  
  • 测试时间因机器的性能不同而有所偏差,大部分情况存在因为虚拟机性能不够导致运行时间过长因此报错

解决方法:打开根目录下的grade-lab-fs文件修改【timeout】的值

image-20231114113527078
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_橙留香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值