1.磁盘文件
上一篇博客我们提到的都是已经打开的文件,那么没有打开的文件都是静静的躺在外存(磁盘)里面,当需要对文件进行访问时,会通过inode值对文件进行访问。
通过以下指令查看当前目录中文件的详细信息及 inode 值。
cpp
ll -i

第一个数就是inode值。
除了这个指令还有一个可以看到文件的更多信息。

磁盘文件是如何进行管理的?
- 磁盘文件的管理类似于菜鸟驿站,其中的包裹就像待访问的文件,而 inode 就是取件码
- 得益于这种规范化的存储模式,我们可以做到对文件的快速定位、快速读取和快速写入

2.磁盘的概念
现在市面上的磁盘主要分为 机械硬盘 和 固态硬盘,前者读取速度慢,但便宜、稳定;后者读取速度快,但价格高昂且数据易损,两者各有其应用场景,本文主要介绍的是 机械硬盘。

左边的就是机械磁盘。
2.1 磁盘的结构
机械硬盘 的结构主要包括以下几种:
- 盘片:一片两面,每一面都可以存储数据,有一摞盘片
- 磁头:一面配备一个磁头,专门用于读取盘面中的数据
- 主轴:用于控制整块盘的转动
- 音圈马达:控制磁头的进退
- 磁头臂:链接磁头与音圈马达
- 伺服电路板:控制读取数据的流向及各种结构的运行
- ......

2.2 数据的存储
当磁头移到指定位置时,对该区域的数据进行写入和读取。
ps:磁头与磁盘是不会直接接触的,而是保持一定距离,不会损坏磁盘。机械硬盘 不能在其运行时随意移动,因为角度的偏转也有可能导致发生摩擦,造成数据丢失,更不能用力拍打 机械硬盘
在盘面设计上,一个盘面被切割若干个扇区,单个扇区大小为 512 字节(或者 4 kb),这些扇区用来存储数据,同一半径中的所有扇区组成扇面 ;而半径相同的扇区组成磁道(柱面)。

CHS定位法:
将盘面分割为多个线性分区,通过下标 N 计算出 CHS 地址,然后进行文件访问。
假设一个扇区编号是28888,有20个磁面,一个磁面有40个磁道,一个磁道有66个扇区,那么就可以通过一个磁面就有2640个扇区,28888/(40*66)=10确定在第10个磁面,28888%2640=2488,2488/66=37确定在第37个磁道,2488%66=42确定在第46个扇区。
CHS定位根据磁道+磁头+扇区的定位方法。
LBA定位法:

将磁道拉长,会得到一串线性空间(数组),其中的每个单位(扇区)为 512 字节(或者 4 kb)
现在 OS 想访问具体的扇区时,只需通过 起始扇区的地址 + 偏移量 就可以获取 LBA 地址,然后通过特定手段转为 CHS 地址,交给外设进行访问即可 LBA和CHS转换。
3. 磁盘分区
在文件系统中,操作系统会使用一个结构体来记录一个分区的开始和结束
cpp
struct partion
{
int start;
int end;
}
在大多数计算机系统中,磁盘被分为多个分区,比如常见的 C 盘、D 盘等。这种分区方式对于操作系统的管理、存储设备的使用和数据的安全性等方面都具有重要意义。
3.1 分区的意义
磁盘空间的大小和复杂性使得不对其进行合理划分时,操作系统在管理和访问数据时的开销会非常大。为了提高效率和降低管理成本,操作系统会将磁盘空间划分成多个分区。这种做法借鉴了分治思想,类似于现实生活中的学校将不同专业的学生和老师分配到不同的学院,通过分配和划分,便于更高效的管理和资源利用。
3.2 分区的作用
1. 系统与数据分离,提升安全性
将操作系统安装在一个分区(如C盘),个人数据(文档、照片、视频)存放在其他分区。
当系统崩溃或需要重装时,只需格式化系统分区,数据分区的文件不会丢失,避免了"一损俱损"的风险。
2. 优化性能,提高读写效率
硬盘的读写速度在不同区域存在差异(外圈速度通常更快),可将常用程序或系统安装在速度较快的分区。
3. 便于管理和组织文件
可根据用途划分不同分区,例如:
C盘:系统盘(仅装操作系统和必要驱动)
D盘:软件盘(安装办公、娱乐等应用程序)
4. 隔离故障,降低风险
若某个分区因病毒、坏道等原因损坏,其他分区仍可正常使用,不会导致整个硬盘的数据全部丢失。
4.文件系统
在linux中的文件系统为ext4。

