lab9 fs

news2025/1/20 3:53:25

image-20230829122900742

文章目录

  • Large files
    • task
    • hints
    • 思路
  • Symbolic links
    • task
    • hints
    • 思路
      • sys_symlink
      • sys_open

Large files

目标:11+256+256*256个block

inode的格式在fs.hstruct dinode中被定义,你需要特别注意以下几点

  1. NDIRECT
  2. NINDIRECT
  3. MAXFILE
  4. addrs[]

在磁盘上找一个文件数据是通过fs.c中的bmap()实现的

  1. 无论是读还是写文件,都调用了bmap
  2. 在写文件时,bmap()分配了新的block去容纳文件内容,在必要的时候,会去分配一个非直接映射块

bmap处理了两种块号

  1. bn参数是一个逻辑块号,是在一个文件中相对于文件起始位置的块号
  2. ip->addrs[]bread()的参数中的块号,都是磁盘块号
  3. 你可以将bmap看做是逻辑块号到物理块号的映射

task

  1. 修改bmap使其通过addrs[]支持11+256+256*256个磁盘块
  2. 如果能通过bigfileusertests测试,就说明成功

hints

  1. 保证你理解了bmap()。画图理清楚inode中不同类型的块的指向和作用
  2. 想一下你如何通过逻辑块号索引一级地址块和直接地址块
  3. 如果你改变了NDIRECT,你可能需要去改变file.hstruct inode中的addrs[]的声明。保证struct inodestruct dinode在addrs数组中有相同数量的元素
  4. 如果你改变了NDIRECT的定义,保证你创造了一个新的fs.img,即make clean 然后make qemu
  5. 对任何一个block进行bread之后都要记得brelse
  6. 你应该只在必要的时候分配一级地址和二级地址
  7. 保证itrunc将一个文件所有的block都free了,包括新增的二级地址

思路

文件系统这一块,感觉学的很难,各种函数很多,但是这个task这一块是不太难,不过我也做了好久。。。

这个task只需要修改bmapitrunc两个函数,以及一些宏常量,之所以只修改这么点东西就可以给一个文件扩容,应该是因为其他函数都是通过bmap来获取逻辑块对应的物理块号的,它们只负责要和写,根本不管到底使用了多少block

首先,需要修改一些宏常量,并且将dinodeinodeaddrs数组长度修改

#define NDIRECT 11
#define NINDIRECT (BSIZE / sizeof(uint))
#define N2INDIRECT (NINDIRECT * NINDIRECT)
#define MAXFILE (NDIRECT + NINDIRECT + N2INDIRECT)

uint addrs[NDIRECT + 2];

然后,修改bitmap函数,首先可以看一下bitmap如何处理直接地址和一级地址,学习一下基本的思路,我们这里基本就是嵌套一下一级地址的情况。

具体实现如下:

  1. 首先,将逻辑块号减去一级地址的块数

  2. 然后这里使用了一个search函数

    uint search(struct inode *ip, uint index, uint bn, uint *addrs)

    这个函数的意思是,目前寻找的文件的inode是ip,现在要去addrs数组的index项指向的那个多级地址块上的第bn个block的地址,如果第bn块处没有地址,那么就创建一个。所以这个本质上就是一个一级地址的情况,通过两次调用这个函数,就可以完成我们二级地址的查找

代码如下

uint search(struct inode *ip, uint index, uint bn, uint *addrs) {
    uint addr, *a;
    struct buf *bp;
    if ((addr = addrs[index]) == 0) {
        addrs[index] = 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;
}

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 < N2INDIRECT) {
        int index = bn / NINDIRECT;
        int nbn = bn % NINDIRECT;
        addr = search(ip, NDIRECT + 1, index, ip->addrs);
        bp = bread(ip->dev, ip->addrs[NDIRECT + 1]);
        addr = search(ip, index, nbn, (uint *)bp->data);
        brelse(bp);
        return addr;
    }

    panic("bmap: out of range");
}

Symbolic links

task

  1. 增加一个系统调用symlink(char *target, char *path)
  2. 需要通过symlinktestusertests

