你以为你保存的是“文件”?其实是 inode + block 的数据幻术!

------ 小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.txtb.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)

实际上系统:

  1. 解析路径,层层查目录项
  2. 找到目标 inode
  3. 读取 inode 中的 block pointer
  4. 将数据块加载到内存 → Buffer → 给 JS 使用

🧪 面试级练习题

Q1:为什么删除大文件后空间没立刻释放?

✅ 引用计数未清零 / 文件被进程占用


Q2:硬链接和软链接最大区别是?

✅ 是否共享 inode(硬链接共享)


Q3:inode 中没有存储什么信息?

A. 文件权限

B. 文件大小

C. 文件名

D. 数据块位置

✅ 正确答案:C


Q4:文件系统为何采用多级间接块结构?

✅ 支持大文件 & 节省 inode 空间


✅ 一句话总结

"文件 ≠ 文件名,数据 ≠ 存在路径里。"
操作系统说:'我只认 inode,文件名你爱叫什么叫什么。'

相关推荐
阿昭L9 小时前
关于僵尸进程
linux·操作系统·僵尸进程
狂浪天涯11 小时前
Android 16 | Display Framework - 2 | Surface
android·操作系统
DoraBigHead1 天前
你看到的内存地址都是假的!操作系统的虚拟内存魔术揭秘
操作系统
喧星Aries2 天前
进程互斥的硬件实现方法
操作系统
红橙Darren2 天前
手写操作系统 - 环境搭建
android·微信·操作系统
egoist20233 天前
【Linux仓库】虚拟地址空间【进程·陆】
linux·运维·服务器·操作系统·进程·虚拟地址空间·fork
DoraBigHead3 天前
进程:你以为你写了代码,其实你只是申请了个号
操作系统
望获linux3 天前
【实时Linux实战系列】多核同步与锁相(Clock Sync)技术
linux·前端·javascript·chrome·操作系统·嵌入式软件·软件
望获linux3 天前
【实时Linux实战系列】硬实时与软实时设计模式
linux·运维·服务器·数据库·操作系统·rtos·嵌入式软件