------ 小dora 操作系统学习笔记 · 文件系统篇Vol.4
"dora:为啥我
touch
了一个文件,磁盘空间没变?删除一个大文件,空间也没回来?"操作系统摊摊手: "你以为保存的是文件名?其实我根本不关心。"
🧠 一、什么是文件系统?它是硬盘的"储物大师"
我们平常看到的:
arduino
/home/dora/大龙虾食谱.txt
在操作系统眼里,只是一个「路径字符串」,它最终需要映射到:
- 一个 inode(索引节点)
- 一堆 data block(数据块)
📌 巧记口诀:
"文件名像门牌号,inode 是户口本,block 才是真家当。"
📦 二、inode 是什么?一个文件的「元信息之家」
inode(index node)本质上是一个结构体结构 ,记录一个文件的元数据:
字段名 | 含义 |
---|---|
mode | 文件类型和权限 |
uid/gid | 拥有者/所属组 |
atime/mtime/ctime | 访问/修改/创建时间 |
size | 文件大小 |
block pointers | 数据块指针(真正数据) |
💡 注意:inode 本身不包含文件名!
文件名存在目录项中,和 inode 是分离的!
📁 三、目录项(Directory Entry):文件名和 inode 的桥梁
操作系统通过目录文件中的条目,把「名字」映射到「inode 编号」:
bash
/etc/passwd
→ /etc
目录是一个特殊的文件
→ 里面有条目:passwd → inode 2345
📌 文件名的真正归属是:目录项,而不是文件自己
📌 巧记口诀:
"文件没名,是目录帮它取的。"
🧱 四、数据块(block):真正存放内容的地方
在 Linux 中,一般采用 块(block) 为单位来管理磁盘:
- 每个块通常为 1KB / 2KB / 4KB(看文件系统)
- 每个 inode 中维护多个「block pointer」指向数据块
- 对大文件,采用「间接块」机制存储更多数据
📊 块指针布局(以 ext2/3/4 为例):
less
inode {
direct[0~11] // 前 12 个直接块指针
single_indirect // 单层间接块(指向 1 个块,块内存的是 block 地址)
double_indirect // 双层间接块
triple_indirect // 三层间接块
}
📌 巧记口诀:
"小文件走直线,大文件走曲线。"
- 小文件:用 direct blocks 就够了
- 大文件:需通过间接块 -> 多级寻址
🔁 五、软链接 vs 硬链接:链接的底层机制
📌 硬链接(hard link)
- 本质:多个目录项 指向同一个 inode
- 删除任意一个文件名,其他还在,数据还在!
📌 link('a.txt', 'b.txt')
→ a.txt
和 b.txt
是同一个 inode,引用计数 +1
📌 软链接(symbolic link)
- 是一个新的 inode
- 内容是路径字符串,例如
"../real/file.txt"
- 类似快捷方式,会重新解析路径
📌 ln -s real.txt link.txt
→ link.txt
是一个指向 real.txt
的「引用文件」
📌 总结对比:
属性 | 硬链接 | 软链接 |
---|---|---|
inode 共享 | ✅ 是 | ❌ 否(独立) |
跨文件系统 | ❌ 不支持 | ✅ 支持 |
原文件删除后 | 数据仍在 | ❌ 会失效 |
🧹 六、rm 文件后空间没回来?你中招了"引用计数机制"
你执行:
bash
rm big.log
发现 df -h
空间没减少!?
原因是:
inode 的引用计数 不为 0,它还在被别的地方用着!
常见场景:
- 程序正在使用该文件(比如 log 正在写)
- 有其他硬链接指向同 inode
📌 真正释放磁盘空间的条件:
- 所有目录项都删除
- 没有进程 open 这个文件
- inode 引用计数 = 0,系统才 reclaim blocks
📌 巧记口诀:
"删了文件没删完,等没人用它才算完。"
🔍 七、实际操作系统里的文件系统(ext4, xfs 等)
现代文件系统除了 inode + block 之外,还优化了很多特性:
文件系统 | 特点 |
---|---|
ext4 | 支持 journaling(日志)、多级索引块 |
xfs | 高性能、支持并发、适合大文件 |
btrfs | 支持快照、校验、子卷 |
NTFS | Windows 系统,使用 MFT(主文件表) |
💣 八、延伸理解:V8 / Node.js 读取文件背后发生了啥?
arduino
fs.readFile('data.txt', callback)
实际上系统:
- 解析路径,层层查目录项
- 找到目标 inode
- 读取 inode 中的 block pointer
- 将数据块加载到内存 → Buffer → 给 JS 使用
🧪 面试级练习题
Q1:为什么删除大文件后空间没立刻释放?
✅ 引用计数未清零 / 文件被进程占用
Q2:硬链接和软链接最大区别是?
✅ 是否共享 inode(硬链接共享)
Q3:inode 中没有存储什么信息?
A. 文件权限
B. 文件大小
C. 文件名
D. 数据块位置
✅ 正确答案:C
Q4:文件系统为何采用多级间接块结构?
✅ 支持大文件 & 节省 inode 空间
✅ 一句话总结
"文件 ≠ 文件名,数据 ≠ 存在路径里。"
操作系统说:'我只认 inode,文件名你爱叫什么叫什么。'