存储引导加载程序:Boot Block中存放的是boot loader(引导加载程序),大小是固定的,这段程序在开机启动时被加载,用于引导操作系统的启动过程。是系统启动的关键,Boot Block对于操作系统的启动至关重要。如果Boot Block中的数据有误或丢失,操作系统可能无法启动。
每一个分区里面都包含一个文件系统,里面的内容都一样,分别取管理一个一个的分区。
**1.Data Blocks:**存储文件内容的位置,里面就是一个一个的块,存储文件的内容,一般来说一块的大小是4kb,可以查看Block Bitmap的大小来查看有多少块,来决定占据了多少个扇形。
文件的存储就是以块单位来存储的,一个文件是5kb就占用2个块,第二个块就占用了1字节,哪怕一个文件的就占用几十kb,同样要给他分配一个块。
**2.inode Table:**inode是一个结构体,里面包含了单个文件的所有属性,一般来说是128个字节,inode Table数组里面包含了很多个inode。
cpp
struct inode
{
int size; // 文件的字节数:表示文件的大小,即文件包含的数据量。
mode_t mode; // 权限掩码
int creater; // 文件创建者
int time; // 文件的时间戳,ACM时间
...
int inode_number;// inode 编号
int datablocks[N];
}
datablock数组里面存放的就是该文件使用的块下标,如果一个文件的内容非常大,占用的块的个数很多的话,最后的几个下标会采取二三级索引的方式,也就是最后的几个下标指的块的内容不是文件内容,而是其他块的编号,这样就可以指向更多块,存储更多的内容,像多叉树一样,最后叶子节点才存放文件内容,这样子空间就变大了好多。

一块是4kb,存储的块数肯定不止两三块,方便理解。
ps:inode里面是没有文件名的!!!
**3.inode Bitmap:**一个位图,记录着inode的使用情况,bit位为1,表示该inode已被占用,为0表示没有被占用。
**4.Block Bitmap:**一个位图,表示Data Blocks里面块被占用的情况,1表示已被占用,0表示没有被占用。
5.Group Descriptor Table:块组描述符,描述块组属性信息,如块组的状态,位置等。
**6.Super Block:**存放文件系统本身的结构信息。

Super Block的信息被破坏,可以说整个文件系统就被破坏了,不会在每个组里面都存在,会在几个组(Block Group)里面存在,保证一个组里面损坏了可以去其他组里面查找。
格式化:

对一个盘的格式化的操作也就是对这个盘的文件系统进行重建,修改里面的数据,把盘里面文件的inode和指向文件的块全部都进行置为0。
删除:
为什么下载文件的时候非常慢,都是删除一个文件就非常快呢?就是因为只要拿到了这个文件的inode值,去inode Bitmap里面查看是否有效,有效的话,在inode Table里面拿到对应的块的编号,任何去Block Bitmap里面把对应的块的位置置为0就可以了,删除也就是支持覆盖。
5.进一步理解inode
inode里面包含了一个文件的属性。
cpp
struct inode {
int size; // 文件的字节数,即文件内容的大小
mode_t mode; // 文件的权限掩码,包括文件类型、权限等信息
int creater; // 文件的创建者(UID)
int time; // 文件的时间戳(如创建时间、修改时间等)
int inode_number; // inode 编号,每个文件或目录在文件系统中的唯一标识符
int datablocks[N]; // 数据块指针,指向文件内容所在的磁盘数据块,通常是直接指针、间接指针等
...
};
上面说了inode里面是没有包含文件名,说明操作系统是利用文件的inode来对文件进行操作的,为什么我们都是使用的文件名,操作系统就知道了对应的inode值了呢?
目录
首先找到,目录也是一个文件,也有自己的inode值,每个目录的里面存储的是它的属性和目录下的文件名和对应的inode值(目录项列表),里面包含
- 文件名(如 test.txt 、 myphoto.jpg )
- 对应的inode编号(如 12345 )
- 文件类型(是普通文件、目录还是设备文件等)
- 权限信息(简化版)
操作系统是会缓存一些重要目录和经常使用的inode值的,加快文件的查找速度。
假设路径:/home/user/test.txt
用 home 目录的inode编号(100)找到其数据块,里面有 user 目录项,获取 user 目录的inode编号(比如 200)。再用 user 目录的inode编号(200)找到其数据块,里面有 test.txt 的目录项,获取其inode编号(比如 12345)。
5.1 文件的增删查改:
5.1.1 增加
创建一个文件的步骤如下:
1.申请一个空闲的 inode,在inode Bitmap对应的inode置为1,将文件信息记录至 inode 属性中。
2.根据Block Bitmap寻找空闲的数据块,将文件内容写入到对应的块中,将使用到的数据块的编号写入到inode的块数组中。
3.添加文件名至当前目录文件的块中,同时将文件名和 文件的inode 之间的属性链接起来
注意: 每使用一个 inode 和一个block,需要把它们对应位图中的信息改为已占用。
5.1.2 访问
找到文件的 inode 编号,在目录分组中查找,然后通过 inode 中块数组的找到文件的数据块,并加载至内存中。
5.1.3 删除
文件创建后,如何删除?删除并不是真删除,而是将 inode Bitmap 和 Block Bitmap 中位图信息进行修改置为0。
- 通过目录的目录项列表通过文件名找到 inode 编号
- 再根据 inode 属性中找到使用的块,设置 Block Bitmap 对应的比特位,设置为 0 (删内容)
- 最后根据 inode 编号在 inode Bitmap 中把对应的inode置为0,
5.2 权限的进一步理解
1.为什么一个目录下不可以创建同名文件?
在目录的文件内容里面根据文件名去找对应的inode值,不能重名。
2.为什么没有目录的读权限就无法查看文件?
没有目录的读权限,这么读取到目录下文件的indoe内容,没有inode值,怎么读取文件属性和内容。
3.为什么没有目录的写权限就无法创建文件?
没有目录的写权限,怎么把文件名和文件的inode值写入到目录的文件内容里面呢。