目录
1.磁盘文件
在计算机中,没有被打开的文件都是静静的躺在外存(磁盘)中,当需要对文件进行操作时,会通过 inode
对文件进行访问
通过以下指令查看当前目录中文件的详细信息及 inode
值
ll -i
如同 pid
与进程的唯一对应性一样,inode
与文件也是唯一对应的(未被硬链接的情况下),可以通过 inode
访问文件在磁盘中的详细信息
2.磁盘概念
现在市面上的磁盘主要分为 机械硬盘 和 固态硬盘,前者读取速度慢,但便宜、稳定;后者读取速度快,但价格高昂且数据易损,两者各有其应用场景,本文主要介绍的是 机械硬盘
2.1基本结构
机械硬盘 的结构主要包括以下几种:
- 盘片:一片两面,每一面都可以存储数据,有一摞盘片
- 磁头:一面配备一个磁头,专门用于读取盘面中的数据
- 主轴:用于控制整块盘的转动
- 音圈马达:控制磁头的进退
- 磁头臂:链接磁头与音圈马达
- 伺服电路板:控制读取数据的流向及各种结构的运行
2.2数据存储
数据是以 0
和 1
的方式进行存储的,常见的存储介质有:强信号与弱信号、高电平与低电平、波峰与波谷、南极与北极 等,而盘面上比较适合的是 南极与北极
机械硬盘 不能在其运行时随意移动,因为角度的偏转也有可能导致发生摩擦,造成数据丢失,更不能用力拍打 机械硬盘
在盘面设计上,一个盘面被切割若干个扇区,单个扇区大小为 512 字节(或者 4 kb),这些扇区用来存储数据,同一半径中的所有扇区组成扇面;而半径相同的扇区组成磁道(柱面)
我们可以先根据磁头(head)确定盘面,再根据半径定位磁道(柱面 cylinder),最后根据块号确定扇区(sector)
这种寻址方法称为 CHS 定位法,是机械设备查找具体扇区时的方法
虽然 CHS
定位法很妙,但它太依赖于具体硬件信息了,假设其中的硬件参数有所不同,那么 OS
就得使用另一套 CHS
定位法,于是为了做到 解耦,OS
使用的并非 CHS
定位法进行文件定位,而是采用 LBA
逻辑地址块进行寻址
将磁道拉长,会得到一串线性空间(数组),其中的每个单位(扇区)为 512
字节(或者 4 kb
)
现在 OS 想访问具体的扇区时,只需通过 起始扇区的地址 + 偏移量 就可以获取 LBA 地址,然后通过特定手段转为 CHS 地址,交给外设进行访问即可 LBA和CHS转换
因此对于外设中文件的管理,经过 先描述,再组织 后,变成了对数组的管理,这个数据就是 task_struct 中的 struct block
最后我们就能理解为什么 IO 的基本单位是 4 kb 了,因为直接读取一个数据块(4 kb),这样可以提高 IO 效率(内存对齐)即使造成内存浪费也只会有最后一个内存浪费
3磁盘信息
系统在分区后,需要对区块进行格式化
不同的文件系统在格式化时写入的数据是不同的,这里讨论的是 EXT
文件系统
-
磁盘分区后,分组、填写系统属性是
OS
做的事 -
为了使分区能被正常使用,需要对分区进行格式化
-
分区格式化:
OS
向分区写入文件系统的管理属性信息 -
在具体分区内,还可以细分为 块组
由 块组 构成的线性空间亦可称为 组线 (代表一个 分区)
struct part
{
struct part group[100]; //分为100个块组
int lba_start; //起始与结束位置
int lba_end;
//……
}
将现有资源再分配后,可以 最大化利用资源,避免造成浪费及拖慢效率
块组(Block Group
)是本文的重点内容
3.1块组信息
块组 是由 分区 细分出的产物,它与分区的关系如图所示:
其中, Boot Block
是 启动块,大小固定为 1 kb
,在每一条 组线 前都有此 块组,它用来 存储分区信息和系统启动,属于被保护的内容,不允许用户私自修改
至于其他 块组,它们有着统一的格式,具体内容如图所示:
其中一个文件对应一个 inode
,而 inode
中存储了该文件的所有属性,包括所使用的数组块信息,因为文件很多,所以需要 先描述,再组织,即通过 inode Table
对 inode
进行管理
注意:
- inode 属性中并不包含文件名,文件名只是给用户用的
- 目录文件也有 inode,目录中的数据块保存的是该目录下的 文件名 和 inode 编号对应的映射关系,而且在此目录内,文件名和 inode 互为 key 值
- inode 确定分组,inode 值只在一个分区内有效,不能跨分区
4.文件操作
4.1文件创建
创建一个文件的步骤如下:
- 申请一个空闲的
inode
,将文件信息记录至inode
属性中 - 寻找空闲的数据块(
Data block
),将数据块信息填入inode
中的磁盘分布区 - 添加文件名至当前目录文件的
Data block
中,同时将文件名和inode
之中的属性链接起来
注意: 每使用一个 inode
和一个 Data block
,需要把它们对应位图中的信息改为已占用
4.2文件访问
文件创建后,如何根据 inode
访问文件呢?
- 找到文件的
inode
编号,在目录分组中查找 - 通过
inode
和Data block
的映射关系,找到文件的数据块,并加载至内存中
这也就解释了为什么在 file
对象中会存在 inode
信息,因为它与 fd
一样重要
4.3对文件增删查改
文件创建后,如何删除?删除并不是真删除,而是将 inode Bitmap 和 Block Bitmap 中位图信息进行修改即可(只要访问不到,就是删除)
根据文件名找到 inode 编号
再根据 inode 属性中的映射关系,设置 Block Bitmap 对应的比特位,设置为 0 (删内容)
最后根据 inode 编号设置 inode Bitmap 中对应的比特位为 0 (删属性)
将位图信息置为 0 后,创建新文件时,系统可以直接使用
至于文件的查找与修改,通过 inode 修改其内部属性即可
注意: inode 和 Data blcok 可能存在失衡的情况
一直创建空文件,导致 inode 满载,而 Data block 空余很多
不断往同一个文件中写入数据,导致 Data block 被占用,后续创建文件时,inode 无法再分配到 Data block
4.4大文件存储
单个数据块大小有限(4 kb
),如何做到一个数据块存储大量数据?
答案是 套娃,Data block
中存储其他 Data block
信息,此时称为多级索引,可以做到一个数据块中存储大量数据
总结:
文件部分复盘结束,这章确实很难理解,我第一遍稀里糊涂,第二遍马马虎虎,还是要多复盘,多整理。