当前位置: 首页 > article >正文

【北邮 操作系统】第十二章 文件系统实现

一、文件的物理结构

1.1 文件块、磁盘块

  1. 类似于内存分页,磁盘中的存储单元也会被分为一个个“块/磁盘块/物理块”。很多操作系统中,磁盘块的大小与内存块、页面的大小相同

  2. 内存与磁盘之间的数据交换(即读/写操作、磁盘I/0)都是以“块”为单位进行的。即每次读入一块,或每次写出一块

  3. 在内存管理中,进程的逻辑地址空间被分为一个一个页面,同样的,在外存管理中,为了方便对文件数据的管理,文件的逻辑地址空间也被分为了一个一个的文件块,于是文件的逻辑地址也可以表示为(逻辑块号,块内地址)的形式。

  4. 用户通过逻辑地址来操作自己的文件,操作系统要负责实现从逻辑地址到物理地址的映射

1.2 连续分配

连续分配方式要求每个文件在磁盘上占有一组连续的块

  1. 用户通过逻辑地址来操作自己的文件,(逻辑块号,块内地址)→(物理块号,块内地址)。只需转换块号就行,块内地址保持不变。

  2. 文件目录中记录存放的起始块号和长度(总共占用几个块)

  3. 用户给出要访问的逻辑块号,操作系统找到该文件对应的目录项(FCB),物理块号=起始块号+逻辑块号,当然,还需要检查用户提供的逻辑块号是否合法(逻辑块号之长度就不合法)

  4. 可以直接算出逻辑块号对应的物理块号,因此连续分配支持顺序访问直接访问(即随机访问)

  5. 优点:连续分配的文件在顺序读/写时速度最快,支持顺序访问直接访问(即随机访问)

  6. 缺点:物理上采用连续分配的文件不方便拓展;物理上采用连续分配,存储空间利用率低,会产生难以利用的磁盘碎片。可以用紧凑来处理碎片,但是需要耗费很大的时间代价。

1.3 链接分配

链接分配采取离散分配的方式,可以为文件分配离散的磁盘块。分为隐式链接显式链接两种。

1.3.1 隐式链接

  1. 链接分配采取离散分配的方式,可以为文件分配离散的磁盘块。分为隐式链接和显式链接两种。

  2. 如何实现文件的逻辑地址到物理块号的转变:

    1) 用户给出要访问的逻辑块号i,操作系统找到该文件对应的目录项(FCB)

    2) 从目录项中找到起始块号(即0号块),将0号逻辑块读入内存,由此知道1号逻辑块存放的物理块号,于是读入1号逻辑块,再找到2号逻辑块的存放位置..….以此类推。

    3) 因此,读入i号逻辑块,总共需要i+1次磁盘I/0

  3. 缺点:采用链式分配(隐式链接)方式的文件,只支持顺序访问,不支持随机访问,查找效率低。另外,指向下一个盘块的指针也需要耗费少量的存储空间。

  4. 优点:采用隐式链接的链接分配方式很方便文件拓展。另外,所有的空闲磁盘块都可以被利用,不会有碎片问题,外存利用率高

1.3.2 显示链接

  1. FAT:把用于链接文件各物理块的指针显式地存放在一张表中。即文件分配表(FAT, File Allocation Table )

  2. 假设某个新创建的文件“aaa”依次存放在磁盘块2->5->0->1;假设某个新创建的文件“bbb”依次存放在磁盘块4->23->3

  3. 注意:一个磁盘仅设置一张FAT。开机时,将FAT读入内存,并常驻内存。FAT的各个表项在物理上连续存储,且每一个表项长度相同,因此“物理块号”字段可以是隐含的。

  4. 如何实现文件的逻辑地址到物理块号的转变:

    1) 用户给出要访问的逻辑块号i,操作系统找到该文件对应的目录项(FCB).

    2) 从目录项中找到起始块号,若i>0,则查询内存中的文件分配表FAT,往后找到i号逻辑块对应的物理块号

    3) 逻辑块号转换成物理块号的过程不需要读磁盘操作

  5. 优点:很方便文件拓展,不会有碎片问题,外存利用率高,并且支持随机访问。相比于隐式链接来说,地址转换时不需要访问磁盘,因此文件的访问效率更高

  6. 缺点:文件分配表的需要占用一定的存储空间。

