Linux --Ext系列文件系统

发布于:2025-06-18 ⋅ 阅读:(21) ⋅ 点赞:(0)

本文重点:

        1.理解物理磁盘结构

        2.掌握CHS和LBA地址

        3.掌握Etx系列文件系统的原理

        4.理解分区,格式化,路径解析,挂载过程

理解硬件

  1.物理的磁盘结构:在文件的储存外设中磁盘是通过无数个极小的磁铁的南北极来表示二进制的,而磁盘物理结构一般是由一个主轴(马达),磁盘(相当于纸),磁头(相当于笔),磁头臂,永磁体。

  2.磁盘的存储结构:磁盘是有N个相同的盘面和N个相同磁头以及一个转动臂组成的,这里的盘面是每一面,即一个圆盘的两名都可以作为盘面。在盘面中又有许多个同心圆组成的磁道,每个磁道中有N个容量大小相同的扇区,这里的扇区是磁盘的最小储存单位,一般是512字节。

  3.那么如何定位一个扇区?可以先定位(柱面C)磁道,然后然后定位磁头(H),最后定位扇区(S)。这里的柱面其实是逻辑上相同半径同心圆磁道组成的,实际并不存在,可以通过这个说法快速定位扇区在哪一个同心圆,然后具体到哪一个磁头的磁道上,再找到对应的扇区。这也叫做CHS定址法,这是早期磁盘中定位扇区的主要方法。如何计算磁盘容量?即磁头数 × 磁道(柱⾯)数 × 每道扇区数 × 每扇区字节数。

  4.磁盘的逻辑结构:磁带作为一种简单的储存声音数据的设备,我们可以把磁带“拉直”,形成线性结构,我们就可以将它认为是每个元素都是一个储存单元的一个一维数组。那么磁盘也是如此,可以逻辑结构上的储存认为是这样的:

而一个磁盘上的所有盘面的同一个磁道,即柱面逻辑上展开是这样的:

然后我们整个磁盘上又分为N个柱面,我们展开又可以得到:

所以这样我们就将一个磁盘逻辑上可以看成一个三维数组,但是实际上在内存分配中它们的内存地址是连续的,所以整个磁盘就可以看成一个一维数组!这样任何一个柱面中的任何一个磁道上的任何一个扇面都拥有了它的线性地址,即数组下标,我们把这种地址就叫做LBA(Logical Block Address)。

 底层磁盘还是需要使用CHS来定位扇区,其中将CHS地址转换成LBA地址是由磁盘自己来做的,磁盘中自带的固件会完成这一个操作,所以在磁盘使⽤者看来,根本就不关⼼CHS地址,⽽是直接使⽤LBA地址,磁盘内部⾃⼰转换。所以:从现在开始,磁盘就是⼀个元素为扇区的⼀维数组,数组的下标就是每⼀个扇区的LBA地址。OS使⽤磁盘,就可以⽤⼀个数字访问磁盘扇区了。

 

磁盘中一下基础概念

  1.引⼊"块"概念:其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会⼀个个扇区地读取,这样效率太低,⽽是⼀次性连续读取多个扇区,即⼀次性读取⼀个”块”(block)。硬盘的每个分区是被划分为⼀个个的”块”。⼀个”块”的⼤⼩是由格式化的时候确定的,并且不可以更改,最常⻅的是4KB,即连续⼋个扇区组成⼀个 ”块”。”块”是⽂件存取的最⼩单位。

  2.引入分区概念:磁盘中可以将一块磁盘分为多个分区,分区实际上就是将磁盘划分,然后写入新的文件系统,对其的一种格式化。

  3.引入"inode"概念,之前我们说过文件 = 数据 + 属性,文件数据存储在块中,那么还必须找到一个地方存储文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种存储文件元信息的区域就叫做inode,中文译名为索引节点,也叫i节点。因此,一个文件必须占用一个inode,但至少占用一个,inode大小一般是128个字节或者256个字节。inode包含很多的文件元信息,但不包含文件名,例如:字节数、属主UserID、属组GroupID、读写执行权限、时间戳等,以及对应数据的块映射的一个块的数组指针。

  4.引入文件系统:我们已经了解到了磁盘是一个块设备,但是这些块需要管理,以及分区如何进行,储存文件属性的inode和文件数据block是如何进行管理的,这都需要一个系统进行管理,这个系统就叫做文件系统。

