理解文件系统

个人主页:Lei宝啊 

愿所有美好如期而遇


磁盘

磁盘的机械构成

磁盘的物理存储

每个磁盘的盘面,磁头,扇面,扇区都有唯一的编号,同时,一个扇区的大小是512字节(扇区的大小也有4KB的,或者其他大小,我们这里介绍的是512字节的),磁盘IO的基本单位是扇区。

每个扇区都是由一个个我们肉眼不可见的小磁块构成,我们平时理解的比特位的1或0,在这个小磁块上的表现就是磁性,南极或者北极,由此表示。如果我们想寻找磁盘上的某一个扇区,首先应该确定是哪个磁头,也就是在哪个盘片上,盘片正反面都是可以存储数据的;接着就是确定在哪一个磁道(柱面)上;最后确定在哪个扇区。

磁盘的逻辑存储

磁带中一圈一圈的存储着数据,如果我们把它扯出来,可以拉成一条直线。

我们可以想象一下,将磁盘上一圈圈的磁道也拉成一条直线,那么我们就可以抽象出,在逻辑上,它存储数据就是线性的。

我们可以根据这个线性地址,通过一系列除法和求余运算计算出CHS地址,线性地址到CHS是由磁盘自己计算转化的。CHS定位法,cylinder磁道,head磁头/盘面,sector扇区)

所以我们其实也可以理解,文件不就是由多个扇区承载的数据吗?我们可以通过线性地址转化成CHS地址,找到一个扇区,那么我们当然也可以找到多个扇区,也就可以找到文件。

操作系统认为,内存和磁盘一次IO 512个字节太小了,所以他规定出一次IO的基本单位为4KB。

操作系统为了更好的管理磁盘,对磁盘进行了分区,也就是说,我管理好一个分区这100GB的空间,那么其他的分区我是不是也可以管理好,那么同理,为了更好的管理这100GB空间,对他进行分组,假如说一个组有10GB,那么操作系统管理好这10GB,是不是其他组也可以管理好?

这里我们先要明白:

Linux磁盘文件特性:文件 = 内容 + 属性,而我们这里要说的是,内容和属性是分开存储的,内容的大小是可变的,属性的大小是固定的,同时文件名不属于属性,系统中标识一个文件用的不是文件名,而是inode。

inode Table && inode Bitmap

什么是inode?struct inode {文件属性,inode编号};这个结构体的大小固定是128个字节,一个数据块可以存储32个inode,inode Table里是操作系统分配的数据块,连续存储着inode,同时我们要知道整个分区内inode的数量是固定的,由操作系统分配。

那么,我们怎么知道在哪个位置存储了inode,同时哪个位置没有存储inode?这就需要位图,我们的inode Bitmap的bit位就表示第几个inode,这个inode是否空闲可用,我们通过遍历位图,可以找到最小的空闲的inode去存储我们新建的文件的属性,然后将这个位置bit位从0改为1,同时记录下这个bit位是第几个bit位。

Data Blocks && Block Bitmap

Data Blocks里就是操作系统分配的只存储文件内容的数据块,每个数据块都有自己的LBA地址,大小为4KB,inode里有一个属性是int block[15],存放着文件内容的数据块的LBA地址,我们可以根据他来将文件的内容和属性对应起来,但是block看起来只能存储60KB的内容?文件不是可以很大吗?这个数组有15个下标,从0~14,其中0~11存储的LBA地址对应的数据块里,存放的就是文件内容,而下标为12,13的LBA地址对应的数据块里,存放的不是文件内容,他存放的仍然是LBA地址,而这个地址再去索引找到的数据块里,存放着的才是文件内容,我们也将这个过程叫做二级索引,但是即使这样,文件的内容依然不是很大,也就扩大了1024倍,也就是60KB*1024,那么最后一个下标14,他是三级索引,这样就再次扩大了文件大小,我们可以依据这样去存放更大的文件。Block Bitmap的bit位就表示哪个数据块被占用,哪个数据块没有被占用。

Group Descriptor Table && super Block

Group Descriptor Table,块组描述符,记录着自己这个分组的各种信息,比如分组的起始inode编号,这个分组有多少个inode,inode Bitmap的使用情况,下一个inode将要分配到哪里等等,我们也将其叫做GDT,GDT是每个分组都有的,如果一个组的GDT损坏了,那么这个组的所有信息都无法找到,文件全部丢失。