1.4 索引分配

索引分配允许文件离散地分配在各个磁盘块中,系统会为每个文件建立一张索引表,索引表中记录了文件的各个逻辑块对应的物理块(索引表的功能类似于内存管理中的页表--建立逻辑页面到物理页之间的映射关系)。索引表存放的磁盘块称为索引块。文件数据存放的磁盘块称为数据块

  1. 假设某个新创建的文件“aaa”的数据依次存放在磁盘块2->5->13->9。7号磁盘块作为“aaa”的索引块,索引块中保存了索引表的内容。

  2. 注意:在显式链接的链式分配方式中,文件分配表FAT是一个磁盘对应一张。而索引分配方式中,索引表是一个文件对应一张。

  3. 可以用固定的长度表示物理块号(如:假设磁盘总容量为1TB=2^40B,磁盘块大小为1KB,则共有 2^30个磁盘块,则可用4B表示磁盘块号),因此,索引表中的“逻辑块号”可以是隐含的。

  4. 如何实现文件的逻辑地址到物理块号的转变:

    1) 用户给出要访问的逻辑块号i,操作系统找到该文件对应的目录项(FCB)

    2) 从目录项中可知索引表存放位置,将索引表从外存读入内存,并查找索引表即可知i号逻辑块在外存中的存放位置。

  5. 可见,索引分配方式可以支持随机访问文件拓展也很容易实现(只需要给文件分配一个空闲块,并增加一个索引表项即可),但是索引表需要占用一定的存储空间

若每个磁盘块1KB,一个索引表项4B,则一个磁盘块只能存放 256 个索引项,如果一个文件的大小超过了256块,那么一个磁盘块是装不下文件的整张索引表的,如何解决这个问题?

解:①链接方案②多层索引③混合索引

【1.链接方案】

如果索引表太大,一个索引块装不下,那么可以将多个索引块链接起来存放。

假设磁盘块大小为1KB,一个索引表项占4B,则一个磁盘块只能存放256个索引项。

若一个文件大小为 256*256KB =65,536 KB=64MB

该文件共有256x256个块,也就对应256x256个索引项,也就需要256个索引块来存储,这些索引块用链接方案连起来。

若想要访问文件的最后一个逻辑块就必须找到最后一个索引块(第256个索引块),而各个索引块之间是用指针链接起来的,因此必须先顺序地读入前255个索引块。

这显然是很低效的。如何解决呢? :scream:

【2.多层索引】

建立多层索引(原理类似于多级页表)。使第一层索引块指向第二层的索引块。还可根据文件大小的要求再建立第三层、第四层索引块。

假设磁盘块大小为1KB,一个索引表项占4B,则一个磁盘块只能存放256个索引项。

若某文件采用两层索引,则该文件的最大长度可以到2562561KB=65,536KB=64MB

可根据逻辑块号算出应该查找索引表中的哪个表项。

如:要访问1026号逻辑块,则1026/256=4,1026%256=2

因此可以先将一级索引表调入内存,查询4号表项,将其对应的二级索引表调入内存,再查询二级索引表的2号表项即可知道 1026号逻辑块存放的磁盘块号了。

访问目标数据块,需要3次磁盘I/O,

若采用三层索引,则文件的最大长度为256x256x256x1KB=16GB

类似的,访问目标数据块,需要4次磁盘I/0

采用K层索引结构,且顶级索引表未调入内存,则访问一个数据块只需要K+1次读磁盘操作

【3.混合索引】

多种索引分配方式的结合。例如,一个文件的顶级索引表中,既包含直接地址索引(直接指向数据块),又包含一级间接索引(指向单层索引表)、还包含两级间接索引(指向两层索引表)。

优点:对于小文件来说,访问一个数据块所需的读磁盘次数更少。

二、文件存储空间管理

2.1 存储空间的划分与初始化

