【Linux操作系统】简学深悟启示录:Ext系列文件系统
文章目录
- 1.文件系统概念引入
- 2.理解硬件
- 2.1 磁盘物理结构
- 2.2 磁盘存储结构
- 2.3 磁盘逻辑结构
- 3.文件系统
- 3.1 inode Table(文件属性)
- 3.2 Data blocks(文件内容)
- 3.3 inode 和 Data blocks 映射
- 3.4 其他小块
- 4.目录
- 4.1 目录与文件名
- 4.2 路径解析
- 4.3 路径缓存
- 5.软硬连接
- 5.1 硬连接
- 5.2 软连接
- 希望读者们多多三连支持
- 小编会继续更新
- 你们的鼓励就是我前进的动力!
1.文件系统概念引入
我们知道,文件=内容+属性
, 那么 磁盘中存储的的文件=存文件的内容+存文件的属性
,文件的内容就是数据块,文件的属性就是 inode
,是分开存储的
2.理解硬件
2.1 磁盘物理结构
磁盘相对于目前市面上常见的固态硬盘来说,单位容量成本更低和数据长期存储稳定性更强,遇到物理损坏时被恢复的概率也更高,尤其在大容量存储场景下优势显著。因此常被企业进行大量存储使用
磁头是一面一个,磁头和磁盘不进行接触,通过 N
、S
极来模拟信号 0
、1
,也就是高频低频,磁头在磁盘的半径上移动,磁盘中间内置马达可以转动,以此能够寻找特定的区域,通常相关的内容会被存储同一片区域内,因为磁头运动越少,效率越高;运动越多,效率越低
2.2 磁盘存储结构
磁盘上有很多个同心圆,每一个圆是一条磁道,每条磁道上有很多个小扇形,即扇区,每个扇区大约 512
字节(4 KB
),我们可以把磁盘看作由无数个扇区构成的存储介质,即扇区是磁盘被访问的最基础单元
🤔那么我们该如何定位,哪一面,哪一个磁道,哪一个扇区?
可以使用 CHS
寻址法
扇区是从磁盘读出和写入信息的最小单位,通常大小为 512
字节
- 磁头(
head
)数:每个盘片一般有上下两面,分别对应1
个磁头,共2
个磁头。比如:2
个磁盘片的硬盘,有4
个磁头,编号为0
、1
、2
、3
- 磁道(
track
)数:磁道是从盘片外圈往内圈编号0
磁道,1
磁道…,靠近主轴的同心圆用于停靠磁头,不存储数据 - 柱面(
cylinder
)数:磁道构成柱面,数量上等同于磁道个数 - 扇区(
sector
)数:每个磁道都被切分成很多扇形区域,每道的扇区数量相同 - 圆盘(
platter
)数:就是盘片的数量
磁盘容量=磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数
,细节:传动臂上的磁头是共进退的(这点比较重要,后面会说明)
✏️举个例子:
假设每个盘面 2w
个扇区,每个盘面 50
条磁道,每条磁道 400
个扇区,问 28888
扇区的位置?
- 先定位磁头:
28888
/20000
=1
、28888
%20000
=8888
- 确定磁头要访问哪⼀个柱面(磁道):
8888
/400
=22
- 定位⼀个扇区:
8888
%400
=88
因此可以确定编号 28888
的扇区在 C
:1
号磁头、H
:22
号磁道、S
:88
号扇区
2.3 磁盘逻辑结构
事实上我们通常将一条条磁道链接起来,形成一个逻辑结构
这样每一个扇区,就有了一个线性地址(其实就是数组下标),这种地址叫做 LBA
整体来看,同一盘面上的磁道都首尾相连,然后从整个柱面来看,磁盘整体是由“柱面”卷起来的
将整个柱面展开就是磁盘的容量了
然后就能逻辑成我们常用的线性结构
3.文件系统
在 Linux
系统中,最常见的是 ext2
系列的文件系统。其早期版本为 ext2
,后来又发展出 ext3
和 ext4
。ext3
和 ext4
虽然对 ext2
进行了增强,但是其核心设计并没有发生变化,我们仍是以较老的 ext2
作为演示对象
ext2
文件系统将整个分区划分成若干个同样大小的块组 (Block Group
),如下图所示。只要能管理⼀个分区就能管理所有分区,也就能管理所有磁盘文件
将整个逻辑化的文件系统,可以分为多个 Partition
分区,不同分区由不同的文件系统管理,即电脑里的磁盘 C
、磁盘 D
之类的,每个区又能分为好几个块组,每个块组又能往下细分各个小板块
前面我们提到文件的内容属性是分开存放的,将对这两部分进行重点解析
3.1 inode Table(文件属性)
使用 ls -li
命令能够看到第一列的数字就是 inode
值,那么这种数值到底是什么呢?
查看操作系统源文件我们可以简单将其大致结构写出,发现 inode
就是一个包含文件属性的结构体,那么 inode Table
就是一个 inode
结构体集合的表,注意文件属性并不包含文件名
由此可知,标识文件用的是 inode
编号,在同一分区下,一个文件一个 inode
,是文件的唯一标识,不可能相等;在不同分区下,inode
编号可以完全相同,但它们属于不同的文件系统管理,彼此没有关联,例如,/dev/sda1
分区中的 inode 100
和 /dev/sda2
分区中的 inode 100
,虽然编号相同,但指向的是完全不同的文件元数据
3.2 Data blocks(文件内容)
Data blocks
里面存放的是文件的内容
其实硬盘是典型的块设备,操作系统读取硬盘数据的时候,其实是不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个块( block
)。
硬盘的每个分区是被划分为一个个的块。一个块的大小是由格式化的时候确定的,并且不可以更改,最常见的是 4KB
,即连续八个扇区组成一个块。块是文件存取的最小单位
Boot Block
是用于保存例如每个分区多大,有几个分区,起始地址等初始信息的,一般在 0
号磁头的一号扇区上
3.3 inode 和 Data blocks 映射
在 inode
结构体中的 blocks
数组,作为指针数组,为的就是方便查找文件内容
直到一个文件的 inode
之后,首先在 inode Table
中找到 blocks
数组,一般该指针数组大小为 15
,前 12
个为直接块指针,直接指向该文件的磁盘内容,后面的指针为树状结构的指针,类似 文件-文件-内容
的结构,因为这种结构就不怕 blocks
太小无法存下所有块编号的问题
3.4 其他小块
- Super Block
存放文件系统本身的结构信息,描述整个分区的文件系统信息。记录的信息主要有:bolck
和 inode
的总量,未使用的 block
和 inode
的数量,一个 block
和 inode
的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block
的信息被破坏,可以说整个文件系统结构就被破坏了
超级块在每个块组的开头都有一份拷贝(第一个块组必须有,后面的块组可以没有)。 为了保证文件系统在磁盘部分扇区出现物理问题的情况下还能正常工作,就必须保证文件系统的 super block
信息在这种情况下也能正常访问。所以一个文件系统的 super block
会在多个 block group
中进行备份,这些 super block
区域的数据保持一致
- Group Descriptor Table
块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储一个块组的描述信息,如在这个块组中从哪里开始是 inode Table
,从哪里开始是 DataBlocks
,空闲的 inode
和数据块还有多少个等等。块组描述符在每个块组的开头都有一份拷贝
- Block Bitmap
Block Bitmap
中记录着 Data Block
中哪个数据块已经被占用,哪个数据块没有被占用
- Inode Bitmap
每个 bit
表示一个 inode
是否空闲可用
🤔知道inode号的情况下,在指定分区,请解释:对文件进行增、删、查、改是在
做什么?
4.目录
4.1 目录与文件名
正常来说,目录也是文件,也有他自己的 inode
,只不过他存放的内容是该目录下文件名和 inode
的映射关系
所以,访问文件,必须打开当前目录,根据文件名,获得对应的 inode
号,然后进行文件访问,访问文件必须要知道当前工作目录,本质是必须能打开当前工作目录文件,查看目录文件的内容!
4.2 路径解析
问题: 打开当前工作目录文件,查看当前工作目录文件的内容?当前工作目录不也是文件吗?我们访问当前工作目录不也是只知道当前工作目录的文件名吗?要访问它,不也得知道当前工作目录的 inode
吗?
答案: 所以类似递归,需要把路径中所有的目录全部解析,出口是 /
根目录,从根目录开始不断向下寻找,获取该目录下文件名和 inode
的映射关系,最终找到自己需要的文件
而实际上,任何文件,都有路径,访问目标文件,比如:/home/zzh/code/test/test.c
,都要从根目录开始,依次打开每一个目录,根据目录名,依次访问每个目录下指定的目录,直到访问到 test.c
,这个过程叫做 Linux
路径解析
所以,我们知道了:访问文件必须要有目录+文件名=路径的原因,根目录固定文件名, inode
号,无需查找,系统开机之后就必须知道
可是路径谁提供?
- 你访问文件,都是指令/工具访问,本质是进程访问,进程有
CWD
!进程提供路径。 - 你
open
文件,提供了路径
4.3 路径缓存
访问任何文件,都要从/目录开始进行路径解析?原则上是,但是这样太慢,所以 Linux
会缓存历史路径结构
Linux
中,在内核中维护树状路径结构的内核结构体叫做: struct dentry
每个文件其实都要有对应的 dentry
结构,包括普通文件。这样所有被打开的文件,就可以在内存中形成整个树形结构
- 整个树形节点也同时会隶属于
LRU
结构中,进行节点淘汰 - 整个树形节点也同时会隶属于
Hash
,方便快速查找 - 更重要的是,这个树形结构,整体构成了
Linux
的路径缓存结构,打开访问任何文件,都在先在这棵树下根据路径进行查找,找到就返回属性inode
和内容,没找到就从磁盘加载路径,添加dentry
结构,缓存新路径
5.软硬连接
5.1 硬连接
zzh@iv-ye51qmh4owxjd1uhrjzq:~/link$ ln test.txt test_hardlink.txt
zzh@iv-ye51qmh4owxjd1uhrjzq:~/link$ ls -li
total 0
413912 -rw-rw-r-- 2 zzh zzh 0 Sep 20 14:33 test_hardlink.txt
413912 -rw-rw-r-- 2 zzh zzh 0 Sep 20 14:33 test.txt
在查找文件的时候,表示上是用文件名,实际上是利用inode查找磁盘数据
ln test.txt test_hardlink.txt
表示让 test_hardlink.txt
指向和 test.txt
相同的磁盘数据,共享 inode
和数据,修改任意一个文件的内容,另一个文件会同步更新。因此硬连接也可以理解为取别名
这也表明该 inode
的连接数为 2
🔥值得注意的是: linux
系统不允许目录建立硬连接,目录内部的 .
和 ..
文件不是硬连接,是系统特殊设置的
5.2 软连接
zzh@iv-ye51qmh4owxjd1uhrjzq:~/link$ ln -s test.txt test_softlink.txt
zzh@iv-ye51qmh4owxjd1uhrjzq:~/link$ ls -li
total 0
413894 lrwxrwxrwx 1 zzh zzh 8 Sep 20 15:15 test_softlink.txt -> test.txt
409692 -rw-rw-r-- 1 zzh zzh 0 Sep 20 15:12 test.txt
硬链接是通过 inode
引用另外⼀个文件,软链接是通过名字引用另外一个文件,但实际上,新的文件和被引用的文件的 inode
不同,应用常见上可以想象成一个快捷方式。已使用 unlink test_softlink.txt
取消软连接