Linux文件——文件系统Ext2(1)_理解硬件

文章目录

Ext文件系统------理解硬件

之前我们学习过Linux下的基础IO操作,但是,IO操作是操作系统把文件从存储设备中读取出来后加载到内存上进行读写等操作。这是操作系统对于内存中打开的文件进行的管理。

但是,还有一部分文件可能是没有被打开的,可能放在一些外设中,比如放在磁盘上。

那么问题就来了,操作系统如何找到磁盘上存放的文件呢?磁盘上又该如何对文件进行管理呢?操作系统又是如何根据用户的指令对磁盘中的文件进行操作呢?

这些都是归于一个方面------即文件系统的工作。

本文是文件系统的第一篇,旨在理解存储文件的一些外设硬件,如磁盘。

在学习文件系统之前,我们需要来学习一些硬件相关的知识------理解磁盘。

学习了磁盘硬件之后,我们才方便对于后序的文件系统抽象化进行理解。

磁盘、服务器、机柜、机房

首先,我们来看看磁盘大概是长什么样子:

如上图所示,磁盘其实就是一个用来存储数据的外设。

我们需要介绍一些知识,我们可以发现,磁盘的表面看着是很光滑的,但其实并不然,如果是用放大镜/显微镜上看还是会有一些比较突的点。

磁盘工作的时候,底下的转盘会旋转,转速非常快,可达每秒几千转。同时,我们可以发现有个探针。探针是用来写入数据的。它们的工作是由磁盘内的一些传动系统带动的:

我们可直接认为:

当磁头在磁盘上进行操作的时候,就是磁盘在进行数据的读写操作。


磁盘属于外设,由操作系统体系结构图可知,这个设备是离CPU比较远的设别。所以,它的读写速度是比较慢的。但是,有一个非常大的优点:即磁盘的存储容量非常大!

我们也学过一个内存分级的概念:离CPU越远,速度越慢,价格越低,存储容量越大。在一些企业级的存储数据设备中,正是因为这个优点,所以很多企业选择使用磁盘来进行存储数据。当然,对于一些常用的,最近的数据,可能会选择其他设备进行存储。

一些企业在使用的时候,会把几块磁盘放在一块,每块磁盘用作不同功能,这样可以组成一台服务器:

其实,我们使用的远端云服务器就是这样的,我们所有的数据都是存在这上面的。

然后,可以把多个服务器在放到一起,进行一些相关网线连接和相关的配置,组成一个机柜:

最后,可以把一个一个的机柜放在同一个空间内,这就组成了机房了:

所以,我们可以知道,机房并不是每个企业都可能有的东西,它涉及到了特别多的成本:

如场地、设备、管理、运行等多项成本,这也就是为什么市面上云服务器厂商没有太多。

磁盘读写数据

我们会好奇,磁盘是如何进行数据的写入和读取的。具体的操作我们肯定是不懂,因为这个涉及到软硬件的结合和一些电子电路的知识。

但是这里可以提及的一点是:

磁盘看似表面光滑,其实上面会有一些凹凸不平的点。我们可以把这些点看做成是一个磁铁:

磁铁具有两个磁极------即南北极。

又知道,计算机的世界是两态性的。计算机只能认识二进制的数据,所以,是否可以让磁铁的极性为两极之一的时候,为数据1,零一个磁极则是0。这样子,不久完成了数据的写入和读取方法的设计了吗?

所以,磁盘对于数据的写入和读取,就是通过磁盘上小磁铁的极性来完成的。

磁盘的物理存储结构

接下来,我们需要了解一下磁盘的物理结构。

我们先来从俯视视角来看磁盘:

其实就是直接看这个光滑的盘面。

磁盘是由马达带动中间的主轴进行转动的。磁盘我们可以想象成是有多个同心圆组成的一个盘面。同心圆的个数会非常多,所以能够近似堪称表面平整光滑。