hints

  1. 增加系统调用的流程

    1. Makefile,加入的不是symlink,而是symlinktest
    2. user/usys.pl
    3. user/user.h
    4. kernel/sysfile.c
    5. syscall.h && syscall.c
  2. kernel/stat.h中增加一个新的文件类型T_SYMLINK代表软链接

  3. kernel/fcntl.h中增加一个标志位O_NOFOLLOW,因为open文件的标志位是or起来的,因此你不能和已有的发生重叠

  4. 你需要找一个位置去存储软链接的目标地址,例如在inode数据块

    symlink应该返回0表示成功,返回-1表示失败

  5. 修改open系统调用去处理一个路径指向软链接的情况

    如果文件不存在,open必须失败

    当一个进程在open中指定了O_NOFOLLOW,则说明不是打开target,而是打开软链接

  6. 如果被链接的文件也是一个软链接,你必须递归地访问,直到访问一个正确的文件

    你可以定义最大递归的层数,比如10

  7. Other system calls (e.g., link and unlink) must not follow symbolic links; these system calls operate on the symbolic link itself.

  8. 你不需要处理软链接到目录的情况

思路

这玩意看着很抽象,但是其实搞清楚以下几件事就行了

  1. 访问文件就是先访问得到inode,然后通过inode去写对应的文件

    通过readi就可以读取path对应的inode

    通过writei就可以在inode对应的文件中去写

  2. 软链接的作用

    在open它的时候,它会直接导向target

  3. 创建软链接,分为以下几步

    1. 首先创建一个文件,即获得一个inode,这个可以通过create函数实现
    2. 将我们的target写入这个inode,我们就将target存在第一个文件数据块就行了
  4. 打开软链接对应的文件,分为以下几步

    1. 在open中获取软链接对应的真实的inode
    2. 然后就让open对这个inode进行分配fd和file的操作即可

代码很少,但是思路真的很有意思

sys_symlink

这里可以先看看create和open的代码是如何使用xv6提供的一些api的,主要是

create,writei,readi

  1. 首先,我们需要将target和path这两个参数从寄存器中读出来,使用argstr即可
  2. 然后,我们需要创建inode,使用create函数,第一个参数是软链接的路径,第二个参数是文件类型,我们这里当然是新建的那个,后面两个参数不知道啥意思,模仿其他函数的使用,填0
  3. 将target写入软链接文件,也就是写入数据块,使用writei函数
    1. 第一个参数是inode的指针
    2. 第三个参数是我们写入的东西的地址,这里就是target的地址
    3. 第四个参数是写到文件的哪里,其实就是使用一个偏移量完成,我们软链接文件没其他的文件内容,就写到偏移量为0的地方,也就是文件的起始位置
    4. 最后一个参数是写入多少个字节
    5. 注意,这里如果操作失败了,需要将这个inode的锁给解开了

bug:没有正确判断函数的返回值,说的就是writei,主要是因为writei的参数太多了,当我一个一个填完参数之后,就忘记判断它的返回值是否小于0了

sys_symlink(void) {
    char target[MAXPATH], path[MAXPATH];
    if (argstr(0, target, MAXPATH) < 0) {
        return -1;
    }
    if (argstr(1, path, MAXPATH) < 0) {
        return -1;
    }

    struct inode *ip;
    // 创建软链接文件的inode
    begin_op();
    if ((ip = create(path, T_SYMLINK, 0, 0)) == 0) {
        end_op();
        return -1;
    }
    // 将target写入软链接的数据块中
    if (writei(ip, 0, (uint64)target, 0, strlen(target)) < 0) {
        iunlockput(ip);
        end_op();
        return -1;
    }

    iunlockput(ip);
    end_op();

    return 0;
}

这里还有一些细节,比如begin_opend_op,比如create之后是会自动给inode上锁的

sys_open

这一个函数的修改就是对应我们真正使用软链接的情况

如果我们设置了O_NOFOLLOW,那说明不是访问target,就是想访问这个软链接,那就正常open就行了