安装 Windows操作系统的时候,一个必经步骤是 -- 为磁盘分区(C:盘、D: 盘、E:盘等)

  1. 存储空间的划分: 将物理磁盘划分为一个个文件卷(逻辑卷、逻辑盘)

  2. 存储空间的初始化: 将各个文件卷划分为目录区、文件区

  3. 目录区主要存放文件目录信息(FCB)、用于磁盘存储空间管理的信息

  4. 文件区用于存放文件数据

  5. 有的系统支持超大型文件,可支持由多个物理磁盘组成一个文件卷

2.2 存储空间管理

2.2.1 空闲表法

  1. 如何分配磁盘块: 与内存管理中的动态分区分配很类似,为一个文件分配连续的存储空间。同样可采用首次适应、最佳适应、最坏适应等算法来决定要为文件分配哪个区间。

  2. 如何回收磁盘块:与内存管理中的动态分区分配很类似,当回收某个存储区时需要有四种情况 -- ①回收区的前后都没有相邻空闲区; ②回收区的前后都是空闲区; ③回收区前面是空闲区; ④回收区后面是空闲区。总之,回收时需要注意表项的合并问题

2.2.2 空闲链表法

  1. 空闲盘块链:

    操作系统保存着链头、链尾指针

    如何分配: 若某文件申请K个盘块,则从链头开始依次摘下K个盘块分配,并修改空闲链的链头指针。

    如何回收: 回收的盘块依次挂到链尾,并修改空闲链的链尾指针。

    适用于离散分配的物理结构。为文件分配多个盘块时可能要重复多次操作

  2. 空闲盘区链:

    操作系统保存着链头、链尾指针。

    如何分配: 若某文件申请K个盘块,则可以采用首次适应、最佳适应等算法,从链头开始检索,按照算法规则找到一个大小符合要求的空闲盘区分配给文件。若没有合适的连续空闲块,也可以将不同盘区的盘块同时分配给一个文件,注意分配后可能要修改相应的链指针、盘区大小等数据。

    如何回收: 若回收区和某个空闲盘区相邻,则需要将回收区合并到空闲盘区中。若回收区没有和任何空闲区相邻,将回收区作为单独的一个空闲盘区挂到链尾。

    离散分配、连续分配都适用。为一个文件分配多个盘块时效率更高

2.2.3 位示图法

  1. 位示图: 每个二进制位对应一个盘块。在本例中,“0”代表盘块空闲“1”代表盘块已分配。位示图一般用连续的“字”来表示,如本例中个字的字长是16位,字中的每一位对应一个盘块。因此可以用(字号,位号)对应一个盘块号。当然有的题目中也描述为(行号,列号)

  2. 重要重要重要: 要能自己推出盘块号与(字号,位号)相互转换的公式。

    (字号,位号)=(i,j)的二进制位对应的盘块号b=ni+j;

    b号盘块对应的字号i=b/n,位号j=b%n

  3. 如何分配:

    若文件需要K个块,

    ①顺序扫描位示图,找到K个相邻或不相邻的“0”;

    ②根据字号、位号算出对应的盘块号,将相应盘块分配给文件;

    ③将相应位设置为“1”

  4. 如何回收:

    ①根据回收的盘块号计算出对应的字号、位号;

    ②将相应二进制位设为“0”

2.2.4 成组链表法(难理解)

空闲表法、空闲链表法不适用于大型文件系统,因为空闲表或空闲链表可能过大。UNIX系统中采用了成组链接法对磁盘空闲块进行管理。

  1. 文件卷的目录区中专门用一个磁盘块作为“超级块”,当系统启动时需要将超级块读入内存。并且要保证内存与外存中的“超级块”数据一致。

  2. 如何分配:

    Eg:需要1个空闲块

    ①检查第一个分组的块数是否足够。1<100,因此是足够的。

    ②分配第一个分组中的1个空闲块,并修改相应 数据

    Eg:需要100个空闲块

    ①检查第一个分组的块数是否足够。100=100,是足够的。

    ②分配第一个分组中的100个空闲块。但是由于300号块内存放了再下一组的信息,因此300号块的数据需要复制到超级块中。

  3. 如何回收:

    Eg:假设每个分组最多为100个空闲块,此时第一个分组已有99个块,还要再回收一块

    将回收的空闲块查到第一个分组中

    Eg:假设每个分组最多为100个空闲块,此时第一个分组已有100个块,还要再回收一块。

    新回收的空闲块作为新的分组,将超级块中的内容复制到新回收的块中,超级块中的内容做一下修改,指向新回收的分组,超级块中 只有一个空闲块