但是,每个同心圆并不是连续并闭合的,而是有一定的间隙(只不过间隙太小,肉眼看不出)。

其实,磁盘中每个"同心圆"被称作为磁道 ,磁道中被分割出来的每一小段"圆弧"叫做扇区 !磁盘上存储数据的位置,就是在扇区 ,如下所示:

对于磁盘盘面的详细划分图如上所示。

其实就是由这样一条条的圆环(磁道)组成一个盘面,每个磁道由被细分为多个和扇形的区域,这个扇形的区域就是扇区!存储数据的区域就是在这个扇区,扇区存储数据的容量一般是512字节。当然,具体的容量取决于不同厂商的实现。

这里还有一个注意的点:

一般来说,每个扇区内存储的数据量是一样的,但是我们看图上的得知,扇区越靠外,扇区面积越大。这就说明:越靠内的扇区,存储密度越大。

当然,不同的厂商不同型号也是不一样的,也有一些型号的磁盘,其每个扇区内存储数据的容量是取决于扇区的大小的,即靠外的存储容量大一些。


上面,我们从磁盘的俯视视角进行观察,现在,我们从整个磁盘的空间立体结构出发:

真实的磁盘物理结构如上所示,是不可能只有一个盘片的。像上图展示的就是三盘六面。

其实,磁盘中,盘面是有多个的。每个面对应的样子都是上面展示的俯视图一样。所以,每个盘面都可以存储数据,那就会有对应个数的读写磁头。

这些读写磁头都是由统一的机械臂杆来进行磁头的前后伸缩控制的(磁头共进退的!)。但是,并不是每个磁头都会用的上。如果数据量比较小的话,会选择合适的磁头来对对应盘面的扇区进行操作。


现在我们知道了磁盘的物理结构了,问题是,如何找到对应的扇区进行读写操作呢?

这里直接进行介绍:采用的是CHS定位法。

1.我们要知道的是,对于每个盘面上的磁道,如果在立体空间连接起来,是可以组成一个柱面:如上图的柱面c。整个磁盘中存在着很多的磁道,也就意味着有很多的柱面。所以,要想写入数据,首先得定好要写入的是哪一个柱面内的扇区,也就是CHS定位的定位C(Cylinder)。

2.其次,前面说到过,并不是每个磁头都能用的上的!磁头是用来选取读取的磁道的。所以,在定位好柱面后,就意味着选取出了若干个磁道,但是并不是每个都用的上,所以需要选取对应的磁头来进行数据的读取,也就是定位H(Head)。

3.选取好磁头后,还是不行,因为,选取磁头仅仅只是选取好了要写入哪些磁道上。但是,磁道又被分为多个扇区。真正写入数据的时候是写入扇区内的!所以,选取好磁道后,还要选取扇区。选取扇区很简单,马达带动磁盘旋转,磁头控制磁道位置,二者相互配合就能成功定位到扇区了!所以,这就是定位S(Sector)

所以,磁盘中数据的写入,是通过CHS(Cylinder Head Sector)来定位具体位置的。当然,具体的定位方法的程序,并不是操作系统决定的!而是由磁盘硬件程序来决定的,也就是驱动程序。操作系统只是调用其驱动程序来进行内容的读写。

对此,我们可以使用指令fdisk -l来进行查看相关信息:

磁盘逻辑结构

但是,使用CHS确实是很符合磁盘的物理存储结构,但是,操作系统在管理的时候,真的是需要记录数据写入的CHS坐标吗?这太麻烦了,所以,我们前面说的:是磁盘的物理结构!

但是,这个物理结构对于操作系统而言,是非常难受的,而且还不好使用。

所以,操作系统需要想一个办法对磁盘物理结构进行抽象化使用。

那么,操作系统如何对磁盘的物理结构进行抽象呢?

我们可以看看这个磁带,我们肯定试过把里面的磁带抽出来的经历。这个磁带在内部就是被卷起来的状态。然后通过内部两个齿轮的转动,转动到特定位置的磁带会被读取数据。

