6.s081 学习实验记录(十)file system

文章目录

    • 一、Large files
      • 简介
      • 提示
      • 实验代码
      • 实验结果
    • 二、Symbolic links
      • 简介
      • 提示
      • 实验代码
      • 实验结果

首先切换到 fs 分支

  • $ git fetch
  • $ git checkout fs
  • $ make clean

一、Large files

简介

该实验需要我们增大xv6文件的最大大小,目前xv6的最大文件大小为 268个块,即 268 * BSIZE。这是因为 xv6 包含12个直接块号 和 一个一级间接块号最大索引 12 + 256 = 268 个块

bigfile 命令将创建xv6允许的最大文件,并报告其大小,未进行实验前结果如图:
在这里插入图片描述
我们需要让xv6支持二级间接块,这样支持的索引块号最大为 11 + 256 + 256 * 256 = 65803 个,这样即可满足 bigfile 的测试要求。

我们的任务:修改 bmap() 函数让其可以支持二重间接块号,

提示

  • 磁盘文件的inode定义由 fs.hstruct inode 定义
  • 主目录中的 mkfs 程序用于创建 xv6 文件系统磁盘硬件并确定该磁盘总共多少数据块,磁盘的总大小由 kernel/param.h 中的FSSIZE 控制,当前分支已经将磁盘的大小改为 20w 个块大小
  • 在磁盘上查找文件数据的函数是 fs.cbmap(),阅读它并确保知道该函数在做什么。该函数在读取和写入文件时都会被调用,写入时bmap()根据需要分配新的块来保存内容,并根据需要分配间接块来保存块地址。
  • 可以将 bmap() 函数理解为将文件的逻辑块号映射为磁盘的物理块号,该函数的 bn 参数表示逻辑块号。而 ip->addrs[] 数组下标和 bread() 需要的都是物理块号,因此 bmap() 需要将 bn 转换为物理块号
  • 如果修改NDIRECT的定义,应该同时修改 file.hstruct inodeaddrs[]数组的大小,需要让他们保证元素数目一致
  • 不要忘记在 bread() 后对读取的块使用 brelse() 函数
  • 确保 itrunc() 可以释放所有块,包括二级间接块

实验代码

本实验中磁盘的最大已经改为20w,因此无需通过mkfs重新创建磁盘。我们只需要修改bmap()即可。

  • fs.h
#define NDIRECT 11
#define ONE_LEVEL_INDIRECT_IDX 11
#define TWO_LEVEL_INDIRECT_IDX 12
#define NINDIRECT (BSIZE / sizeof(uint))
#define N_TWO_INDIRECT NINDIRECT * NINDIRECT
#define MAXFILE (NDIRECT + NINDIRECT + N_TWO_INDIRECT)// On-disk inode structure
struct dinode {short type;           // File typeshort major;          // Major device number (T_DEVICE only)short minor;          // Minor device number (T_DEVICE only)short nlink;          // Number of links to inode in file systemuint size;            // Size of file (bytes)uint addrs[NDIRECT+2];   // Data block addresses
};
  • fs.c
struct {struct spinlock lock;struct inode inode[TWO_LEVEL_INDIRECT_IDX];
} itable;static uint
bmap(struct inode *ip, uint bn)
{uint addr, *a;struct buf *bp;// 如果是直接块if(bn < NDIRECT){if((addr = ip->addrs[bn]) == 0)ip->addrs[bn] = addr = balloc(ip->dev);return addr;}bn -= NDIRECT;// 如果属于一级间接块的范围if(bn < NINDIRECT){// Load indirect block, allocating if necessary.if((addr = ip->addrs[NDIRECT]) == 0)ip->addrs[NDIRECT] = addr = balloc(ip->dev);bp = bread(ip->dev, addr);a = (uint*)bp->data;if((addr = a[bn]) == 0){a[bn] = addr = balloc(ip->dev);log_write(bp);}brelse(bp);return addr;}bn -= NINDIRECT;// 属于二级索引块// 二级索引块地址 ---> 二级索引块,内容为一级索引块地址 ---> 一级索引块,内容为实际数据块地址 ---> 数据块if(bn < N_TWO_INDIRECT){// 加载二级间接索引块,如果二级索引块还未分配,则分配一个数据块作为二级索引块// 如果二级索引块不存在,为其分配地址,并记录在 addrs 数组对应的位置if((addr = ip->addrs[TWO_LEVEL_INDIRECT_IDX]) == 0){ip->addrs[TWO_LEVEL_INDIRECT_IDX] = addr = balloc(ip->dev);}// 读取二级索引块,内容为一级索引块地址bp = bread(ip->dev, addr);a = (uint*)bp->data;// bn 必定是可以整除 NINDIRECT 的数,决定查询一级索引的第几项,如果此时一级索引块也未分配// 分配一级索引块,并将地址记录到对应的二级索引块中if((addr = a[bn / NINDIRECT]) == 0){a[bn / NINDIRECT] = addr = balloc(ip->dev);log_write(bp);}brelse(bp);// 读取一级索引块的内容bp = bread(ip->dev, addr);a = (uint*)bp->data;// 得到在一级索引块中实际数据块的idx,如果不存在,则分配if((addr = a[bn % NINDIRECT]) == 0){a[bn % NINDIRECT] = addr = balloc(ip->dev);log_write(bp);}brelse(bp);return addr;}panic("bmap: out of range");
}