相关文章:

【北邮 操作系统】第十二章 文件系统实现

一、文件的物理结构 1.1 文件块、磁盘块 类似于内存分页&#xff0c;磁盘中的存储单元也会被分为一个个“块/磁盘块/物理块”。很多操作系统中&#xff0c;磁盘块的大小与内存块、页面的大小相同 内存与磁盘之间的数据交换(即读/写操作、磁盘I/0)都是以“块”为单位进行的。即…...

Docker 插件生态:从网络插件到存储插件的扩展能力解析

Docker 容器技术以其轻量、快速、可移植的特性,迅速成为构建和部署现代应用的核心工具。然而,尽管 Docker Engine 自身功能强大,但在面对多样化的生产环境和复杂业务需求时,仅靠核心功能往往无法满足所有场景。 例如,跨主机的容器网络通信、异构存储系统的持久化数据管理…...

WordPress搜索引擎优化的最佳重定向插件:进阶指南

在管理网站时&#xff0c;我们经常需要调整网页地址或修复错误链接。这时&#xff0c;通过重定向不仅能有效解决这些问题&#xff0c;还能显著提升网站在搜索引擎中的排名。对于熟悉基础重定向插件的用户来说&#xff0c;一些功能更强大的工具可以帮助你更全面地管理网站&#…...

org.junit.runners.model.InvalidTestClassError:此类问题的解决

不知道大家是否遇见过以上这种情况&#xff0c;我也是今天被这个错误搞得很烦&#xff0c;后来通过网上查找资料终于找到了问题所在————就是简单的Test注解的错误使用 Test注解的注意情况 &#xff1a;1 权限必须是public 2 不能有参数 3 返回值类型是void 4 本类的其他的…...

用户管理页面(解决toggleRowSelection在dialog用不了的隐患,包含el-table的plus版本的组件)

新增/编辑/删除/分配角色&#xff0c;图片上传在此文章分类下另一个文章 1.重点分配角色&#xff1a; <template><!-- 客户资料 --><div class"pageBox"><elPlusTable :tableData"tableData" :tablePage"tablePage" onSi…...

打卡第35天:GPU训练以及类的Call方法

知识点回归&#xff1a; 1.CPU性能的查看&#xff1a;看架构代际、核心数、线程数 2.GPU性能的查看&#xff1a;看显存、看级别、看架构代际 3.GPU训练的方法&#xff1a;数据和模型移动到GPU device上 4.类的call方法&#xff1a;为什么定义前向传播时可以直接写作self.fc1(x)…...

Linux-GCC、makefile、GDB

GCC gcc -E test.c -o test.i预处理(-o指定文件名) gcc -S test.i -o test.s编译gcc -c test.s -o test.o汇编gcc test.o -o test链接(生成一个可执行程序的软连接) gcc test.c -o test一条指令可以完成以上所有内容 gcc *.c -I(大写的i) include由于在main.c中找不到当前文件…...

[MySQL初阶]MySQL(7) 表的内外连接

标题&#xff1a;[MySQL初阶]MySQL(7)表的内外连接 水墨不写bug 文章目录 一. 内连接 (INNER JOIN)二. 外连接 (OUTER JOIN)关键区别总结 三、 如何选择 在 MySQL 中&#xff0c;连接&#xff08;JOIN&#xff09;用于根据两个或多个表之间的相关列组合行。内连接&#xff08;I…...

Spring Boot中Excel处理完全指南:从基础到高级实践

Excel处理基础知识 1.1 为什么需要在应用中处理Excel文件&#xff1f; 在企业应用开发中&#xff0c;Excel文件处理是一个非常常见的需求&#xff0c;主要用于以下场景&#xff1a; 数据导入&#xff1a;允许用户通过Excel上传批量数据到系统 数据导出&#xff1a;将系统数据…...

Windows下NVM的安装与使用