super Block,超级块,存放文件系统本身的结构信息。记录着整个分区的各种信息,比如block和inode的总量,未使用的block和inode数量,最近一次写入数据的时间等等,这个一但损坏了,整个分区就挂了,整个文件系统结构就被破坏了。那么这个块是所有分组都有的吗?不是,系统会有选择性地其中几个分组,这样如果一个分组中的超级块信息被破坏,还可以根据其他分组中的超级块进行恢复,所以,我们也应该知道,这几个分组中超级块的数据是同步的。

这里我们还要介绍一个东西:

我们选中一个盘右击鼠标,可以看到一个选项叫做格式化,这是做什么的呢?

我们上面介绍的文件管理方式,是分区一创建好就有的吗?当然不是,而是格式化写入了一个新的文件系统,我们上面介绍的文件系统是ext*(2),不同的分区可以有不同的文件系统,而super block就是存储着文件系统的信息,多个分区也就有多个super block,操作系统将他们组织起来,那么,对于分区的管理也就变成了对super block的增删查改。

几个点

到这里,我们需要提出来几个点。

第一点

首先,inode里存着inode编号,什么是inode编号?在整个分区中,他唯一标识着一个文件,有了inode编号,我们就可以找到这个文件,我们如何通过他来找到这个文件?

从Block group0开始,第一个分组中的inode Block,起始编号就是1,同时这个分组通过GDT记录着这个组中有多少inode,假如说有10000个inode,那么下一个组,他的inode起始编号就是10001,同时他的GDT中也记录着有多少个inode。

我们新建一个文件时,先在inode Bitmap中找到最小的空闲的inode,然后记下他的偏移量,直接去inode Block中索引到位置存储文件属性,然后根据分组的起始inode编号,加上在位图中的偏移量,就是这个文件的inode编号,然后将这个编号返回。举个例子,我们在inode Bitmap中假设找到第二十个位置是空闲的,偏移量就是20,然后当前分组的起始inode编号是1,那么这个新建的文件的inode编号就是20 + 1 = 21。

那么我们查找一个文件时,他的inode编号是3,那么我们通过第一个分组的起始编号和第二个分组的起始编号就可以确定这个文件是在哪个分组内的,找到分组后,通过他的编号在inode Bitmap中找到 inode的偏移量,然后在inode Block中找到inode,inode中找到文件的属性以及block[15],通过他再去Data Blocks中找到这个文件对应的内容。

第二点

我们还需要知道的是,inode Block和Data Blocks中数据块的数量是操作系统分配的,会出现两种情况,一种是inode Block空间用完,Data Blocks还有剩余,另一种就是反过来。

第三点

再一个,我们如何通过inode寻找文件?我们诚然可以将文件的属性和内容对应起来,但是真说到要找文件,该如何寻找?

通过inode编号去寻找,可是去哪里找inode编号?直接看到吗?我们使用者关心过吗,没有,使用者关心的是文件名,而系统关心的是inode。

在linux中,我们新建一个文件,系统要做什么?

linux中,一个文件对应着唯一的一个inode,每一个inode都有自己唯一的inode编号(inode的设置是以分区为单位的,不可以跨区),当我们新建一个文件时,系统会存储好他的内容和属性,同时为他分配一个inode,而文件名是不属于文件属性的。

但是我们知道,任何一个普通文件,都一定在目录中,同时我们也知道,目录也是文件,也是inode+目录的内容,那么目录的内容保存什么呢?保存的是文件名和inode编号的映射关系!

那么我们之前给目录加的rwx权限,对文件的增删查改怎么理解呢?

首先是写权限,我们创建文件时,由用户输入的文件名,以及系统要为其分配的inode和返回的inode编号,要建立映射关系,然后存储在目录的内容当中,但是如果不给写权限,那么就写不进去,自然这个文件也就无法创建。

读权限,我们读文件的属性和内容,首先需要文件名去目录的内容中进行匹配找到自己的inode编号,然后确定分组,减去分组的起始inode编号,然后在inode Block中找到文件属性,再找到文件内容,但是如果没有读权限,那么也就无法知道inode编号,自然就读不出来文件的属性和内容了。