而如果我们没设置,说明实际上要访问的是target,在这种情况下,我们只需要在open函数分配fd和file之前,将ip指针切换成target的ip地址即可,因此,找一个适当的位置截胡即可。我这里选择的是在获取已有文件的inode时进行的

  1. 首先,如果进入了else分支,都进入这个while循环,这个while循环走来就读取path的inode,如果不是软链接或者不是需要target的情况,那就直接break,这样的话就和之前的open一样了
  2. 如果需要找target,那就会读出当前软链接文件的target,然后解锁当前inode,进入下一轮while循环,获取target的inode,如果还是软链接,则递归操作,这里是通过迭代代替递归
    1. 这中间关键的函数是readi函数,我看了下实现,具体的操作其实看不太懂。这里有个小问题,那就是最后一个参数应该传入的是我们想读入的path的长度,但是我们这里不知道path多长,只能传入MAXPATH。这样有没有可能多读了呢?我估计是因为这些数据块的没有被write的地方都是0,那么多读一点正好还给path当结尾0了
    if (omode & O_CREATE) {
        ip = create(path, T_FILE, 0, 0);
        if (ip == 0) {
            end_op();
            return -1;
        }
    } else {
        int depth = 0;
        while (1) {
            if ((ip = namei(path)) == 0) {
                end_op();
                return -1;
            }
            ilock(ip);
            if ((ip->type == T_SYMLINK) && (!(omode & O_NOFOLLOW))) {
                if (++depth > 10) {
                    iunlockput(ip);
                    end_op();
                    return -1;
                }
                if (readi(ip, 0, (uint64)path, 0, MAXPATH) < 0) {
                    iunlockput(ip);
                    end_op();
                    return -1;
                }
                iunlockput(ip);
            } else {
                break;
            }
        }

        if (ip->type == T_DIR && omode != O_RDONLY) {
            iunlockput(ip);
            end_op();
            return -1;
        }
    }

这个lab说简单也简单,说难也难,主要是我人菜还不愿意慢慢学

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

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

相关文章

OpenGL手册

基础知识 图元类型 内置变量 GLSL 中文手册 基本类型: 类型说明void空类型,即不返回任何值bool布尔类型 true,falseint带符号的整数 signed integerfloat带符号的浮点数 floating scalarvec2, vec3, vec4n维浮点数向量 n-component floating point vectorbvec2, bvec3, b…

Midjourney学习(三)6个高级应用

使用Remix Mode在原图片的基础上进行二次创作 通过prompt得到大图之后&#xff0c;点击Make Variations按钮&#xff0c;输入Remix Prompt&#xff0c;即可得到意想不到的效果&#xff01; 局部内容重绘 通过局部重绘可以实现对画面内容更加精细化的控制&#xff0c;同样也是需…

【数学建模】清风数模正课7 多元线性回归模型

多元线性回归分析 回归分析就是&#xff0c;通过研究自变量X和因变量Y的相关关系&#xff0c;来解释Y的形成机制&#xff0c;从而达到通过X去预测Y的目的。 所以回归分析需要完成三个使命&#xff0c;首先是识别重要变量&#xff0c;其次是判断正负相关&#xff0c;最后是估计…

PCB电路板电压电流监测软件

PCB电路板电流监测软件详细设计说明书是一个详细描述软件系统设计和实现的文档&#xff0c;它提供了软件系统的架构、功能模块、接口设计、数据存储和处理、界面设计、数据库设计、系统测试、部署和维护计划等方面的详细信息。模拟量采集/老化房采集软件 该文档的目的是为了确保…

企业工程系统管理 工程项目管理系统源码 工程项目各模块及其功能点清单

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

百亿数据查询秒级响应,观测体系之日志中心该如何玩转?

日志是处理生产故障、性能优化、业务分析的重要参考依据&#xff0c;是系统稳定运行不可或缺的一部分。随着业务系统规模急剧膨胀增大&#xff0c;尤其是是微服务架构逐渐普及&#xff0c;一个系统可能涉及多个应用模块与服务实例&#xff0c;传统模式下运维人员去定位问题显得…

爬虫逆向实战(二十六)--某某学堂登录

一、数据接口分析 主页地址&#xff1a;某某学堂 1、抓包 通过抓包可以发现数据接口是Account/LoginPost 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现pass是加密参数 请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 无co…

ios开发 swift5 苹果系统自带的图标 SF Symbols

文章目录 1.官网app的下载和使用2.使用代码 1.官网app的下载和使用 苹果官网网址&#xff1a;SF Symbols 通过上面的网址可以下载dmg, 安装到自己的mac上 貌似下面这样不能展示出动画&#xff0c;还是要使用动画的代码 .bounce.up.byLayer2.使用代码 UIKit UIImage(system…

双指针算法,基础算法实践,基本的算法的思想,双指针算法的实现

一&#xff0c;定义 双指针算法是一种常用于解决数组和链表问题的算法技巧。它的核心思想是使用两个指针在数据结构中按照一定的规则移动&#xff0c;从而达到快速搜索或处理数据的目的。这个技巧通常用于优化算法&#xff0c;降低时间复杂度&#xff0c;提高程序的执行效率。…