本文将介绍windows下nvm相关知识。 在不同的项目中可能会使用不同版本的Node.js&#xff0c;例如A项目中需要node>18&#xff1b;B项目中需要node>20。这时候就需要使用NVM切换不同的node版本。进而可以在同一台设备上使用多个node版本。 一、NVM是什么&#xff1f; n…...

Ubuntu挂起和休眠

Ubuntu挂起和休眠 1. 挂起&#xff08;Suspend&#xff09;2. 休眠&#xff08;Hibernate&#xff09;3. 混合挂起&#xff08;Hybrid-Sleep&#xff09;注意事项图形界面操作 在 Ubuntu 系统中&#xff0c;挂起&#xff08;Suspend&#xff09;和休眠&#xff08;Hibernate&am…...

【R语言编程绘图-mlbench】

mlbench库简介 mlbench是一个用于机器学习的R语言扩展包&#xff0c;主要用于提供经典的基准数据集和工具&#xff0c;常用于算法测试、教学演示或研究场景。该库包含多个知名数据集&#xff0c;涵盖分类、回归、聚类等任务。 包含的主要数据集 BostonHousing 波士顿房价数据…...

云服务器部署Gin+gorm 项目 demo

更多个人笔记见&#xff1a; &#xff08;注意点击“继续”&#xff0c;而不是“发现新项目”&#xff09; github个人笔记仓库 https://github.com/ZHLOVEYY/IT_note gitee 个人笔记仓库 https://gitee.com/harryhack/it_note 个人学习&#xff0c;学习过程中还会不断补充&…...

MySQL数据一致性守护者:pt-table-checksum原理与实战全解析

MySQL数据一致性守护者:pt-table-checksum原理与实战全解析 在MySQL主从复制环境中,数据一致性是DBA和运维人员最关心的问题之一。主从数据不一致可能导致业务逻辑错误、报表数据失真甚至系统故障。Percona Toolkit中的pt-table-checksum工具正是为解决这一痛点而生,它能够…...

检索器组件深入学习与使用技巧 BaseRetriever 检索器基类

1. BaseRetriever 检索器基类 在 LangChain 中&#xff0c;传递一段 query 并返回与这段文本相关联文档的组件被称为 检索器&#xff0c;并且 LangChain 为所有检索器设计了一个基类——BaseRetriever&#xff0c;该类继承了 RunnableSerializable&#xff0c;所以该类是一个 …...

Unity——QFramework工具 AciontKit时序动作执行系统

AciontKit 是一个时序动作执行系统。 游戏中&#xff0c;动画的播放、延时、资源的异步加载、网络请求等&#xff0c;这些全部都是时序任务&#xff0c;而 ActionKit&#xff0c;可以把这些任务全部整合在一起&#xff0c;使用统一的 API&#xff0c;来对他们的执行进行计划。…...

【Doris基础】Doris中的Replica详解:Replica原理、架构

目录 1 Replica基础概念 1.1 什么是Replica 1.2 Doris中的副本类型 2 Doris副本架构设计 2.1 副本分布机制 2.2 副本一致性模型 3 副本生命周期管理 3.1 副本创建流程 3.2 副本恢复机制 4 副本读写流程详解 4.1 写入流程与副本同步 4.2 查询流程与副本选择 5 副本…...

【中国·广州】第三届信号处理与智能计算国际学术会议 (SPIC2025) 即将开启

第三届信号处理与智能计算国际学术会议 (SPIC2025) 即将开启 在信息技术飞速发展的当下&#xff0c;信号处理与智能计算作为前沿科技领域&#xff0c;正深刻改变着我们的生活与产业格局。为汇聚全球顶尖智慧&#xff0c;推动该领域进一步突破&#xff0c;第三届信号处理与智能…...

Android12 Launcher3显示所有应用列表

Android12 Launcher3显示所有应用列表 1.前言&#xff1a; 最近在Android12Rom定制时需要显示所有桌面应用的图标&#xff0c;并且不能去掉抽屉&#xff0c;在手机上面抽屉和所有应该列表是两种不同模式&#xff0c;用户基可以自行选择&#xff0c;但是在自定义的launcher中这…...

24.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--认证微服务