我们再谈到文件的删除,我们平时有没有注意到一个现象,就是拷贝文件花费的时间比删除花费的时间要长,比如所几个G的文件,我们删除就很快,而拷贝就要花些时间,这是为什么?

因为我们删除文件时,系统只是清空了文件对应的inode Bitmap,这样做,表明这个文件无效了,同时文件对应的Block Bitmap也做了清空。

所以我们删除文件时,如果没有写权限,也就无法删除目录内容中文件名和inode编号的映射关系,也就无法删除这个文件。

第四点

目录是不是文件呢?是的,那么目录的inode编号我去哪里找,是不是又要去找这个目录的父目录?父目录是不是文件?父目录的inode编号去哪里找?这样一直往上找,我们最终也就找到了根目录,而根目录的inode编号是确定的。

在我们打开一个目录时,操作系统会缓存下这个目录的路径,每打开一个目录,就缓存这个目录的路径,文件也是同理,当我们切换目录以及寻找文件时,就会快很多。

当我们打开一个目录,缓存下这个目录的路径,同时我们想要查看这个目录下的文件的属性和内容,那么就会根据缓存下的路径递归般的找到根目录,从根目录开始解析文件,找到一个个的inode,从而找到他们的属性和内容。

由此,我们可以得到一个结论:查找一个文件,在linux内核中,都要递归般的获得根目录,由根目录进行路径解析,得到inode。

但是,这和我们的分区有什么关系,文件不是存储在分区中吗?怎么和根目录扯上关系了?

一个被写入文件系统的分区,要想被linux操作系统使用,需要将这个分区“挂载”到对应的目录中!分区的访问,都是通过“挂载”的目录进行访问的,操作系统在打开目录和文件时,会在内存中缓存下来文件信息和文件路径信息,形成一个叫做dentry的数据结构,而文件系统的管理信息就保存在super block中,也是一个struct结构体,将写入文件系统的分区挂载到对应的目录下,其实就是两个数据结构的联系,这样我们再访问根目录下的文件时,就相当于访问了分区下的文件。

那么我又怎么知道我的文件在哪个分区下?首先,分区和挂载的目录是对应的,而我们要找一个文件,需要他的路径,当我们知道他的路径后,匹配他的路径前缀,就可以知道分区挂载的目录,从而找到这个分区。

第五点

在磁盘中,没有目录和路径这样的概念,只有文件的概念,包括我们平时说到的视频,图片什么的。但是因为我们每打开一个文件,需要对他们进行管理,于是在内存中才有了目录和路径这个概念。

那么我们对文件的理解也就是未被打开的磁盘文件,以及已经打开的内存文件。

当文件未被打开时,就是我们上面讲的磁盘对文件的存储和管理,当文件打开时,加载到内存,则会被进程管理,然后由进程对文件做出一系列增删查改的操作。

总结: 

我们将磁盘从物理结构抽象成线性的逻辑结构,并将这个线性空间进行了分区,现在我们知道,访问分区其实就是访问它所挂载的目录,因为只有挂载后,才能访问这个分区。

而一个分区对文件的管理方式并不是分区后就有的,还需要写入文件系统,这个文件系统的管理信息存储在super block中。

为了对对一个分区更好的管理,又将分区进行了分组,每一个分组都按照写入的文件系统管理方式进行管理,我们上面讲解的是ext*(2)文件系统,GDT,inode block,data block,inode bitmap,data bitmap。

当我们希望新建一个文件时,touch + 新建文件名,这是个进程,而进程的路径是确定的,每当我们跑起来一个进程时,他的路径就确定了,我们也可以通过ls /proc/进程pid查看到cwd,也就是进程的路径,进程路径拼上这个文件名就是文件的路径,操作系统根据这个路径逆向递归找到分区挂载的目录,从而知道在哪个分区创建文件,然后在分组中的inode bitmap中遍历寻找最小的还未被使用的位置,由0改为1,记下偏移量,在inode block中对应位置填充新建文件的信息,如果这个文件还有内容,那么就再遍历data bitmap,再对应data block,将他的编号填入inode的数组中,做完这些,操作系统返回inode编号,就是文件所在分组的inode起始编号加上他在inode bitmap中的偏移量,将编号返回后,操作系统会将这个inode编号和文件名建立映射关系,将他写入到这个文件的父目录的data block中,这样我们的文件就创建好了。

