[Linux] 详析 Linux磁盘文件管理系统、文件inode以及 软硬连接
内存文件只是操作系统中所有文件的一小部分, 绝大部分的文件都是处于未打开的状态的
. 这些文件一般都静静的在磁盘中存储着, 所以也被称为**磁盘文件
**磁盘相关信息
磁盘的物理结构
磁盘盘片
, 悬在盘片上的像针一样的东西叫磁头
, 磁盘中间的部分叫主轴
, 磁头链接着磁头臂
, 磁头臂被一个传动轴
连接着:盘片旋转
, 传动轴则可以让磁头臂左右摆动
, 即 磁盘内部的机械结构是类似这样运动的:磁盘的存储结构
数据都在盘片上存储着, 而磁头负责从盘片上读取或向盘片上写入数据
**-
盘片是怎么存储数据的?
其实光滑的
盘片上可以看作有无数个同心圆
, 图片表示就类似这样:不过这些
圆在盘片上被称为磁道
, 而每个磁道又会被分为许多的的扇区
:==这只是抽象图, 并不确切表示盘片中磁道和扇区的数量==
数据就在这些磁道中以二进制的形式存储着
并且, 每条磁道都有自己的编号,
最外层磁道的编号为0
; 每条磁道上的每块扇区也有自己的编号,每块扇区的大小一般为512字节
每条磁道的扇区数是相同的, 每块扇区的大小也是相同的, 这也就意味着每条磁道的可存储数据的大小其实也是相同的
很明显
越外层的磁道越长, 长磁道与短磁道可存储数据的大小也是相同的吗?是的
, 每条磁道存储数据的密度不相同 -
磁盘是通过什么来读取或写入数据的呢?
既然数据在磁道中存储着, 那么就肯定要从磁道中读取数据 或 向磁道中写入数据
那么磁盘是通过什么来进行此操作的呢?
没错, 就是
通过磁头
盘片的旋转结合磁头的左右摆动, 可以使磁头悬浮于盘片的任意位置, 也就是说磁头可以通过一定的操作在盘片的任意位置读取数据或写入数据
盘片在高速旋转时不能接触到任何物体, 不然盘片就会发生损伤
所以磁头一般是悬浮在盘片上下的
磁头通过感应盘片上的磁场变化来读取数据, 通过改变盘片上的磁场来写入数据
(磁场分为NS, 正好对应二进制的01)
==磁盘中可能存在多个水平但上下放置的盘片, 那么这些盘片必定会存在相同半径的磁道同处于同一个圆柱面上, 这个圆柱面我们就称之为磁柱(Cylinder):==
磁柱是Cylinder, 磁头是Head, 扇区是Sector
, 当我们知道这三个结构的编号, 就能在磁盘中定位到一个指定的扇区
知道磁柱的编号就确定了
磁道的编号
, 磁头可以确定哪个盘面
, 扇区编号可以知道扇区在磁道中的位置
, 知道这三个编号, 就能确定到某个盘片上的某条磁道上的某块扇区, 也就知道了当前访问的扇区
这样的地址被称为**
CHS地址
**, 用这样的方法, 可以找到磁盘中每个单元的确切位置 -
磁盘存储结构的逻辑抽象
经过上面介绍了磁盘的物理结构 和 存储结构之后, 其实数据就是存储在一个一个圆圈上的. 也可以看作是线性存储的
毕竟圆圈是可以拉直的
就像磁带一样, 卷在一起的时候可以看作是数据存储在一个一个圆圈上, 当把磁带拉直也可以看作数据是存储在一条直线上. 不管是卷起来还是拉直, 其实都没有损坏磁带, 更没有损坏磁带上的数据.
那么其实, 磁盘上的盘片上的磁带也可以抽象成这样的直线的、线性的形式,
作为一个数组被管理起来
即, 磁盘上的所有盘片的所有磁道都可以抽象成一个线性的数组然后整合起来:
所有的扇区被整合成一个数组, 每个下标对应着一个扇区, 即可以根据数组的下标来定位到磁盘中的某个扇区, 这里的下标被叫做
LBA逻辑块地址
通过LBA是可以计算出相对应的CHS的
, 比如:已知磁盘上每个盘片上有100条磁道, 每条磁道20个扇区, 当我们获得一个LBA是9231. 我们就可以根据9231来计算出对应的CHS:
9231表示第9231个扇区, 每个盘片100个磁道, 每个磁道20个扇区, 即每个盘片2000个扇区:
9231/2000 -> 第5个面盘上(Head), 9231%2000 = 第1231个扇区, 1231/20 -> 第62条磁道上(C), 1231%20 = 11个扇区(S)
即,
LBA=9231 对应的CHS为 62:5:11
文件系统
一般来说操作系统与磁盘进行I/O操作的基本单位是4KB
. 即, 实际上对操作系统来说, 还可以将抽象出来的一个单元对应一个扇区的数组, 进一步划分一下, 以8个单元为一个大的单元
, 即 8*512B = 4KB, 以便于操作系统与磁盘实际进行I/O操作
为什么不将操作系统与磁盘的I/O操作的基本单位 直接设置为一个扇区, 而是固定设置成4KB呢?
对大多数的磁盘
来说, 一个扇区一个扇区的IO太慢了, 设置成4KB是为了提高IO效率
不让软件设计和硬件具有强相关性, 在此, 就是不让操作系统和磁盘之间在IO方面具有强相关性
因为, 如果操作系统与磁盘的IO单位是按照当前磁盘设计的话, 那么针对不同型号、扇区大小不同的磁盘时, 操作系统就需要做出相应的修改, 这个过程是复杂且繁琐的. 而如果将操作系统与硬件的IO基本单位设置成一个固定的值, 就不需要根据硬件去作出修改. 这也就是软件设计中常说的,
解耦合
1,073,741,824
和 134,217,728
, 即使后者比前者小了一个数量级, 但依旧是千万级的会针对磁盘的不同分区, 将分区分为不同的组, 再针对组进行管理.
对于像组, 这种属性基本相同的结构来说, 管理好一个组, 就可以管理好其他所有的组
操作系统会将分区细分为向上面那样的组, 还会分出一个 Boot Block区域.
Boot Block
Super Block
Group Descriptor Table
Block Bitmap
inode Bitmap
indoe Table
. 最后的这个 Data blocks
则表示文件内容组的属性
Data blocks
Data blocks
, 其实就是组内存储文件内容的一个区域, 此区域以 块 为单位, 每块的大小为4KB
. 占一个组的绝大部分内容即使文件内容并没有达到4KB的内容, 此文件还是会占用一个4KB的块, 此块独属于此文件, 其他文件不能使用
inode Table
Linux系统中, 存在一个 inode结构体, 此结构体存储的是磁盘文件的各种属性
.ll
或者 stat
可以查看多个或单个文件的属性:stat
查看单个文件的详细属性时, 可以看到 一个文件拥有非常多的属性:File
Size
Blocks
IO Block
Device
Inode
Links
Access
Uid
Gid
等file 文件名
, 还有Access 权限
Blocks
IO Block
Inode
Links
等inode是一个结构体, 存储着文件的所有属性
就可以了一个叫 inode的属性, 是一个整型值, 此值表示某文件在操作系统中的唯一的一个编号
stat
命令输出的一个叫 Inode
的属性, 也可以通过 ll -i
查看:inode
具体是什么东西, 那么再看inode Table
inode Table 就是组内用来存储 文件inode结构体的一个表格、数组, inode Table的每个单位存储一个inode结构体
inode结构体的大小为 128字节, 那么 inode Table 的单位大小就是 128字节
inode Table
结构示意
inode
结构体存储着 操作系统层面 文件的所有属性, 但是其中是没有存储文件名的
文件名在Linux操作系统中是属性吗?是的, 但是
inode
中并没有存储文件名这其实意味着,
在Linux底层层面, 系统是不认识文件名的, inode结构体中存储的inode编号 是操作系统底层对文件的唯一实际标识
inode Bitmap
inode Bitmap 就是描述 inode Table 占用情况的位图
Block Bitmap
Group Descriptor Table
inode起始编号
inode Table被占用了多少、还剩多少
Data Blocks 中占用了多少、还剩多少
此Group的实际大小是多少
……
GDT
Super Block
Super Block 超级块
, 其实并不独属于其所在组此分区在磁盘中的实际区域
分区内的分组情况
分区所使用的文件系统格式
……
为什么 Super Block 要存储在组内?
为什么不像Boot Block一样, 单独存储在组外分区内呢?
为了提供备份
可能正在维护的Super Block会发生损坏?
就像Windows中, 如果操作系统正在写入数据的时候突然关机断电, 那么在下次开启的时候很有可能会触发一个询问:
上次系统非正常关机, 怎么怎么样, 是否恢复启动?
如果分区中只有一个Super Block这样的结构, 那么是无法恢复的
并不是 所有组内都会存储Super Block, 而是一部分
inode 怎么与 其描述文件的Data Blocks部分 联系起来
-
一部分存储文件内容在 Data Blocks中的存储位置, 比如
[0, 11] 这些位置直接保存文件内容对应的Data Blocks对应的编号
-
如果文件内容很大, 一部分描述不完时, 还会有另一部分内容. [12, 14] 这部分内容会保存某块 Data Block
但是这块
Data Block中保存的并不是文件内容, 而是像 [0, 11] 那样 保存此文件内容在Data Blocks中对应的其他编号
这是一种
二级映射
创建和删除文件 的执行流程
文件系统中的 目录
需要的是 x执行权限
:需要的是 w写权限
:需要的是 r读权限
:文件的w和r权限实际上是对 文件内容的读写权限, 也就是说 目录文件的文件内容 其实就是目录下的文件
准确一点, 应该说 目录文件的文件内容, 其实是 目录下文件的 文件名 和 inode编号 之间的映射
同一目录下, 是否可以存在多个相同的文件名?
不可以,
同一目录下的文件名是唯一的, 也就是说, 同一目录下一个文件名只对应一个inode编号
创建文件, 操作系统做了什么?
- 创建文件的inode, 并将inode和内容分别存储至 组的inode Table 和 Data Blocks中, 并修改inode Bitmap 和 Block Bitmap 的相应内容
- 找到当前用户所处的目录, 再根据当前目录的inode找到目录文件在 Data Blocks中的数据块
- 将 创建的文件的文件名和inode编号, 存储到目录文件在Data Blocks的数据块中, 并修改 相关的 Block Bitmap
*删除文件, 操作系统又做了什么?
操作系统删除文件, 并不会真的将文件 存储在Data Blocks的内容 和 inode Table的属性删除, 而是只将 inode Bitmap 和 Block Bitmap 这两个位图中有关删除文件的位置设置为0. 再将目录文件的 Block Bitmap 的相关位置设置为0. 就完成了文件的删除
inode Bitmap 和 Block Bitmap 这两个位图, 描述的是磁盘中实际的存储块的使用情况. 如果这两个位图中相关的位置为0, 那么在操作系统看来, 相应的 inode Table 和 Data Blocks 存储块中就没有存放有效数据, 相应的位置都是可以直接使用的
操作系统删除文件, 并不会真的将数据从磁盘中清除.
那么当一个公司的服务器需要更换磁盘时, 一般会对磁盘中的数据进行擦除. (以往可能会使用物理损毁)
软硬连接
硬连接
硬连接, 就可以将不同的文件名, 映射到同一个inode编号上
ln 原文件名 新创建的硬链接文件名
这两个就是同一个文件, 只是文件名不同, 操作系统没有在磁盘中再创建一个内容相同的文件
, 并不会多占用一份磁盘空间. 其实就只是在目录的Data Blocks数据块中, 添加的了一个映射关系, 并没有其他的数据,ln
之后, 此文件inode编号除了被两个不同的文件名映射之外, 还存在另外一个变化:表示权限一栏的后的数字, 从 1 变为了 2
这个数字是inode结构体记录的此文件的硬连接数
, 只要磁盘中存在一个硬连接到此inode的文件, 这个计数就会+1其实文件在操作系统中只看做是一个 inode结构体 + 文件内容 就可以了
, 文件名什么的只是一个供用户查看、记忆的没有什么重要的实际意义的马甲, 而文件名映射的inode编号才是那个最重要的指向一个实际文件的数据. 也就是说, 其实 inode编号 就像是一个 “指针”硬连接数有什么用
呢?硬连接有什么用?
./
作为前缀软连接
ln
, 只不过 需要添加一个选项 -s
, 可以看做soft , 即 ln -s
表示建立软连接:软连接创建的新文件的内容, 其实是所连接的原文件的所在路径
软硬连接都可以用, unlink 命令来取消连接
作者: 哈米d1ch 发表日期:2023 年 3 月 29 日