文件系统
- 磁盘结构与文件系统的联系
-
- 磁盘的基本结构
- 寻址方式
- 文件系统静态结构
- 如何理解目录
- 软链接与硬链接
- 动态库和静态库
-
- 概念
- 生成静态库和动态库
磁盘结构与文件系统的联系
磁盘的基本结构
机械硬盘结构⬇️ 
实物图⬇️
盘片(Platter)
- 材质:由铝合金或玻璃制成,表面涂有磁性材料
- 数据表示:数据通过磁化方向(北极/南极)表示0和1
- 结构特点:通常硬盘包含多个盘片,两面都可使用
磁道(Track)
- 定义:盘片上同心圆的环形数据区域 最外圈磁道为0磁道
扇区(Sector)
- 定义:磁道被等分的圆弧段
- 大小:传统大小为512字节,现代多为4KB(高级格式)
- 重要性:最小物理存储单元
柱面(Cylinder)
- 定义:所有盘片上相同半径的磁道组成的圆柱面
- 特点:磁头无需移动即可访问的所有磁道
可结合此图来理解⬇️ 
寻址方式
| CHS | 柱面-磁头-扇区 | 早期BIOS使用 |
| LBA | 逻辑块地址(线性编号) | 现代系统使用 |
| ZBR | 区位记录(外圈密度高) | 提高存储效率 |
主要需要理解CHS和LBA的转化⬇️
可以想象硬盘像一卷厕纸,之前的同心圆展开后就变成了一段连续的、线性的空间,像是数组一样,这就是磁盘的逻辑结构。 当我们能拿到该种类磁盘的信息(每个盘面多少扇区、每个扇面多少磁道、每个磁道多少扇区)时,就可以实现CHS到LBA 地址的转化,从而使操作系统可以更方便地管理磁盘文件。
文件系统静态结构
磁盘中有数以万计的文件,要高效、合理地管理它需要解决以下几个核心问题: 空间管理:哪些块已用/未用? 文件组织:如何找到文件的所有块? 命名与目录:如何通过路径找到文件? 元数据:如何存储权限、时间戳等信息? 可靠性:断电或崩溃时数据一致性?