当我们希望查找一个文件时,ls + 文件名,如果这个文件的路径缓存了下来,那就用文件的dentry去确定,如果没有缓存下来,那就使用进程的路径拼上这个文件名,就是文件的路径,然后操作系统根据这个路径逆向递归找到分区挂载的目录,而这个目录的inode编号是确定的,从这里再开始对文件的解析,找到文件的inode,从而找到文件的父目录,再通过文件名在父目录内容中存储的文件名和inode编号映射关系,找到文件的inode编号,这个文件的分区我们也通过他的路径确定了,那么就去这个指定分区中根据这个编号去寻找,最终得到他的属性和内容。


若有理解错误,欢迎各位指正。

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

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

相关文章

【C++庖丁解牛】模版初阶

📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 目录 1. 泛型编程2. 函数模…

ssGSEA -- 学习记录

文章目录 biref统计学原理其他注意事项代码实现部分 biref 前情提要链接: https://blog.csdn.net/jiangshandaiyou/article/details/136536349 https://blog.csdn.net/jiangshandaiyou/article/details/134457515 相比起GSA,GSEA不再关注于差异基因&…

打卡--MySQL8.0 一(单机部署)

一路走来,所有遇到的人,帮助过我的、伤害过我的都是朋友,没有一个是敌人。如有侵权,请留言,我及时删除! MySQL 8.0 简介 MySQL 8.0与5.7的区别主要体现在:1、性能提升;2、新的默认…

【C++】三大特性之继承

1 继承的概念及定义 1.1 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展、增加功能,这样产生新的类,称派生类(或子类)。而被继承的…

.NetCore6.0实现ActionFilter过滤器记录接口请求日志

文章目录 目的实现案例:一.首先我们新建一个WebApi项目二.配置 appsettings.json 文件,配置日志存放路径三.创建 Model 文件夹,创建AppConfig类和ErrorLog类1.在AppConfig类中编写一个GetConfigInfo方法获取配置文件中的值2.在ErrorLog类中&a…

磁盘无法访问?别慌,这里有解决之道!

电脑中,那块储存着重要文件与数据的磁盘,突然之间无法访问,是不是让你感到惊慌失措?面对这样的突发状况,很多人可能会感到手足无措。但别担心,本文将为你解析磁盘无法访问的原因,并提供实用的数…

全志D1s开发板裸机开发之坏境搭建

环境搭建 开发板介绍 张天飞老师编写的《RISC-V体系结构编程与实践》,里面的源码是基于 QEMU 模拟器的,可以认为它是一款虚拟的开发板。如果需要在真实开发板上学习,可以使用百问网的 DongshanPI-D1S 开发板。 DongshanPI-D1S 是百问网推出…

【MySQL | 第四篇】区分SQL语句的书写和执行顺序

文章目录 4.区分SQL语句的书写和执行顺序4.1书写顺序4.2执行顺序4.3总结4.4扩充&#xff1a;辨别having与where的异同&#xff1f;4.5聚合查询 4.区分SQL语句的书写和执行顺序 注意&#xff1a;SQL 语句的书写顺序与执行顺序不是一致的 4.1书写顺序 SELECT <字段名> …

【脚本玩漆黑的魅影】寂雨镇全自动练级

文章目录 原理全部代码 原理 老样子。 治疗路径&#xff0c;练级路径。 def zhi_liao(): # 去治疗walk(RIGHT)walk(RIGHT)press(UP, 0.4)for i in [1, 2, 3, 4]:press(A)for i in [1, 2, 3, 4]:press(B)press(DOWN, 0.4)press(LEFT) def chu_qu(): # 右逛c.press(B)press(…

分类算法(Classification algorithms)