实验结果

  • usertests -q(该程序至少需要运行1分半)
    在这里插入图片描述
  • userstest -q
    在这里插入图片描述

二、Symbolic links

简介

实现符号链接(软链接)
目标:实现 symlink(char *target, char *path) 系统调用,该系统调用在path表示路径下创建一个新的符号链接,引用target路径。最终通过symlinktest测试。

提示

  • 创建一个新的系统调用 symlink,在 user/usys.pl, user/user.h添加对应的项,在 kernel/sysfile.c 中实现sys_symlink()函数
  • kernel/stat.h 中添加T_SYMLINK文件类型,表示符号链接类型的文件
  • kernel/fcntl.h添加一个新的flag标志位O_NOFOLLOW,该标记位将在 open() 系统调用中使用。注意flag标记位在open() 中使用时需要使用按位或(or)
  • 实现 symlink 系统调用的逻辑,需要在一个地方先缓存 target 路径,可以选择存储在 inode的数据块中,同时该系统调用应该在成功时返回0,失败时返回-1
  • 修改 open()系统调用,在打开一个符号链接文件时,如果其引用的对象不存在,则打开失败,如果存在,则打开其引用的对象
  • 如果符号链接文件引用的文件依然是符号链接文件,那么需要递归的去引用,直到遇到一个非链接文件。如果递归变为循环递归,需要返回错误,且需要添加一个递归阈值(例如10)以防止无限制递归。
  • 其他系统调用,操作符号链接文件本身时,就应该操作该文件本身(例如 link、unlink)。
  • 无需处理对于目录的符号链接

实验代码

  • kernel/fcntl.h
#define O_NOFOLLOW 0x004
  • kernel/stat.h
#define T_SYMLINK  4  // symbol link
  • user/user.h
int symlink(char *target, char *path);
  • user/usys.pl
entry("symlink");
  • makefile
$U/_symlinktest\
  • kernel/syscall.h
#define SYS_symlink  22
  • kernel/syscall.c
extern uint64 sys_symlink(void);static uint64 (*syscalls[])(void) = {
// ...
[SYS_close]   sys_close,
[SYS_symlink] sys_symlink,
};
  • kernel/sysfile.c:sys_symlink 可以参考 sys_link
uint64
sys_symlink(void){char target[MAXPATH];char path[MAXPATH];struct inode *ip;if((argstr(0, target, MAXPATH)) < 0 || argstr(1, path, MAXPATH) < 0)return -1;begin_op();// 如果是目录,返回错误if((ip = namei(target)) != 0){ilock(ip);if(ip->type == T_DIR){iunlock(ip);end_op();return -1;}iunlock(ip);}// 创建软链接文件,返回的是一个上锁的fdip = create(path, T_SYMLINK, 0, 0);if(ip == 0){end_op();return -1;}// 将 target 路径写入到软链接文件中if(writei(ip, 0, (uint64)target, 0, strlen(target) + 1) <= 0) {end_op();return -1;}iunlockput(ip);end_op();return 0;
}
  • kernel/sysfile.c:修改 sys_open(),添加对于软链接文件的处理
uint64
sys_open(void){// ...begin_op();if(omode & O_CREATE){ip = create(path, T_FILE, 0, 0);if(ip == 0){end_op();return -1;}} else {if((ip = namei(path)) == 0){end_op();return -1;}ilock(ip);if(ip->type == T_DIR && omode != O_RDONLY){iunlockput(ip);end_op();return -1;}if (ip->type == T_SYMLINK && !(omode & O_NOFOLLOW)) {int total = 10;while (ip->type == T_SYMLINK && total > 0) {// 读取软链接文件中存储的 target 路径if(readi(ip, 0, (uint64)path, 0, ip->size) != ip->size) {iunlockput(ip);end_op();return -1;}iunlockput(ip); //释放软链接文件的锁// ip重新赋值为软链接 target 指向的文件if((ip = namei(path)) == 0) {end_op();return -1;}// 锁住,进行下一轮判断ilock(ip);total--;}// 超过循环上限if (total == 0) {iunlockput(ip);end_op();return -1;}}}// ... 其他代码
}

