Linux——文件系统
前言:通过对基础IO的学习,可以知道:文件描述符用于标识已经打开的文件,通过数组数组下标来建立映射关系,而这个数组是一个指针数组,每个文件都有一个file对象,内部保存了文件相关的inode等其他信息。
inode_number用于寻找该文件存储在磁盘或者硬盘的文件信息和数据。
1.硬件基础
1.1 理解什么是柱面、磁道、磁头、扇区
磁道:完整的一圈被称为磁道
扇区:图中黑色部分称为扇区 注:即使长短不同,但是实际扇区A、B、C的大小都为512B
扇区是存储数据的基本单位
柱面:磁盘是分布如图所示,而柱面是垂直方向上,所有磁道构成的面,有多少磁道,就有多少柱面
磁头:磁盘一般有上下两个面,每个面对应一个磁头,那么一个磁盘共有两个磁头
1.2 LBA地址
我们可以把每个磁道拉直,这样就抽象成了一个数组,每个扇区对应有着自己的地址(其实是数组下标),这种地址叫做LBA
某扇区的LBA = 它所在的柱面号 * 单个柱面的扇区总数 + 它所在的磁头号*每磁道扇区数 + 扇区号S - 1
2.初识文件系统
2.1 什么是“块”?
为了提高效率,操作系统实际在读取硬盘时,不会按最小单位读取(即一个扇区一个扇区读取),而是一次性读取多个扇区,这样连续的扇区被称为”块“。
块:一个块的大小通常为 4KB = 4096B一个扇区的大小为512B,那么一个块就由8个扇区构成。
注:
知道LBA,块号 = LBA/8
知道块号,扇区 = 块号*8 + n(块内第几个扇区)
2.2 什么是“分区”?
磁盘是可以被分成多个”分区“的,就比如我们熟悉的windows操作系统,一块硬盘能够被分成 C盘、D盘、E盘等。其中C、D、E就是分区,分区本质上是对硬盘的格式化。
注:柱面是分区的最小单位。
2.3什么是“inode”?
用于存储文件的创建者、创建日期、大小等信息的区域叫做inode
注:
①:linux中文件存储的属性和内容是分离存储的
②:linux下,保存文件属性的集合inode,一个文件一个inode,inode内有一个唯一的标识符,叫做inode号
③:文件名属性没有纳入到inode数据结构中
④:inode的大小一般为128字节或者256字节
⑤:任何文件的内容大小可以不同,但是属性大小一定是相同的
3.ext2文件系统
3.1 宏观认识
ext2文件系统将整个区域划分为不同的分区(假设为1、2、3、4),再将其中的每个分区划分成若干个同样大小的组块(Block Group),如下图所示。
3.2 块组内部构成
3.2.1 inode table (i节点表)
存放文件属性 如文件大小,所有者,最近修改时间等
当前分组所有inode属性的集合
inode_number 以分区为单位,在同一分区内是唯一的,不可跨分区
注:通过inode_number就可以找到对应文件的信息
3.2.2 Block Bitmap (块位图)
通过位图的方式来记录哪个数据块被占用,哪个数据块没有被占用
例如:一个有98304个bit位,换算后对应3个数据块,那么在Block Bitmap中 001,就表示第一个数据块被占用,其他没有被占用。
3.2.3 inode Bitamp 位图
每个bit表示一个inode是否空闲可用
3.2.4 GDT (Group Descriptor Table)
块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储一个块组的描述信息,如在这个块组中从哪里开始是inode Table,从哪里开始是DataBlocks,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有一份拷贝。
3.2.5 Super Block
存放文件系统本身的结构信息,描述整个分区的文件系统信息。记录的信息主要有:block和inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了
注:
①:当知道了 block 和 inode table 的大小就知道了 Block BitMap 和 Inode Bitmap的大小,就知道了GDT多大,因此Super Block衡量了一个分区所有信息
②:在使用一个分组前,需要把所有信息写入到Super Block 和 GDT 当中,同时将Blcok Bitmap、inode BitMap、inode Table、Data Block 全部清零,这个过程就叫格式化。
③:不是所有块组都有Super Block,一个inode Block挂了,影响不过是几个g的数据,但是一个超级块挂了,影响就是几百G的数据 ,因此当其中一个超级块出问题时,可以用其他块组中的超级块来恢复。
这就是为什么超级块会被放在多个块组中,而不是单独放在File System中,就是为了其中一个出错,数据还能够恢复
3.2.6 Date Blocks
数据区:存放文件内容,也就是一个一个的Block。根据不同文件类型有以下几种情况
👉:对于普通文件,文件的数据存储在数据块中
👉:对于目录,该目录下所有的文件名和目录名存储在所在目录的数据块中,除了文件名外
👉:Block号和inode number 一样按照分区划分,不可跨区,且每个分区内唯一
3.2.7 初步总结:
通过对上述内部构成的认识,可以有初步的认识:一个磁盘被分成多个区,每个区都有Super Block 来描述每个区的信息,因此只要把每个区的超级块通过数据结构连接起来并加载到内存中,其中每一个区被分成多个块组,块组中有GDT、Block、inode BitMap,同样将这些信息加载到内存中,只要知道文件的inode号,就能在指定分区中确定哪一个分组,进而在哪一个分组确定是哪一个inode,只要有了inode,对应的文件属性和内容就全都有了,操作系统就能通过对数据结构的增删查改来实现对磁盘的管理。
3.3 目录与文件名
在实际的过程中,我们访问文件并不会使用inode号,而是使用文件名,但文件名并不会保存在inode中。
3.3.1 路径解析
问:我们该如何看待目录?
答:目录也是按照上述方式保存,也有自己的 inode table 和数据内容,而数据内容保存了inode和文件名的映射关系。
因此,访问文件时,必须打开当前目录,根据数据内容中的映射关系,通过文件名找到inode号,然后进行文件访问
所以,访问文件必须要知道当前工作目录,本质是必须能打开当前工作目录文件,查看目录文件的内容(因为数据内容中有文件名和inode_number的映射关系,只要知道了inode_number就知道该打开哪个文件对应的信息了)。
看这样一个目录:/blender_picture/Output。上述说了,要想访问一个文件,必须打开当前目录,也就是说我必须先打开Output文件,而打开Output文件就必须先打开
blender_picture,打开blender_picture需要打开/(根)目录。
注:/目录在系统启动时就会创建
3.3.2 路径缓存
问:难道我们访问任何文件都要从/目录开始吗?
答:这样做效率太低了,实际上,操作系统在进行路径解析时,会把历史访问的所有目录形成一颗多叉树,进行保存。有就直接加载,没有就继续完善二叉树,第二次查找的时候就会变得很快。
注:struct dentry 路径缓存,pcb中没有,只在内存中保存,每个文件都有dentry结构,包括普通文件,这样所有被打开的文件都可以在内存中实现树形结构
3.3.3 挂载分区
通过inode,我们可以在指定分区中找到对应文件存储的信息,但是如何确定文件在哪个分区呢?
答:挂载分区是将一个存储设备(如硬盘的一个分区)与操作系统的目录树中的某个目录建立关联的过程。这样,用户就可以通过访问该目录来访问存储设备上的文件和数据,具体过程:分区→格式化→建立挂载点→执行挂载操作
4.当一个文件打开时发生了什么?
当没有指定路径时,操作系统会添加pwd, 并且在内核当中搜索路径,如果没有当前路径,则会在内核中添加当前路径作为新的路径,以便下次可以快速打开;如果有当前路径,则直接打开文件,并找到对应inode,根据文件的inode找到文件的属性和内容,在内核当中创建struct file、创建struct inode、创建文件缓冲区,将inode的属性进行填充、磁盘属性加载到内存、文件内容部分加载到文件缓冲区,把struct file对应地址在文件描述符表中进行分配,给用户返回文件描述符,因此之后用户就可以通过文件描述符找到该文件内存当中的struct file对象 、对应路径inode以及缓冲区。
原文地址:https://blog.csdn.net/m0_51952310/article/details/145181249
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!