Ex2文件系统

  1.我们想要在硬盘上储存文件,那么必须就要将硬盘格式化成某种格式的文件系统才能储存文件。文件系统的目的就是组织和管理硬盘中的文件,这里用较为早期的ext2文件系统来演示,因为后期的系统虽然进行了提示和增强,但是核心设计没有发生改变。

  2.基本结构:ext2文件系统将一个分区再分为N个Block Group,也就是说一个分区只有能够管理一个分组,剩下的分组按照这个方法进行管理那么就能将整个分区管理,然后管理所有的分区,也就管理了所有的文件。ext2⽂件系统会根据分区的⼤⼩划分为数个Block Group。⽽每个Block Group都有着相同的结构组成。Block Group下又分为几个组成部分:Super Block,GDT,Block bitmap,inode bitmap,inde Table, data blocks,相信在组成部分中大家就已经能够初见端倪了,接下来我会逐个分析。

  3.1 Super Blcok(超级块):用于储存文件系统本身的结构信息,描述整个分区的文件系统信息。记录的信息主要有:bolck 和 inode的总量,未使⽤的block和inode的数量,⼀个block和inode的⼤⼩,最近⼀次挂载的时间,最近⼀次写⼊数据的时间,最近⼀次检验磁盘的时间等其他⽂件系统的相关信息。Super Block的信息被破坏,可以说整个⽂件系统结构就被破坏了。Super Blcok在第一个组中的开头都会有一份拷贝,一般会有其他的几份拷贝在其他组,防止一份Super Blcok损坏导致整个分区挂掉,损坏的Super Blcok会从其他组进行重新拷贝,保证分区的正常运行。

  3.2 GDT(Group Descriptor Table):这是整个分组的管家,它是块组描述符表,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储⼀个块组的描述信息,如在这个块组中从哪⾥开始是inode Table,从哪⾥开始是Data Blocks,该组中bolck 和 inode的总量,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有⼀份拷⻉。

  3.3 Block bitma(块位图) :Block Bitmap中记录着Data Block中哪个数据块已经被占⽤,哪个数据块没有被占

  3.4 inode位图(Inode Bitmap):每个bit表⽰⼀个inode是否空闲可⽤

  3.5i节点表(Inode Table) :存放⽂件属性 如 ⽂件⼤⼩,所有者,最近修改时间等 ,当前分组所有Inode属性的集合 ,inode编号以分区为单位,整体划分,不可跨分区。

  3.6:Data Block 数据区:存放⽂件内容,也就是⼀个⼀个的Block。根据不同的⽂件类型有以下⼏种情况: 对于普通⽂件,⽂件的数据存储在数据块中。对于⽬录,该⽬录下的所有⽂件名和⽬录名存储在所在⽬录的数据块中,除了⽂件名外,ls -l命令看到的其它信息保存在该⽂件的inode中。Block 号按照分区划分,不可跨分区。

  3.7 inode和data blcok的映射:在inode中的逻辑结构是如下图所示的