实验结果

  • symlinktest
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/475321.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Postman轻松签名,让SHA256withRSA保驾护航!

前言 在接口测试中&#xff0c;我们经常需要对请求进行签名&#xff0c;以保证数据的安全性。而SHA256withRSA是一种较为常见的签名算法&#xff0c;它可以使用私钥对数据进行签名&#xff0c;使用公钥进行验签。 但是&#xff0c;实现该算法签名可能会涉及到一些繁琐的操作&…

嵌入式 day23

链接命令 建立链接文件&#xff1a;ln 命令 命令名称&#xff1a;ln 命令所在路径&#xff1a;/bin/ln 执行权限&#xff1a;所有用户 语法&#xff1a;ln -s [原文件] [目标文件] -s 创建软链接 功能描述&#xff1a;生成链接文件 范例&#xff1…

【GPT-2】论文解读:Language Models are Unsupervised Multitask Learners

文章目录 介绍zero-shot learning 零样本学习 方法数据Input Representation 结果 论文&#xff1a;Language Models are Unsupervised Multitask Learners 作者&#xff1a;Alec Radford, Jeff Wu, Rewon Child, D. Luan, Dario Amodei, I. Sutskever 时间&#xff1a;2019 介…

Java集合篇之set,面试官:请说一说HashSet、LinkedHashSet、TreeSet的区别?

写在开头 Java的集合世界中主要由List&#xff0c;Set&#xff0c;Queue&#xff0c;Map构成&#xff0c;我们在之前的博文中已经学习了List&#xff0c;接下来我们继续学习Set集合。 Set特点&#xff1a;存取无序&#xff0c;不可以存放重复的元素&#xff0c;不可以用下标对…

Sentinel注解@SentinelResource详解

Sentinel注解SentinelResource详解 熔断 针对访问超过限制【sentinel中配置的限制】的资源&#xff0c;通过java代码配置&#xff0c;返回一个自定义的结果&#xff0c;需要用到 SentinelResource 注解的 blockHandlerClass 和 blockHandler 属性。 blockHandlerClass&#…

Electron实战之进程间通信

进程间通信&#xff08;IPC&#xff09;并非仅限于 Electron&#xff0c;而是源自甚至早于 Unix 诞生的概念。尽管“进程间通信”这个术语的确创造于何时并不清楚&#xff0c;但将数据传递给另一个程序或进程的理念可以追溯至 1964 年&#xff0c;当时 Douglas McIlroy 在 Unix…

review 10

整理磁盘操作的完整流程&#xff0c;如何接入虚拟机&#xff0c;是否成功识别&#xff0c;对磁盘分区工具的使用&#xff0c;格式化&#xff0c;挂载以及取消挂载、复习cp、mv和find指令 1&#xff1a;U盘接入虚拟机 在弹出窗口直接选择 虚拟机-可移动设备-找到u盘-连接 2&a…

04_device_bus_driverLinux内核模块

01_basicLinux内核模块-CSDN博客文章浏览阅读45次。环境IDubuntuMakefilemodules:clean:basic.creturn 0;运行效果。https://blog.csdn.net/m0_37132481/article/details/136157384?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%…

实习日志15

1.大改了一下界面 1.1.识别与验真 1.2.历史记录 2.改了几个bug 2.1.改json格式用JSON.stringify(value,null,2); 2.2.内嵌页面值与原页面值重复 2.3.验真条件判断 if (isVerifyCell.getValue() "不需要") {if (verifyResultCell.getValue() ! "未查验")…

树和二叉树的基本知识

一、树的概念及结构 1.树的概念 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因 为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的 。 有一个 特殊…

分享一个学英语的网站

名字叫&#xff1a;公益大米网​​​​​​​ Freerice 这个网站是以做题的形式来记忆单词&#xff0c;题干是一个单词&#xff0c;给出4个选项&#xff0c;需要选出其中最接近题干单词的选项。 答对可以获得10粒大米&#xff0c;网站的创办者负责捐赠。如图 触发某些条件&a…

Linux系统的历史记录添加时间和IP信息

1 为什么要优化系统历史记录 对于linux系统&#xff0c;默认情况下&#xff0c;系统记录的历史命令比较简单。某些历史记录可能也无法正常保存&#xff0c;因此当服务器出现异常&#xff0c;希望通过历史命令来了解曾经做了哪些操作时&#xff0c;往往非常被动&#xff0c;下面…