所以,我们是否可以认为,其实,每个磁道上的扇区也是可以被展开来的:

既然磁道能进行展开,那么整个盘面是不是也可以被展开呢?这当然可以。也就是说,整个盘面虽然是一个一个同心圆,但是,可以看作成是一个扇区的连续结构进行盘卷而成。

一个盘面可以展开来,那么,一个柱面呢?那必然也是可以的。柱面的展开就跟下面这个卷是一样的:


上面说的还是不太好理解,这一次,我们将从图示入手:

1.先对某个盘面上的某个磁道进行展开:

2.再对某个柱面进行展开:

柱面其实就是由多个磁道拼接起来的一个空间柱面。那么,把这个柱面展开,那不就是如上图所示,一个柱面内有多个磁道的展开。

整个磁盘中会有很多个这样的柱面展开:

最后我们可以完成CHS坐标对于连续线性结构的映射关系。

其实我们可以发现,这其实就是c语言中的三维数组!所以,操作系统看待磁盘的物理结构的时候,就是通过三维数组来看待的,这种坐标,叫做LBA地址

LBA和CHS的转化

LBA地址是操作系统用的。CHS坐标是磁盘内用的。二者需要进行一定的转化才行。

所以,接下来我们需要讲解二者之间的转化。

首先我们来看LBA如何转化为CHS:

我们先来复习一下位图的相关知识,这个和我们的转化公式是有一定的关联的:

我们知道,位图的本质是通过把每个比特位当作存储空间,记录某种状态。

比如一个整形变量,4个字节,32个比特位:

其实就是把每个整形空间分成32份,然后从0开始标号。然后位图是由整形变量数组来组成的,因为一个整数只能标识32个状态。

假设当前判断整数65是否存在,即找到编号为65的比特位。那么如何找呢?

很简单,首先我们需要知道它在第几个整型变量对应的比特位内:

所以我们可以让65 / 32得到是2,也就是在编号为2的位置,其实就是数组下标为2的空间。

然后再让65 % 32就可以得到在某个空间内对应的比特位编号。

其实上述就是想说明一个结论:
在由多个划分为一定数量n的空间,且从0连续编号的情况下:
给定一个整数x,要找到对应的位置,首先得确定空间编号,即使用整除(x / n)。再确定相对于局部空间的偏移量,所以需要使用取余算法(x % n)。


所以,我们现在来看看LBA如何转化为CHS坐标:

首先得确定柱面号c:

发现,以每个柱面为独立空间,柱面被进行了划分为多个磁道,磁道又被分为若干个扇区。

所以,求柱面号c非常简单,直接让LBA / 每个柱面对应的扇区数不久好了。

所以,柱面号c = LBA / (每个柱面对应的磁道数 * 每磁道对应的扇区数)

其中,每柱面的扇区数 = (每个柱面对应的磁道数 * 每磁道对应的扇区数)

接下来,我们要求磁头号h,但是我们来细想一下,能否直接使用取余算法得到磁头号h呢?
答案是不行!

因为上述通过位图讲述的原理我们会发现,以每个整形字节作为整体空间,比特位是单个字节空间的一级分区。

而这里对于磁道而言,它并不是。一级分区!我们如果使用公式:
LBA % (每个柱面对应的磁道数 * 每磁道对应的扇区数) ,得到的是什么?

得到的是相对于某个柱面内的,扇区编号的偏移量(如果一个柱面内的扇区用0开始进行连续编号)。但是,对于磁盘物理结构而言,由于柱面内的扇区又被进行了一层划分,所以,一个柱面内的扇区并不是从0一只连续编号,而是很多组从0开始编号的。

所以,我们可以这样子做,既然得到的是某个柱面内的扇区连续编号数,我们可以把柱面内的磁道再堪称独立空间呀,然后每个磁道又被分为多个扇区:

所以最后:
磁头号h = (LBA % (每个柱面对应的磁道数 * 每磁道对应的扇区数)) / 每磁道对应扇区数
扇区号s = (LBA % (每个柱面对应的磁道数 * 每磁道对应的扇区数)) % 每磁道对应扇区数 + 1

这里要注意:一般来说,磁头号和柱面号习惯0开始,而扇区号是从1开始

但是,对于扇区号而言,没必要那么麻烦的算。我们可以忽略柱面分区,我们直接把所有得磁头分区当成一个独立空间,这样子,扇区号仍是磁头号得一级分区空间。

然后,我们直接让 扇区号s = (LBA % 每磁道对应的扇区数) + 1

最后总结:

柱面号c = LBA / (每柱面对应的扇区数)
磁头号h = (LBA % 每柱面对应的扇区数) / 每磁道对应扇区数
扇区号s = (LBA % 每磁道对应的扇区数) + 1
每柱面的扇区数 = (每个柱面对应的磁道数 * 每磁道对应的扇区数)


接下来看如何把CHS转化为LBA呢?

这个比较简单,如果说目前给定了CHS坐标c,h,s:

我们只要通过这三个坐标来计算,需要跳过多少个扇区,才能得到LBA这个数,其实就是对LBA对CHS的转化呢作逆运算。

首先,我们要知道的是,c,h是由0开始编号得,s由1开始编号。

如果给定柱面号c,说明当前处于第c个编号的柱面,我们要确定的是,前面共有多少个柱面给我们"用完了"。因为柱面号为c的这个柱面我们肯定没用完。

答案是:c个。因为从0开始编号。

所以我们由柱面号可以知道,前面c * 每柱面对应的扇区数一定是被跳过的。

然后再来看磁头号,也是一样的,磁头号表明的是,当前位置下,前面有多少个磁头给我跳过了,这样子我们可以通过h * 每磁道对应扇区数来计算在当前柱面跳过了多少个扇区。

每个LBA对应的是一个扇区,所以还得计算,在当前磁道内跳了几个扇区。其实就是s - 1

因为扇区号表示的是在某个磁道内的编号,所以编号为几,代表为这个磁道内的第几个位置。但是,因为扇区编号从1开始,但是LBA是从0开始计算的,所以,需要减1才能得到LBA。

所以最终,得到:
LBA = c * 每柱面的扇区数 + h * 每磁道对应扇区数 + s - 1


所以:从此往后,在磁盘使用者看来,根本就不关心CHS地址,而是直接使用LBA地址,磁盘内部自己转换。所以:

从现在开始,磁盘就是一个 元素为扇区的一维数组,数组的下标就是每一个扇区的LBA地址。OS使用磁盘,就可以用一个数字访问磁盘扇区了。

相关推荐
悲伤小伞3 小时前
Linux_Ext系列文件系统基本认识(一)
linux·运维·服务器·c语言·编辑器
喜欢你,还有大家4 小时前
Linux笔记2——常用命令-1
linux·服务器·笔记
网硕互联的小客服4 小时前
服务器无法访问公网的原因及解决方案
运维·服务器
Gappsong8744 小时前
Rufus:Ubuntu U盘启动盘制作工具详解
linux·c++·web安全·网络安全
dessler5 小时前
RabbitMQ-交换机(Exchange)
linux·分布式·zookeeper·云原生·kafka·rabbitmq
程序员编程指南6 小时前
Qt开发环境搭建全攻略(Windows+Linux+macOS)
linux·c语言·c++·windows·qt
我爱学嵌入式6 小时前
C语言第 4 天学习笔记:位运算、流程控制与输入输出
linux·c语言·笔记
西红柿煎蛋7 小时前
WSL2子系统连接USB
linux
豆是浪个7 小时前
Linux(Centos 7.6)命令详解:jobs
linux·运维·centos
kyle~7 小时前
数据交换---JSON格式
服务器·microsoft·json