逻辑回归(logical regression&#xff09;&#xff1a; 逻辑回归这个名字听上去好像应该是回归算法的&#xff0c;但其实这个名字只是在历史上取名有点区别&#xff0c;但实际上它是一个完全属于是分类算法的。 我们为什么要学习它呢&#xff1f;在用我们的线性回归时会遇到一…

ABA关键词选品,大卖成功打造亚马逊爆款的秘密武器

做亚马逊新手在产品方面容易出现的问题&#xff08;都说跨境7分靠选品&#xff0c;3分靠运营&#xff0c;如果品没选对&#xff0c;直接掉坑里&#xff09;&#xff1a; 比较盲目的上产品&#xff0c;没有进行详细的市场调研&#xff08;如目标市场&#xff0c;国情以及受众分析…

【黑马程序员】STL实战--演讲比赛管理系统

文章目录 演讲比赛管理系统需求说明比赛规则程序功能 创建管理类功能描述创建演讲比赛管理类 菜单功能添加菜单成员函数声明菜单成员函数实现菜单功能测试 退出功能添加退出功能声明退出成员函数实现退出功能测试 演讲比赛功能功能分析创建选手类比赛成员属性添加初始化属性创建…

spring boot 2.4.x 之前版本(对应spring-cloud-openfeign 3.0.0之前版本)feign请求异常逻辑

目录 feign SynchronousMethodHandler 第一部分 第二部分 第三部分 spring-cloud-openfeign LoadBalancerFeignClient ribbon AbstractLoadBalancerAwareClient 在之前写的文章配置基础上 https://blog.csdn.net/zlpzlpzyd/article/details/136060312 因为从 spring …

基于docker部署的Selenium Grid分布式自动化测试

01、什么是Selenium Grid Selenium Grid是Selenium套件的一部分&#xff0c;它专门用于并行运行多个测试用例在不同的浏览器、操作系统和机器上。 Selenium Grid有两个版本——老版本Grid 1和新版本Grid 2。我们只对新版本做介绍&#xff0c;因为Selenium团队已经逐渐遗弃老版…

【电路笔记】-PNP晶体管

PNP晶体管 文章目录 PNP晶体管1、概述2、PNP晶体管电路示例3、PNP晶体管识别1、概述 PNP 晶体管与我们在上一篇教程中看到的 NPN 晶体管器件完全相反。 在这种类型的 PNP 晶体管结构中,两个互连的二极管相对于之前的 NPN 晶体管是相反的。 这会产生正-负-正类型的配置,箭头…

Echarts 配置项 series 中的 data 是多维度

文章目录 需求分析 需求 如下图数据格式所示&#xff0c;现要求按照该格式进行绘制折线图 分析 在绘制折线图时&#xff0c;通常我们的 series 中的 data 数据是这样的格式 option {title: {text: Stacked Area Chart},tooltip: {trigger: axis,axisPointer: {type: cross…

车辆伤害VR安全教育培训复用性强

VR工地伤害虚拟体验是一种新兴的培训方式&#xff0c;它利用虚拟现实技术为参与者提供身临其境的体验。与传统的培训方式相比&#xff0c;VR工地伤害虚拟体验具有许多优势。 首先&#xff0c;VR工地伤害虚拟体验能够模拟真实的工作环境和事故场景&#xff0c;让参与者在安全的环…

论文阅读:Diffusion Model-Based Image Editing: A Survey

Diffusion Model-Based Image Editing: A Survey 论文链接 GitHub仓库 摘要 这篇文章是一篇基于扩散模型&#xff08;Diffusion Model&#xff09;的图片编辑&#xff08;image editing&#xff09;方法综述。作者从多个方面对当前的方法进行分类和分析&#xff0c;包括学习…

Python(38):Request的data需入参是json,用转换json.dumps(data)

Python接口自动化测试遇到问题:误传str类型给request 一&#xff1a;request接口请求数据用str传参报错&#xff0c;请求响应报错 排查原因&#xff1a;查看服务器报错是Json解析报错。 1.1、如果直接入参&#xff0c;进行request请求的数据&#xff1a; data请求值为&…

ElevenLabs用AI为Sora文生视频模型配音 ,景联文科技提供高质量真人音频数据集助力生成逼真音效

随着Open AI公司推出的Sora文生视频模型惊艳亮相互联网&#xff0c;AI语音克隆创企ElevenLabs又为Sora的演示视频生成了配音&#xff0c;所有的音效均由AI创造&#xff0c;与视频内容完美融合。 ElevenLabs的语音克隆技术能够从一分钟的音频样本中创建逼真的声音。为了实现这一…