Files
Operating-System/FileSystem/structure.md
2026-03-22 17:40:44 +08:00

441 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
好,直接给你一版**“一屏吃透文件系统数据结构”**,从最底层磁盘组织 → inode → 数据块索引 → 目录结构 → 空闲空间管理 → 现代高级结构,一次性压满信息密度,尽量做到你说的“每屏最大信息量”。
---
# 一、文件系统的本质抽象(先立一个统一模型)
你可以把整个文件系统抽象成三张核心表:
```text
(1) inode表 inode_id → metadata权限/大小/时间/指针)
(2) 数据映射: (inode_id, offset) → block
(3) 目录映射: (parent_inode, filename) → inode_id
```
👉 所有“文件结构”本质都在优化这三件事:
* 如何表示文件数据第2条
* 如何快速查找文件名第3条
* 如何管理空间(块分配)
---
# 二、文件数据的组织方式(核心重点)
## 1⃣ 连续分配Contiguous Allocation
```text
inode:
start_block
length
```
```text
[block100][block101][block102][block103]...
```
✔ 优点:
* 顺序读写极快(完美局部性)
* 实现简单
✘ 缺点:
* 文件增长困难(需要搬迁)
* 外部碎片严重
👉 现在基本不用(但思想在 extent 里复活)
---
## 2⃣ 链式分配Linked Allocation
```text
block100 → block500 → block20 → block9 ...
```
inode 只存:
```text
first_block
```
✔ 优点:
* 无外部碎片
* 动态扩展容易
✘ 致命问题:
* 随机访问 O(n)
* 每个block都要存指针浪费
* cache locality 极差
👉 FAT 文件系统就是这个思路(用数组模拟链表)
---
## 3⃣ FATFile Allocation Table
本质:
```text
FAT[block] = next_block
```
```text
FAT:
100 → 500
500 → 20
20 → EOF
```
✔ 优点:
* 比链式更容易管理
* 支持随机访问(通过表)
✘ 问题:
* FAT表巨大必须常驻内存
* 可靠性差(单点损坏)
---
## 4⃣ 多级索引inode经典结构ext2/3
inode结构
```text
inode:
direct[12]
indirect
double_indirect
triple_indirect
```
访问逻辑:
```text
offset → 第几个block → 走指针树
```
结构:
```text
inode
/ | \
direct indirect double
|
[block pointers]
```
✔ 优点:
* 支持大文件
* 随机访问 O(1)(理论)
✘ 问题:
* 小文件浪费指针
* 大文件访问多次IO多级跳转
👉 这是 UNIX 经典设计
---
## 5⃣ Extent现代主流ext4
核心思想:
👉 不记录“每个block”而记录“连续区间”
```text
extent:
(logical_start, physical_start, length)
```
例:
```text
(0, 100, 50) // 文件0-49 → 磁盘100-149
```
结构:
```text
inode
└── extent tree
```
✔ 优点:
* 极大减少元数据
* 顺序读写性能好
* 减少碎片
👉 本质:**连续分配的升级版 + 树结构管理**
---
## 6⃣ B-tree / B+treeXFS / Btrfs
```text
[key]
/ | \
child child child
```
key可能是
```text
(file_offset → block)
```
✔ 优点:
* O(log n) 查找
* 高扇出 → 极少IO
* 适合大规模数据
👉 XFSextent索引用B+tree
👉 Btrfs所有东西都是B-tree
---
## 7⃣ Copy-on-WriteBtrfs / ZFS核心
写数据时:
```text
旧块不改 → 写新块 → 更新指针
```
结构:
```text
旧树 ----\
\--> 新树(部分共享)
```
✔ 优点:
* snapshot免费
* 崩溃一致性好
* 支持版本回滚
✘ 缺点:
* 写放大
* 碎片增加
---
# 三、目录结构(名字 → inode
## 1⃣ 线性表ext2早期
```text
"file1" → inode 10
"file2" → inode 20
```
查找:
```text
O(n)
```
---
## 2⃣ 哈希表HTreeext4
```text
hash(filename) → bucket → inode
```
结构:
```text
root
/ \
bucket bucket
```
✔ 平均:
```text
O(log n)
```
---
## 3⃣ B-tree目录XFS / Btrfs
```text
filename → inode
```
用B+tree组织
✔ 优点:
* 有序支持range scan
* 高效查找
---
# 四、空闲空间管理(磁盘怎么分配)
## 1⃣ 位图bitmap
```text
1 = used
0 = free
```
```text
001011000100...
```
✔ 优点:
* 查找连续空间方便
* 实现简单
---
## 2⃣ 空闲链表
```text
free → free → free
```
✘ 问题:
* 找连续空间困难
---
## 3⃣ 分组grouping
一次记录多个空闲块:
```text
block → [free1, free2, free3...]
```
---
## 4⃣ B-tree管理现代FS
```text
free_extent:
(start, length)
```
用树管理:
✔ 高效查找大块连续空间
---
# 五、日志Journaling
目的:
👉 防止系统崩溃导致文件系统损坏
流程:
```text
写日志 → 提交 → 写实际数据
```
模式:
1. write-ahead logging
2. metadata journalingext4默认
3. full journaling慢但安全
---
# 六、把所有结构统一成一张“全景图”
```text
用户操作:
open("/a/b/file")
↓ 路径解析
目录结构HTree / B-tree
(parent_inode, name) → inode
↓ inode
inode table
↓ 数据定位
extent / B-tree / indirect block
↓ block
page cache → disk
↓ 磁盘
物理block
```
---
# 七、一句话总结(给你压缩记忆)
```text
文件系统 = inode + 数据索引结构 + 目录索引 + 空闲管理 + 一致性机制
```
演化路径:
```text
连续 → 链式 → FAT → inode多级索引 → extent → B-tree → CoW
```
---
# 八、你现在应该形成的“认知模型”(很重要)
你可以这样理解:
```text
早期FS像数组 + 指针
现代FS像数据库KV + B-tree + WAL
```
---
# 九、如果你继续往下深挖(我建议你下一步搞这个)
下一步最关键的是搞清楚:
👉 一次 read() 发生了什么:
```text
用户态
→ VFS
→ dentry cache
→ inode cache
→ page cache
→ block layer
→ IO scheduler
→ disk
```
这个链路一通:
👉 文件系统 + 虚拟内存 + IO 子系统就串起来了
---
如果你下一步想继续,我可以给你一版:
👉 **“从 open 到 read 到 page cache 命中/缺页的全流程 + 内核数据结构图task_struct / file / inode / dentry 全串)”**
那个是操作系统理解的分水岭。