文件、目录与 inode:持久化的核心抽象
文件是"未解释的字节序列"这一极简抽象;文件的真实身份是 inode(索引节点),目录只是"名字到 inode 号"的映射表,硬链接与软链接正是这一模型的两个自然推论。
一句话定义
文件是"未解释的字节序列"这一极简抽象;文件的真实身份是 inode(索引节点),目录只是"名字到 inode 号"的映射表,硬链接与软链接正是这一模型的两个自然推论。
为什么重要
"一切皆文件"是 UNIX 设计哲学的基石——设备、管道、套接字都以文件接口呈现(呼应 kp-026 的 VFS)。而 inode 模型则解释了大量日常现象:为什么删除大文件空间没释放(fd 未关)、为什么 inode 会耗尽但磁盘明明有空间、为什么 mv 同分区文件瞬间完成。
前置知识
kp-003(文件操作走系统调用);kp-018(文件页驻留内存的概念)。
核心概念
- inode:文件的元数据实体:权限、属主、大小、时间戳、链接计数、数据块指针;不含文件名。
- 目录项(dentry):目录文件中的一条"文件名 → inode 号"记录;目录本身也是文件。
- 硬链接:同一 inode 的多个名字,
ln创建,删除任一名字只是链接计数减一。 - 软链接(符号链接):独立的新文件,内容是另一个路径字符串,可跨文件系统、可指向不存在的目标。
- 文件描述符(fd):进程打开文件后得到的句柄,指向内核打开文件表(含偏移量)。
- 路径解析:从根 dentry 出发逐级查目录,内核用 dentry cache 加速。
原理与机制
一次 open("/home/a.txt") 的内核路径:
"/" -> 根目录 inode
"home" -> 读根目录数据块, 找到 home 的 inode 号
"a.txt" -> 读 home 目录数据块, 找到 a.txt 的 inode 号
-> 读 inode, 权限校验, 创建打开文件表项, 返回 fd
inode 的数据块指针策略:小文件直接指针;更大用一级/二级/三级间接块(ext2 模型),现代 ext4 改用 extent(起始块+长度连续区间),长文件开销从 O(指针数) 降为 O(extent 数)。删除文件 = 目录项移除 + 链接计数减一;计数归零且无进程持有 fd 时,inode 与数据块才真正回收——这就是"文件被删,日志进程还在写,空间不释放"的机制解释。
图示
目录文件(名字->inode号) inode 表 数据块
[ a.txt -> #1024 ] --------> inode #1024 (nlink=2) --> +--------+
[ b.txt -> #1024 ] --------> (同一inode: b.txt 是硬链接) | 文件内容 |
[ s.txt -> #4096 ] --> inode #4096: 内容是 "/home/a.txt" (软链接)
直观类比
inode 像人的身份证(唯一、记录全部档案),文件名像常用称呼——可以有好几个称呼(硬链接)指向同一张身份证;软链接像一张写着"他住在哪"的便条,人搬走了便条就失效。目录则是一份通讯录:只有"称呼→身份证号"的映射,别无其他。
实例或案例
stat a.txt # inode 号、链接数、时间戳全景
ls -i # 列目录项的 inode 号
ln a.txt hard && rm a.txt && cat hard # 硬链接: 删原名数据仍在(nlink 未到 0)
ln -s /nonexist broken && ls -l broken # 悬空软链接
df -i # inode 使用率: 小文件海可耗尽 inode 而 df 显示有空间
经典排查:lsof | grep deleted 找出"已删除但仍被进程持有"的大文件,重启或重启该进程后空间回收。
常见误区
- 认为文件名属于文件:名字只存在于目录数据中,重命名只是改一条目录项。
- 认为跨文件系统可以硬链接:inode 号只在单个文件系统内唯一,跨系统只能用软链接。
- 认为 fd 就是从 0 开始的连续小数字所以随便记:0/1/2 是约定(标准输入/输出/错误),其余由内核分配,并发下要小心复用竞态。
与其他知识点的关系
目录查找的缓存(dentry cache)由 kp-015 的 RCU 保护;文件页的驻留与回收连接 kp-027 页缓存;磁盘上 inode 与数据块的具体排布是 kp-023 的主题。
延伸阅读
《UNIX 操作系统设计》第 4 章;《操作系统导论》文件与目录章节。
自测题
- 删除文件时内核做了什么、何时真正释放空间?
答:移除目录项并把 inode 链接计数减一;计数归零且无进程打开该文件时,inode 与数据块标记为空闲,空间才释放。
- 硬链接与软链接的本质区别?
答:硬链接是同一 inode 的另一个名字,与原文件完全平等;软链接是存着路径字符串的独立文件,解析时重定向,可跨文件系统且可悬空。
- 为什么
mv同一分区是瞬时操作?
答:同分区内 mv 只改目录项(名字→inode 映射),不移动任何数据块;跨分区则退化为复制加删除。