前面十二个指针是直接指向data block储存文件内容块的,下面的三个指针指向的是储存了其他块指针的的块,也就能够使inode统一大小但是能够储存大型文件,最后一个三级指针能够储存的文件大小为4个T(一个块为4Kb)。如果该组内的block块用完了是可以去其他组占用空闲的data block的。但是一个组中的inode用完了不能跨组。

  3.8 创建新文件的操作:(1)储存属性,OS先会将inode bitmap加载到内存中,然后找到一个空闲的inode,然后在inode table中将属性写到对应的块中。(2)储存数据,假设该⽂件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第⼀块数据复制到300,下⼀块复制到500,以此类推。(3)记录分配情况,将对应的data block映射到inode中。(4)添加文件名到目录中。这里使用一个简图来说明:

  3.9 具体文件的查找都是需要通过inode先在inode bitmap去查找该inode是否有效,有效为1空闲为2,然后在inode table中找到对应的inode去找对应的block映射,再在block bitmap查询是否该block有效,最后去data block 找到该文件的内容。如果需要删除一个文件,并不需要将文件内容从磁盘删除,只需要将对应inode bitmap和block bitmap设为0即为逻辑上的删除,此时不会影响新的文件属性和数据在原来的inode和block之中写入。 

关联操作系统

  所以在上面的了解之中我们知道了需要在一个分区中找到一个文件就必须要有inode,但是没有使用文件名,这是因为在目录中已经储存了文件名和inode的映射关系,即用户有了文件名就可以找到对应的文件。目录也是文件,磁盘中并没有目录的概念,所以目录的内容保存的就是该目录下的文件名和对应映射的inode。所以,访问⽂件,必须打开当前⽬录,根据⽂件名,获得对应的inode号,然后进⾏⽂件访问。所以,访问⽂件必须要知道当前⼯作⽬录,本质是必须能打开当前⼯作⽬录⽂件,查看⽬录⽂件的内容。

  所以这里我们就能够理解为什么一个目录没有读权限就不能够查看该目录下的文件,没有写权限就无法新增文件,没有执行权限就无法打开目录,因为目录和普通文件在磁盘中是一样的,没有读写权限就无法查看和写入data block。

  既然如此,我们可以通过这个方式找到目录下的文件的内容,但是我们并不知道该目录的inode也就无法访问它的内容,也就是目录下文件和inode映射。所以要访问它就要知道它的上一层目录的inode,层层递归,最后就到了根目录,所以访问一个目标文件都要从根⽬录开始,依次打开每⼀个⽬录,根据⽬录名,依次访问每个⽬录下指定的⽬录,直到访问到test.c。这个过程叫做Linux路径解析。所以,我们知道了:访问⽂件必须要有⽬录+⽂件名=路径的原因 ,根⽬录固定⽂件名,inode号,⽆需查找,系统开机之后就必须知道,是系统硬编码的。

  那么在我们每次打开或者访问某个文件都有从根目录开始解析路径吗?并不是这样的,Linux中会对路径进行和缓存,目录的概念只有在OS中才有,由OS在内存中自己进行维护。在进程的PCB中找到struct flies_struct ,然后在这个结构体中有一个file* fd_arry数组,然后去查看file,我们会找到一个struct path结构体,再进去查看就会发现一个struct dentry的结构体,这个结构体中储存着该文件的inode,以及它的父节点和子节点,所以这个dentry是一个树形结构,也就是说在文件打开以后就会自动初始化一个dentry然后作为所在目录的子节点插入这个缓存树中,所以后续查找的过程只需要遍历这棵树就能找到对应的文件,而不需要再访问磁盘,减少IO提升系统效率。

  我们已经能够根据inode号在指定分区找⽂件了,也已经能根据⽬录⽂件内容,找指定的inode了在指定的分区内,我们可以为所欲为了。可是:inode不是不能跨分区吗?Linux不是可以有多个分区吗?我怎么知道我在哪⼀个分区?这就归功于系统中的挂载分区了。分区写⼊⽂件系统,⽆法直接使⽤,需要和指定的⽬录关联,进⾏挂载才能使⽤。所以,可以根据访问⽬标⽂件的"路径前缀"准确判断我在哪⼀个分区。将分区写入目录的操作就叫做挂载。


网站公告

今日签到

点亮在社区的每一天
去签到