【MIT 6.S081】2020, 实验记录(9),Lab: file system

目录

    • Task 1:Large files
    • Task 2:Symbolic links
      • 2.1 增加一个系统调用 symlink
      • 2.2 新增文件类型
      • 2.3 新增 NOFOLLOW 标志位
      • 2.4 实现 sys_symlink 系统调用
      • 2.5 修改 sys_open 函数
      • 2.6 测试

Task 1:Large files

现在的 xv6 系统中,一个文件的 data block 的索引目录最多到一级间接索引:

现有的一级间接索引

而这个 task 为了增大可支持的最大文件大小,要求扩展出二级间接索引,如下图:

二级间接索引

代码实现上,主要是扩展 fs.c 文件中的 bmap()itrunc() 函数:

  • bmap():传入相对的 block number(比如这个文件的第一个 block 的相对 block number 就是 0),返回这个 block 的地址。如果没有的话需要分配创建。
  • itrunc():释放一个文件的所有 blocks

直接索引表上有 13 个元素位置,原本是 12 个直接索引 + 1 个一级间接索引,现在需要改成 11 个直接索引 + 1 个一级间接索引 + 1 个二级间接索引。

修改 fs.h 文件中的相关参数:

在这里插入图片描述
相应的修改 dinode 和 inode 中 addrs 的元素数量(因为宏 NDIRECT 数值变了,所以这两个地方需要相应地修改一下):

dinode
inode

bmap() 函数中增加对耳机间接索引的支持:

static uint
bmap(struct inode *ip, uint bn)
{uint addr, *a;struct buf *bp;// 检查 bn 是否可以走直接索引if(bn < NDIRECT){if((addr = ip->addrs[bn]) == 0)  // 如果发现 bn 的 block 还不存在,则 alloc 一个 blockip->addrs[bn] = addr = balloc(ip->dev);return addr;}bn -= NDIRECT;// 检查 bn 是否可以走一级间接索引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;// 检查 bn 是否可以走二级间接索引if (bn < N_DOUBLE_INDIRECT) {if ((addr = ip->addrs[NDIRECT + 1]) == 0) {ip->addrs[NDIRECT + 1] = addr = balloc(ip->dev);}// 先从一级间接索引中找bp = bread(ip->dev, addr);a = (uint*)bp->data;uint level1 = bn / NINDIRECT;  // 在一级索引目录中的 indexif ((addr = a[level1]) == 0) {a[level1] = addr = balloc(ip->dev);log_write(bp);}brelse(bp);// 再从二级间接索引中找bp = bread(ip->dev, addr);a = (uint*)bp->data;uint level2 = bn % NINDIRECT;  // 在二级索引目录中的 indexif ((addr = a[level2]) == 0) {a[level2] = addr = balloc(ip->dev);log_write(bp);}brelse(bp);return addr;}panic("bmap: out of range");
}

itrunc() 函数中增加对二级间接索引的支持:

void
itrunc(struct inode *ip)
{int i, j;struct buf *bp;uint *a;for(i = 0; i < NDIRECT; i++){if(ip->addrs[i]){bfree(ip->dev, ip->addrs[i]);ip->addrs[i] = 0;}}if(ip->addrs[NDIRECT]){bp = bread(ip->dev, ip->addrs[NDIRECT]);a = (uint*)bp->data;for(j = 0; j < NINDIRECT; j++){if(a[j])bfree(ip->dev, a[j]);}brelse(bp);bfree(ip->dev, ip->addrs[NDIRECT]);ip->addrs[NDIRECT] = 0;}// 释放二级间接索引目录下的 blocksif (ip->addrs[NDIRECT + 1]) {// 从直接索引中记录的指针,访问一级间接索引struct buf *bp1 = bread(ip->dev, ip->addrs[NDIRECT + 1]);  // 一级间接索引的 blockuint *a1 = (uint*)bp1->data;for(j = 0; j < NINDIRECT; j++) {  // 遍历一级间接索引的所有索引项if (a1[j]) {// 从一级间接索引中记录的指针,访问二级间接索引struct buf *bp2 = bread(ip->dev, a1[j]); // 二级间接索引的 blockuint *a2 = (uint*)bp2->data;for(int k = 0; k < NINDIRECT; k++) {  // 遍历二级间接索引的所有索引项if (a2[k])bfree(ip->dev, a2[k]);  // 释放这个 data block}brelse(bp2);bfree(ip->dev, a1[j]);   // 释放二级间接索引的 block}//释放完了二阶指针块,}brelse(bp1); bfree(ip->dev, ip->addrs[NDIRECT + 1]);  // 释放一级间接索引的 blockip->addrs[NDIRECT + 1] = 0;}ip->size = 0;iupdate(ip);
}