block group 0…block group n是将磁盘的大空间划分成的一个个小的区域块。
以ext2文件系统为例,如上图所示,磁盘是典型的块设备,磁盘分区被划分为一个个block。一个block的大小是由格式化的时候确定的,并且不可以更改。
| Boot Block | 引导扇区 | • 包含系统启动代码• MBR或GPT分区表可能位于此• 系统启动时BIOS/UEFI首先读取此区域 | 通常为512字节,位于磁盘最起始位置 |
| Super Block | 超级块 | • 文件系统的"元数据目录"• 记录inode总数、块大小、块数量等全局信息• 多个副本分布在不同的块组中,提供冗余 | 通常占用1个磁盘块,分散存储 |
| Group Descriptor Table | 组描述符表 | • 描述每个块组的详细信息• 包含块位图、inode位图、inode表的起始位置• 支持快速定位块组内资源 | 每个块组都有对应的描述符 |
| Block Bitmap | 块位图 | • 位图数据结构,跟踪数据块的分配状态• 每个位对应一个数据块(0=空闲,1=已用)• 加速空闲块查找 | 大小取决于块组中的数据块数量 |
| inode Bitmap | inode位图 | • 位图数据结构,跟踪inode的分配状态• 每个位对应一个inode(0=空闲,1=已用)• 加速空闲inode分配 | 大小取决于块组中的inode数量 |
| inode Table | inode表 | • 存储所有inode的结构化数组• inode包含文件元数据:权限、大小、时间戳、数据块指针等• 每个文件/目录对应一个inode | 连续存储,大小固定 |
| Data Blocks | 数据块 | • 实际存储文件内容的区域• 块大小可配置(1K、2K、4K、8K等)• 支持直接指针、间接指针等多种寻址方式 | 占用大部分磁盘空间 |
inode:包含单个文件的所有属性,128字节; 一般而言一个文件对应一个inode。inode具有唯一编号 可以看出文件系统中,文件内容和数据是分开存储的! 在linux系统下,文件属性中不包含文件的名称!!只知道该文件的编号。 在linux系统里标识文件用的是inode编号
inode结构⬇️
#define NUM 15
struct inode
{
inode number
文件类型
权限
引用计数
拥有者
所属组
ACM时间
int blocks[NUM];
}
文件读取过程:所以只要知道该文件的inode编号就可以在inode table中找到该文件的inode(上面那个结构体),之后就能找到结构体内的block数组,根据数组内存储的块编号就能在data block中读取整个文件。
疑问: int block[NUM]是一个只有十五个数的数组,按理说只能定位十五个数据块(1K、2K、4K、8K等)总和起来不超过1MB。他是如何索引庞大的文件的?
解答:int blocks[NUM] 中的 15个指针通过多级间接索引机制,能够管理从几KB到TB级别的文件。
blocks[0] ~ blocks[11] : 12个直接指针(直接索引,指向的数据块中存的就是文件内容)
blocks[12] : 一级间接指针(间接索引,指向的块中存的不是文件内容,而是存储文件的块号)
blocks[13] : 二级间接指针(间接索引,指向的块中存的不是文件内容,而是存储文件的块号)
blocks[14] : 三级间接指针(间接索引,指向的块中存的不是文件内容,而是存储文件的块号)
二级间接块结构:
- 二级间接块数:1个(指向1024个一级间接块)
- 每个一级间接块:包含1024个数据块指针
- 二级间接总容量:1024 × 1024 × 4KB = 4GB
- 累计容量(含直接和一级间接):4.05MB + 4GB = 约4.004GB
这15个指针的设计体现了经典的时空权衡(Time-Space Tradeoff):
| 空间效率 | 小inode结构,仅需15×4=60字节 | 节省内存和磁盘元数据空间 |
| 时间效率 | 小文件直接访问(O(1)),大文件虽慢但可用 | 优化常见访问模式 |
| 可扩展性 | 4级索引支持从字节到TB的范围 | 适应不同规模的文件需求 |
| 实用性 | 符合典型文件大小分布(大多数文件小,少数文件大) | 基于真实使用模式的优化 |
这就是为什么一个看似简单的int blocks[15]能够支撑现代文件系统的核心原因!这种分层索引机制是UNIX文件系统设计中最经典、最优雅的设计之一。
Block Bitmap:比特位的位置和块号映射起来 它的设计理念可以用一个简单的比喻来理解⬇️ 想象一本书的目录页,目录中每一行对应书中的一个章节,并标记该章节是否已被占用。 在Block Bitmap中: 每个比特位(bit) ↔ 对应一个数据块(data block) 比特值 = 0 → 该数据块空闲可用 比特值 = 1 → 该数据块已被占用 这个区域可以解决文件系统空间管理(哪些块已用/未用?)的问题
inode Bitmap:比特位的位置和inode编号映射起来 如果说Block Bitmap是管理数据空间的地图,那么Inode Bitmap就是管理文件身份的户籍系统。它的核心作用是: 精确跟踪每一个inode号码的分配状态,确保文件系统能够高效、无冲突地创建和删除文件。 基本映射关系: 每个比特位(bit) ↔ 对应一个inode号码 比特值 = 0 → 该inode号码空闲可用 比特值 = 1 → 该inode号码已被分配给文件/目录
文件删除过程:先拿到文件编号,在inode bitmap中发现位图中为“1”是有效的内容,接着去inode table中读取它的属性获得int blocks[NUM]中的块号,之后在Block Bitmap中将数字全部置为“0”,再去inode Bitmap中将“1”改为“0”,此时文件成功被删除!
Group Descriptor Table:描述每个块组的详细信息(基本使用情况)。 因为inode Bitmap和Block Bitmap仅仅只是知道该位置有没有被使用。具体用了多少还剩多少,整个分组是多大,是由Group Descriptor Table来记录管理的。
SuperBlock⬇️ 
如何理解目录
在Linux文件系统中,目录(Directory) 是特殊的文件类型,它不仅是文件的容器,更是文件系统结构的核心。 目录的内容是文件名和对应inode,完成了名称对inode的映射。
软链接与硬链接

动态库和静态库
概念
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking) 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。 操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
生成静态库和动态库
静态库的使用 命令:gcc -c add.c -o add.o gcc -c sub.c -o sub.o 将两个c文件编译为.o文件 使用ar -rc libmymath.a add.o sub.o 将两个文件打包
ar是gnu归档工具,rc表示(replace and create)
查看静态库中的目录列表
[root@localhost linux]# ar –tv libmymath.a
rw–r—r— 0/0 1240 Sep 15 16:53 2017 add.o
rw–r—r— 0/0 1240 Sep 15 16:53 2017 sub.o
t:列出静态库中的文件
v:verbose 详细信息
命令:gcc main.c -L. -lmymath -L 指定库路径 -l 指定库名(去掉lib,去掉后缀就是库名称) 测试目标文件生成后,静态库删掉,程序照样可以运行。
动态库的创建
命令:gcc -fPIC -c math_functions.c -o math_functions.o -fPIC 生成位置无关代码 -shared 生成共享库
# 创建动态库
gcc –shared –o libmath.so math_functions.o
# 或者一步完成
gcc –fPIC –shared –o libmath.so math_functions.c
动态库的使用
# 编译链接动态库
gcc main.c –L. –lmath –o program