【附安装包】CAD2024(建筑版)安装教程

软件下载 软件&#xff1a;CAD建筑版本&#xff1a;2023语言&#xff1a;简体中文大小&#xff1a;4.52G安装环境&#xff1a;Win11/Win10硬件要求&#xff1a;CPU2.5GHz 内存8G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.baidu.com/s/1cHe…

android frida 逆向 自吐加密算法

前言&#xff1a; ♛ frida hook android Android 逆向神器 前几天在学习 Android 逆向的时候发现了一个神器&#xff1a;通过 frida hook 我们可以 “劫持” 一些函数 为我们所用&#xff0c; 今天就和大家上手一个 加密函数的劫持 让打印出&#xff1a; 加密秘钥 …

Ansys Zemax | 手机镜头设计 - 第 2 部分:使用 OpticsBuilder 实现光机械封装

本文是3篇系列文章的一部分&#xff0c;该系列文章将讨论智能手机镜头模块设计的挑战&#xff0c;从概念、设计到制造和结构变形的分析。本文是三部分系列的第二部分。概括介绍了如何在 CAD 中编辑光学系统的光学元件以及如何在添加机械元件后使用 Zemax OpticsBuilder 分析系统…

MySQL 存储引擎详解

文章目录 0.前言1.基础介绍2.1. InnoDB存储引擎底层原理InnoDB记录存储结构和索引页结构InnoDB记录存储结构&#xff1a;InnoDB索引页结构&#xff1a; 3. MVCC 详解3.1. 版本号分配&#xff1a;3.2. 数据读取&#xff1a;3.3. 数据写入&#xff1a;3.4. 事务隔离级别&#xff…

剑指offer(C++)-JZ29:顺时针打印矩阵(算法-模拟)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 输入一个矩阵&#xff0c;按照从外向里以顺时针的顺序依次打印出每一个数字&#xff0c;例如&#xff0c;…

JDK配置环境变量(超详细)

1.打开高级系统设置 电脑右键--属性&#xff0c;或者搜索“高级系统设置” 找到高级系统设置 2.环境变量 高级--环境变量 3.配置JAVA_HOME JAVA_HOME 4.添加到Path中 %JAVA_HOME%\bin 5.测试是否配置成功 快捷键winR,输入cmd&#xff0c;回车 打开黑屏命令窗口。 如果配…

windows11显示未激活怎么办

遇到的问题 本人遇到的问题&#xff0c;win11家庭中文版 reset后&#xff0c;系统正常使用&#xff0c;但是系统状态是未激活&#xff0c;未激活就意味着某些功能不可用&#xff0c;比如我就是想改一下系统主题&#xff0c;就是不能改&#xff0c;因为系统没有激活&#xff0c…

开学季触控笔买哪种好?ipad可以用的性价比手写笔

虽然苹果的平板电脑价格不菲&#xff0c;但如果你有足够的资金&#xff0c;还是可以考虑购买一台。而且&#xff0c;这款iPad配上了一支电容笔&#xff0c;不仅可以用来绘画&#xff0c;还可以用来做笔记。苹果的原装电容笔&#xff0c;虽然功能很强&#xff0c;但价格很贵&…

当摩托不再“摩登”,谁又在风口狂飙?

【潮汐商业评论/文】 “你看&#xff0c;这女生骑摩托车真是泰酷辣。” Jessica举着手机里一个女生骑摩托的视频对闺蜜说。 对于很多人来说&#xff0c;摩托车都是一个极具独特魅力的出行工具。硬朗的机车、酷帅的骑行服&#xff0c;配上发动机的轰鸣声&#xff0c;似乎看到…

上海港股通开通条件是什么?港股通交易佣金最低多少?

上海港股通权限开通条件有&#xff1a; 1、申请权限开通前20个交易日证券账户日均资产不低于50万元; 2、进行港股知识测试&#xff0c;且测试分数不低于80分; 3、风险承受能力等级需要匹配&#xff0c;无投资经验期限的门槛 港股通的股票范围是香港联合交易所恒生综合大型股…

[ES]二基础 |

一、索引库操作 1、mapping属性 mapping是对索引库中文档的约束&#xff0c;常见的mapping属性包括&#xff1a; 1)type&#xff1a;字段数据类型&#xff0c;常见的简单类型有&#xff1a; ①字符串&#xff1a;text(可分词的文本)、keyword&#xff08;精确值&#xff0c…