测试:

在这里插入图片描述

usertests 的结果:

usertests

Task 2:Symbolic links

这个 task 目标是新增一个系统调用,支持创建符号连接,就是一种新的文件类型,它链接到了另一个实际的文件。实现的思路就是,增加一种新的文件类型 “symlink”,创建 symlink 时,在文件内容中写入实际链接的文件名,这样就可以实现链接过去了。

2.1 增加一个系统调用 symlink

在 syscall.h 中增加一个新的系统调用号:

syscall.h
在 user/usys.pl 中增加一个 entry:

entry
在 user/user.h 中增加声明:

在这里插入图片描述
在 kernel/syscall.c 中的系统调用表中增加这个系统调用:

syscall.c

2.2 新增文件类型

我们需要新增一种 SYMLINK 的文件类型:

SYMLINK

2.3 新增 NOFOLLOW 标志位

按照 lab 官网给出的提示:

Add a new flag to kernel/fcntl.h, (O_NOFOLLOW), that can be used with the open system call. Note that flags passed to open are combined using a bitwise OR operator, so your new flag should not overlap with any existing flags. This will let you compile user/symlinktest.c once you add it to the Makefile.

我们在 kernel/fcntl.h 中增加这个 flag:

NOFOLLOW

2.4 实现 sys_symlink 系统调用

在 kernel/sysfile.c 中,我们实现 sys_symlink() 函数,用来在 path 上创建一个链接到 target 的 SYMLINK 文件:

uint64 sys_symlink(void)
{char target[MAXPATH], path[MAXPATH];  // 在 path 上创建一个 symlink 指向 targetstruct inode *dp, *ip;// 校验并绑定参数if (argstr(0, target, MAXPATH) < 0 || argstr(1, path, MAXPATH) < 0) {return -1;}begin_op();  // 开始一个文件系统操作// 校验 target 是否合法if ((ip = namei(target)) != 0 && ip->type == T_DIR) {end_op();goto bad;}// 创建 symlink 文件dp = create(path, T_SYMLINK, 0, 0);  // 这一步会同时为 inode 加锁if (dp == 0) {goto bad;}// 在 symlink 文件中写入 target 信息int targetLen = strlen(target);if (writei(dp, 0, (uint64)target, 0, targetLen) != targetLen) {panic("symlink: writei");  // 模仿 sys_unlink() 函数中的写法}iunlockput(dp);  // 释放 inode 的 lockend_op();return 0;bad:end_op();return -1;
}

2.5 修改 sys_open 函数

我们需要修改 sys_open() 函数,官网给出的提示是:

  • Modify the open system call to handle the case where the path refers to a symbolic link. If the file does not exist, open must fail. When a process specifies O_NOFOLLOW in the flags to open, open should open the symlink (and not follow the symbolic link).
  • If the linked file is also a symbolic link, you must recursively follow it until a non-link file is reached. If the links form a cycle, you must return an error code. You may approximate this by returning an error code if the depth of links reaches some threshold (e.g., 10).

sys_open
该函数的完整代码如下:

uint64
sys_open(void)
{char path[MAXPATH];int fd, omode;struct file *f;struct inode *ip;int n;if((n = argstr(0, path, MAXPATH)) < 0 || argint(1, &omode) < 0)return -1;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;}}// 当没有 NOFOLLOW 标志时,对于 SYMLINK 文件,默认的行为是打开的链接过去的 target 文件if ((omode & O_NOFOLLOW) == 0) {struct inode *dp;char target[MAXPATH];int i;for (i = 0; i < 10 && ip->type == T_SYMLINK; i++) {// 从 inode 读取数据if (readi(ip, 0, (uint64)target, 0, MAXPATH) == 0) {iunlockput(ip);end_op();return -1;}// 读取 target 的 inodedp = namei(target);if (dp == 0) {iunlockput(ip);end_op();return -1;}iunlockput(ip);ip = dp;ilock(ip);}// 如果 10 轮循环后也没找到 target 原文件if (i == 10) {iunlockput(ip);end_op();return -1;}}if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){iunlockput(ip);end_op();return -1;}if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){if(f)fileclose(f);iunlockput(ip);end_op();return -1;}if(ip->type == T_DEVICE){f->type = FD_DEVICE;f->major = ip->major;} else {f->type = FD_INODE;f->off = 0;}f->ip = ip;f->readable = !(omode & O_WRONLY);f->writable = (omode & O_WRONLY) || (omode & O_RDWR);if((omode & O_TRUNC) && ip->type == T_FILE){itrunc(ip);}iunlock(ip);end_op();return fd;
}

