探秘磁盘内部的储存方式,揭露文件在软硬件上的不同模式
1 引言
- 进程中被打开的文件,被加载进了内存当中。
- 难道所由的文件都被打开,加载进了内存当中吗?--- 当然不是
- 那么那些没有被打开文件存储在哪里呢?---被储存在了磁盘和固态硬盘(SSD)上
- 4.那么那些在磁盘上的文件需不需要被操作系统管理呢?---当然需要啦
- 那么操作系统怎么样才能在磁盘上快速找到目标文件呢?
2 磁盘的机械结构
2.1 盘面
- 盘片:就是堆叠在一起的圆形金属片。
- 盘面:盘片表面涂上磁性物质,涂上磁性物质,可以存储数据的那一面就叫做盘面。但是,盘片也可以两面都涂上磁性物质,这样一个盘片就有了两个盘面。
2.2 磁道和扇区
- 磁道(又叫做柱面):盘面上一个个被划分出来的同心圆环,叫做磁道。
- 扇区:每一个磁道又被划分为一个个扇形,这一个扇形就称为扇区。
扇区一般就是操作系统进程I/O操作最小的单位。
既然,是作为最小单位,那么每一个扇区存储的内容应该是一样多的,但是,我们可以观察到每一个扇区的大小是不一样,那怎么办?
为了保证扇区的存储大小一致,所以,每一个不同磁道的扇区的存储数据密度是不一致的
2.3 柱面和磁头
柱面:就是由每一个盘面上半径相同的磁道组成的空心圆柱
磁头:每一个盘面上都会有点一个读取数据的机械结构(注意:磁头和盘面只是离得非常近,两者之间是不接触的)
磁头和盘片的运动轨迹:盘片是依靠中心圆中主轴上的马达高速转动。磁头则是横向运动(如下图)
两者之间保持一个合适的速度差,使得磁头可以扫过盘面的每一块区域。
3 磁盘的物理储存
3.1 CHS定位寻址法
如果,为了让磁盘找到目标文件,在硬件层面上是使用CHS定位寻址法。
- 先让磁头确定目标数据是在哪一个柱面(C)
- 再通过确定在哪一个磁道,这样就确认的使用哪一个磁头 (H)
- 最后在通过确定哪一个扇区(S)
这样通过柱面,磁头,扇区三个参数,就确定了数据的位置。
这样每一个文件,不就是多个扇区组成的吗。这样就确定文件的位置了
4 磁盘的逻辑存储
4.1 线性的存储空间
我们看到这种磁带的黑色长线就是,他储存数据的地方,通过转动中央的两个孔来实现对数据的读取。
由此,我们联想到可不可以把所有的磁盘空间抽象的转化为一个长数组,把对数据的增删查改转化为对数组的增删查改。
4.2 LBA地址
- LBA地址(Logical Block Addressing,逻辑块寻址):是将扇区编号转化为一维线性编号的逻辑寻址方式,即:它将磁盘上所有扇区编号为一个连续的线性序列。
- LBA地址是一个线性地址(单一的数字),用于唯一标识磁盘上的一个扇区,LBA地址从0开始,依次递增。
- 工作原理:LBA编址方式将CHS这种三维寻址方式转变为一维的线性寻址;在访问磁盘时,系统或者磁盘控制器直接指定从硬盘上的特定扇区读取或写入LBA地址,硬盘控制器负责将LBA值转化为实际的物理CHS值。
- 优点:简化了数据访问的过程,提高了系统的效率,支持更大的容量;因为它采用线性寻址的方式,因此不受物理结构的限制。
- 注:LBA地址是扇区数组的下标;在使用LBA地址进行磁盘访问时,LBA地址指向磁盘的一个逻辑扇区,即:LBA地址实际上是直接对扇区的索引,不是对数据块的索引。
- 既然我们将磁盘抽象出来,那么依旧需要存在一个把扇区以数组下标的方式表示转化为以CHS方式表示(扇区的抽象位置 -> 扇区的物理位置)
- 但是呢,OS觉得就是每次都只能读写512字节效率实在是太低了,所以就将I/O操作的最小单位设置为4KB
那么这样从抽象地址转化到具体的地址,要增加一步:LBA地址 * 8+(0,1,2,3,4,5,6,7)这样才能算出一个扇区在这个线性结构中的具体位置。
4.3 inode
Linux下文件的特点: 文件 = 属性 + 内容
肯定没问题的是,我们描述一个文件的属性,肯定是使用一个结构体,而且是一个统一的结构体(那么文件属性的大小就是确定的,是一个固定的值)
但是,文件的内容完全是随机的,根本就没有一个固定的大小。
所以,Linux在存储文件方面采用了属性和内容分开存储的方式
我们可以很明显的看到,在这个结构体中并没有文件名,在OS内部我们不用文件名来标识文件,我们采用inode编号来唯一标识该文件。
ll -i :显示文件inode编号
4.4 分区与分组
我们一个磁盘一般来说都是512GB和1TB的大容量的,直接要管理这么大一块的内存空间显然是非常困难的,所以我们可以采用一下分治的思想,将空间划分为一小块,一小块的,然后将管理逻辑复制到每一个小块上。
4.5.这10GB中具体的管理模式
4.5.1 inode Table(i节点表)
前文提到了inode 是一个存储文件属性的结构体,那么inode table就是一块存储inode的数组空间。
4.5.2 inode Bitmap(inode位图)
inode Bitmap 是一个对位图的应用,每一个比特位就对应这inode Table 里的数组下标,用0/1来标识,该块的数组下标的内存是否被使用。
4.5.3 Data Blocks (数据区)
Data Block 以4KB为基本大小的数组,用来存放文件的内容。
4.5.4 blocks Bitmap(块位图)
blocks Bitmap也是对位图的应用,每一个比特位于Data Blocks的数组下标一 一对应,用来表示这块内存是否被使用。
4.5.5 GDB (Group Descriptor Table)
- 块组描述符:是对文件系统中所有块组进行管理的数据结构,每个块组在GDT中都有一个对应的条目,这个条目包含了块组的关键信息,如:inode表、数据块、inode位图、块位图的位置。
- GDT是一个全局的数据结构,每个块组中并不包含一个单独的GDT完整副本,通常只存储在文件系统中块组0,它描述了文件系统中所有块组的信息。
4.5.6 SB (Super Block)(超级块)
- 超级块:是文件系统中一个全局的数据结构,即:对整个文件系统进行管理的数据结构,存放整个文件系统的结构信息,如:block、inode的数量,未使用用的block、inode的数量,最近一次挂载的时间,最近写入数据的时间等其他与文件系统相关的信息
- 超级块的位置:一个文件系统,对应一个Super Block,通常在块组0中内保存着,为了提高文件系统的可靠性和容错性,会在个别块组内且存储Super Block的副本。(就例如,按照千分之一的概率来存放Super Block ,每一千个存放Block Group 中有一个Super Block)
4.5.6 Boot Block
Boot Block:只存在0号盘面、0号磁道、1号扇区中,即:分组0前,其作用是辅助开机,如:引导OS启动、检测文件系统状态、加载其他引导程序等。
4.5.7 Block Group
Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。政府管理各区的例子。
4.5.8 inode Table 内存储的文件内容,怎么和Data Block 内存储的文件
在结构体inode内部有一个 int block[15]的数组用来记录Data Block 数组中的数组下标。
在block[0,12]中的每一个位置记录的就是Data Block数组中的下标,记录的那个数组块,存储的也是文件内容。
很明显,如果每一个Block数组只能记录一个4KB的数据块,那一个文件能够存储的空间也不大。但是,由于属性的大小是固定的,我们也不好对数组进行扩容。
Block[12,14]这两块空间指向的Data Block中的4KB数据块中存储的数据不是文件内容,而是其他的4KB空间(这些4KB空间中存储的是文件内容)----- 这样就造成了类似于二级索引的结果。
而Block[15]这块空间则是采用三级索引,指向的4KB空间中存储的是Data Block 数组的下标,而这些数组下标的4KB空间,内部存的其他的Data Block 数组的下标,而这些数组下标所指向的空间才是存储着文件内容
5 文件名和目录
文件是不是一定会存在一个目录里面?----- 那是肯定的
那么目录是不是也是一个文件?---- 是的,目录也是一个文件
那么目录这个文件中存储的文件内容是什么呢?
5.1 目录中存储的文件内容
直接给出结论:目录中存放的内容就是文件名与文件inode的映射关系
5.2 重谈文件的增删改
对于文件的增删改操作,最开始都是要先归结于查,得先找到文件,才能对文件进行操作吧!
5.2.1 在文件系统中如何找到文件(即利用inode去找到文件的流程)
- OS一开始都会给每一个分组都会记录一个起始inode编号,利用这个起始inode编号与目标inode进行对比(具体方法就是:每一个分组内的文件数是已知的,通过起始inode编号和文件数得出一个范围,在这个范围里进行比较),确定自己在哪一个分组。
- 根据自己查找到文件的目的,即对文件进行增删改中的哪一项?在决定是去访问Block Group中的哪一块区域。
- 删除文件:直接访问inode Bitmap,找到对应文件的比特位(将文件inode编号减去分组起始inode编号,得出该文件在这个inode Bitmap中对应哪一个比特位)直接将这个比特位置为0.不用去管Data Block 中的文件内容,等待下次要用到的时候直接覆盖式写入就行了。
- 新建文件:首先,就得先访问inode位图,找到合适的(没有被使用的inode),再在i节点表找到对应的inode的节点,填上对应的文件属性,再去块位图找到合适的数据区的4KB储存块,建立链接,再写入数据,最后在目录里面建立inode编号与文件名的映射关系。
- 修改文件:找到目标inode,找到对应数据块,修改文件,修改inode内部的文件属性,
5.3 路径
我们之前提到了inode实在分组里面是唯一的,但是,在分区中inode是不唯一的,所以,我们如何在查找文件的时候通过文件名,来准确得出那个文件是我们需要的。
5.3.1 如何在整个OS中,通过文件名找到目标文件
我们已知的是目标文件的文件名和他的路径,所以,当我们查找到一个文件的时候,我们都通过路径去逆向的查找,在目录xzy中查找file-operating目录的inode编号,但是此时目录xzy的inode编号未知,所以在home目录查找xzy目录的编号,最终到达根目录的时候(根目录的inode编号是已知的),最后回溯一下,这样就可以得到目标文件的inode了
5.4 分区
你看这就是,我电脑下的两大分区,C盘和D盘
df -h 查看Linux系统下的分区
5.4.1 格式化
向我们对磁盘的操作中就有格式化这种操作,其实上就是清空磁盘中的内容,为磁盘装入全新的文件管理系统。 (每个不同的分区可以装不同的EXT文件系统)
5.4.2 分区进行"挂载"
- 前提:一个写入文件系统的分区,要能被Linux使用,必须要把这个具有文件系统的分区进行"挂载"。
- 挂载:将一个文件系统所对应的分区,挂载到指定的目录下。使得用户可以通过访问指定的目录,实现访问分区下的目录或文件。
通过解析文件路径(字符串前缀匹配),可以确定哪个目录是文件路径的一部分,从而推断出文件存储在哪个分区上。
挂载的本质:将存储设备上的文件系统,与文件系统(Super Block)中的某个目录(挂载点,dentry)建立关联关系,使得用户可以通过访问挂载点目录来间接访问文件系统上的所有数据。
在这个过程中,Super Block提供了文件系统的全局信息,dentry通过目录下缓存机制来加速文件名的查找,它提供了文件名到inode的快速映射,使得用户可以通过文件名快速访问文件数据。
在这里我就简单的将挂载认为是,为了让分区也能得以区分,把他们放在不同的目录下。
- 点赞
- 收藏
- 关注作者
评论(0)