SP.IdentityService 项目为微服务架构中的核心认证中心&#xff0c;采用 OpenIddict 框架实现 OAuth2.0 和 OpenID Connect 协议&#xff0c;提供完整的身份认证和授权解决方案。项目集成了 ASP.NET Core Identity 框架&#xff0c;实现了用户管理、角色权限控制等基础功能&…...

基于React Native开发鸿蒙新闻类应用的实战开发笔记

以下为基于React Native开发鸿蒙新闻资讯类应用的实战开发笔记&#xff0c;结合架构特性与踩坑经验&#xff0c;重点记录关键实现方案和技术决策&#xff1a; 一、环境搭建与工程初始化&#xff08;关键步骤复盘&#xff09; ​​Node.js版本锁定​​ 必须使用​​Node 18​​&…...

[Java 基础]运算符,将盒子套起来

在 Java 中&#xff0c;运算符&#xff08;Operator&#xff09;用于执行特定的操作&#xff0c;例如数学计算、赋值、比较等。运算符是 Java 语言的重要组成部分&#xff0c;能够帮助我们高效地操作数据。 1. 算术运算符 运算符说明示例结果加法5 38-减法5 - 32*乘法5 * 31…...

智能快递地址解析接口如何用PHP调用?

一、什么是智能快递地址解析接口 随着互联网技术的普及和电子商务的迅猛发展&#xff0c;网购已成为现代人日常生活的重要组成部分。然而&#xff0c;在这个便捷的背后&#xff0c;一个看似不起眼却影响深远的问题正悄然浮现——用户填写的快递地址格式混乱、信息不全甚至错漏…...

华为OD机试真题——模拟消息队列(2025B卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 B卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《模拟消息队列》: 目录 题…...

c# 显示正在运行的线程数

在 C# 中&#xff0c;若想获取当前进程正在运行的线程数&#xff0c;可以使用 System.Diagnostics 命名空间中的 Process 类来实现。该方法适用于 Windows 平台&#xff0c;并能够获取当前进程的线程信息&#xff0c;包括线程总数和运行中的线程数量。 ✅ 方法一&#xff1a;使…...

MySQL 日志数据同步的详细教程

以下是 MySQL 日志数据同步的详细教程&#xff0c;主要介绍基于二进制日志&#xff08;binlog&#xff09;的主从复制和基于 GTID 的高级同步方案&#xff1a; 一、MySQL 二进制日志&#xff08;binlog&#xff09;同步基础 1. 二进制日志原理 binlog 是 MySQL 的事务性日志&am…...

2025 Java面试大全技术文章(面试题1)

数据类型与包装类 问题&#xff1a;Java中基本数据类型与包装类的区别是什么&#xff1f;自动装箱与拆箱的底层原理&#xff1f; 答案&#xff1a; 基本数据类型&#xff08;如int、double&#xff09;直接存储值&#xff0c;包装类&#xff08;如Integer、Double&#xff09;…...

docker 中 什么是「卷」?(Volume)

&#x1f5c3;️ 什么是「卷」&#xff1f;&#xff08;Volume&#xff09; 「卷」就是 Docker 里用来“保存数据”的一块空间&#xff0c;就像是一个外接硬盘&#xff0c;或者一个 USB 闪存。 容器本身是临时的&#xff0c;你一删它&#xff0c;它的数据也跟着没了。但卷是用…...

三维可视化和实时数据处理对前端性能要求以及优化渲染效率

在三维可视化&#xff08;如 Three.js 场景&#xff09;和实时数据处理&#xff08;如每秒数百条设备状态更新&#xff09;场景中&#xff0c;前端性能优化是确保用户体验的核心挑战。以下结合技术原理与行业实践&#xff0c;详细说明Web Workers和虚拟 DOM的优化机制&#xff…...

基于VU37P的高性能采集板卡

基于VU37P的高性能采集板卡是一款最大可提供20路ADC接收通道的高性能采集板卡。每路A/D通道支持1GS/s的采样率&#xff0c;分辨率为14bit&#xff0c;模拟输入带宽可达500MHz&#xff0c;交流耦合&#xff0c;输入阻抗50欧姆。 产品简介 可提供20路ADC接收通道的高性能采集板…...