2.6 测试

完成以上代码实现后,测试就可以跑通过了:

symlinktest

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

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

相关文章

算法——贪心算法

《算法图解》——贪心算法 # 首先创建一个表&#xff0c;包含所覆盖的州 states_needed set([mt,wa,or,id,nv,ut,az]) # 传入一个数组&#xff0c;转换成一个集合#可供选择的广播台清单 stations {} stations[kone] set([id,nv,ut]) #用集合表示想要覆盖的州&#xff0c;且不…

EMQX 4.0和EMQX 5.0集群架构实现1亿MQTT连接哪些改进

EMQX 5.0水平扩展能力得到了指数级提升&#xff0c;能够更可靠地承载更大规模的物联网设备连接量。 在EMQX5.0正式发布前的性能测试中&#xff0c;我们通过一个23节点的EMQX集群&#xff0c;全球首个达成了1亿MQTT连接每秒100万消息吞吐&#xff0c;这也使得EMQX 5.0成为目前为…

Jenkins流水线将制品发布到Nexus存储库

1、安装jenkins&#xff08;建议别用docker安装&#xff0c;坑太多&#xff09; docker run -d -p 8089:8080 -p 10241:50000 -v /var/jenkins_workspace:/var/jenkins_home -v /etc/localtime:/etc/localtime --name my_jenkins --userroot jenkins/jenkins:2.449 坑1 打开x…

Python使用 k 均值对遥感图像进行语义分割

本篇文章介绍K-means语义分割来估计 2000 年至 2023 年咸海水面的变化 让我们先看一下本教程中将使用的数据。这是同一地区的两张 RGB 图像,间隔 23 年,但很明显地表特性和大气条件(云、气溶胶等)不同。这就是为什么我决定训练两个独立的 k-Means 模型,每个图像一个。 首…

仰卧起坐计数,YOLOV8POSE

仰卧起坐计数&#xff0c;YOLOV8POSE 通过计算膝盖、腰部、肩部的夹角&#xff0c;计算仰卧起坐的次数

[江苏工匠杯]easyphp

先看源码 <?php highlight_file(__FILE__); $key1 0; $key2 0; ​ $a $_GET[a]; $b $_GET[b]; ​ if(isset($a) && intval($a) > 6000000 && strlen($a) < 3){if(isset($b) && 8b184b substr(md5($b),-6,6)){$key1 1;}else{die("…

mvn 相关命令汇总

1、需求 项目上一致是使用的mvn 进行打包, 对于项目上的一些mvn 命令&#xff0c;有时候会忘记&#xff0c;所以将mvn 汇总起来 2、命令汇总 ① mvn clean 将项目目录下的编译的文件清除掉,即target 文件夹的编译文件 ② mvn complie 编译项目的代码&#xff0c;生成class 文…

Spring boot2.7整合jetcache方法缓存

前面的文章 我们讲了 spring boot 整合 jetcache 做基本字符串数据缓存 但是 我这里有个这样的逻辑 我的 domain 包下 有一个 book 属性类 里面就 id 和 name 属性 设置了 对应的 set get函数 和一个整体的构造函数 package com.example.javadom.domain;public class book {pr…

TrueNAS怎么设置中文,最新2024版本安装详细说明

首先我们做好安装前的准备工作 1&#xff0c;ISO镜像安装包 2&#xff0c;虚拟机&#xff08;建议使用ESXI虚拟机环境&#xff09; 如果是物理机安装&#xff0c;建议先给底层安装虚拟机系统esxi&#xff0c;再在上面安装方便以后的管理&#xff0c;如果你想物理机直接安装&a…

3.15消费者权益保护教育宣传活动怎样联系媒体投稿宣传?

在315金融消费者权益保护教育宣传活动中,想要有效地联系媒体报道并进行便捷宣传,可以通过以下步骤来利用智慧软文发布系统进行操作: 1. 准备宣传素材: - 制作高质量的新闻稿件,内容应围绕金融消费者权益保护的主题,包含活动的目的、特色、实施计划、预期影响、参与方式等细节;…

怎么看一手伦敦银多少钱?

做伦敦银投资的朋友需要搞清楚“一手伦敦银多少钱”的问题&#xff0c;这也是伦敦银交易的基础问题。为什么需要搞清楚这个基础问题呢&#xff1f;有些基础问题我们不需要搞懂&#xff0c;但是关于一手伦敦银多少钱却需要搞清楚&#xff0c;因为这决定了投资者的资金利用率。 关…

复合材料热压机比例阀放大器

复合材料热压机动作主要依赖于其内置的液压系统。是工业生产中常用的设备&#xff0c;通过施加高温和高压来实现对材料的压制成型。为了确保热压板能够精确地上下移动以及保持所需的压力&#xff0c;通常会使用液压系统来控制。液压系统中必不可少的需要比例阀来控制油缸的运行…

【数字孪生】Nginx发布数字孪生三维建模模型服务及调用方法

【数字孪生】Nginx发布数字孪生三维建模模型服务及调用方法 一、需求二、实施步骤2.1 准备模型文件2.1.1 3D tiles模型2.1.2 3D Tiles标准文件格式 2.2 配置nginx server块2.2.1 Nginx能干啥 2.3 访问 三、实现效果 一、需求 利用三维渲染引擎Cesium加载3D tiles模型。 二、实…

下载JDK17版本详细教程(下载、安装、环境变量配置)

官网下载 Oracle 甲骨文中国 | 云应用和云平台 安装 更改自己的安装位置。点击下一步&#xff0c;记住自己的安装位置 环境配置 右键此电脑点击属性---高级系统设置----环境变量 在系统变量里面点击新建环境变量JAVA_HOME&#xff0c;下面填入自己的jdk安装地址&#xff0c…

关于微服务跨数据库联合查询的一些解决思路

微服务架构的一个非常明显的特征就是一个服务所拥有的数据只能通过这个服务的API来访问。通过这种方式来解耦&#xff0c;这样就会带来查询问题。以前通过join就可以满足要求&#xff0c;现在如果需要跨多个服务集成查询就会非常麻烦。 解决思路 下面提供几个思路仅供参考 表…

【鸿蒙HarmonyOS开发笔记】常用组件介绍篇 —— Toggle切换按钮组件

概述 Toggle为切换按钮组件&#xff0c;一般用于两种状态之间的切换&#xff0c;例如下图中的蓝牙开关。 参数 Toggle组件的参数定义如下 Toggle(options: { type: ToggleType, isOn?: boolean })● type type属性用于设置Toggle组件的类型&#xff0c;可通过ToggleType枚举…

python异常:pythonIOError异常python打开文件异常

1.python读取不存在的文件时&#xff0c;抛出异常 通过 open()方法以读“r”的方式打开一个 abc.txt 的文件&#xff08;该文件不存在&#xff09;&#xff0c;执行 open()打开一个不存在的文件时会抛 IOError 异常&#xff0c;通过 Python 所提供的 try...except...语句来接收…

linux查看服务器登录成功和登录失败的命令

last 查看成功登录服务器的信息&#xff0c;包括ip&#xff0c;时间&#xff0c;登录用户&#xff0c;时长。lastb 查看登录服务器失败的信息。 last命令实例&#xff1a; 其他参数&#xff1a; -a&#xff1a;把从何处登入系统的主机名称或ip地址&#xff0c;显示在最后一行…

.rmallox勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复

导言&#xff1a; 近年来&#xff0c;勒索病毒的威胁日益增加&#xff0c;其中一种名为.rmallox的勒索病毒备受关注。这种病毒通过加密文件并勒索赎金来威胁受害者。本文将介绍.rmallox勒索病毒的特点&#xff0c;以及如何恢复被其加密的数据文件&#xff0c;并提供预防措施&a…

Css提高——flex布局及其相关属性

目录&#xff1a; 1、传统布局与flex布局的区别 2、flex的布局原理 3、flex常见的父项属性 3.1、flex-direction &#xff1a;设置主轴的方向 3.2、justify-content 设置主轴上的子元素排列方式 3.3、flex-wrap 设置子元素是否换行 3.4、align-items 设置侧轴上的子元素排…