文件系统
文件系统负责把数据长期、有组织地保存在磁盘上,并向应用程序提供"文件"与"目录"这两个抽象。面试中常问 inode 是什么、硬链接与软链接的区别、FAT 与 inode 索引的差异——把这些概念串成一条线,文件系统题就不再零散。
文件与目录、inode
文件是一段有名字的数据集合;目录本质是"文件名 → 文件元数据"的映射表,所有目录组成一棵树,根为 /。文件属性(权限、大小、时间戳)与数据本身分开存放,Linux 中由 inode(索引节点) 承担:
目录项 dentry: 文件名 hello.txt → inode 编号 123
inode 123: [权限][大小][时间][数据块指针 → 块1, 块5, 块9 ...]
ls -i 可查看 inode 编号;stat 可查看完整属性。同一个 inode 可以对应多个目录项,这正是硬链接的基础。
数据块的物理分配方式
数据块在磁盘上的组织方式决定了文件系统的性能与可靠性:
| 方式 | 原理 | 优点 | 缺点 | 代表 |
|---|---|---|---|---|
| 连续分配 | 文件占一段连续块 | 顺序读快 | 外部碎片、难扩展 | 早期系统 |
| 链接分配 | 每块带指针指向下一块 | 无外部碎片 | 只能顺序访问 | FAT |
| 索引分配 | inode 集中保存块指针 | 支持随机访问 | inode 需预留空间 | ext4/NTFS |
# 模拟 FAT 按"簇链"读出文件占用的全部簇
fat = [1, 2, 4, -1, 5, -1] # -1 表示链尾
def read_file(start):
blocks, cur = [], start
while cur != -1:
blocks.append(cur)
cur = fat[cur]
return blocks
print("文件占用簇:", read_file(2)) # 输出:文件占用簇: [2, 4, 5]
inode 索引分配还有一层优化:inode 内先存若干直接块指针,不够再用一级、二级间接块,小文件只需一次访问 inode 就能拿到全部数据块,大文件则靠多级间接块扩展。
硬链接与软链接
- 硬链接:多个目录项指向同一个 inode,链接计数 +1;删除一个名字,只要计数不为 0,数据仍在。硬链接不能跨文件系统,也不能指向目录。
- 软链接(符号链接):是一个独立的 inode,内容存放目标路径,类似 Windows 快捷方式;目标被删除后链接悬空失效。
ln hello.txt hard_link # 硬链接:与 hello.txt 共享 inode
ln -s hello.txt soft_link # 软链接:独立小文件,内容是路径
stat hello.txt
# 输出片段:Size: 12 Blocks: 8 Links: 2 ← 硬链接使 Links 变为 2
页面缓存与写回
磁盘读写很慢,文件系统把读过的块缓存在内存 page cache 中;写入先落缓存,由内核按策略批量写回磁盘(写回式)。因此"程序退出时数据可能尚未真正落盘",数据库调用 fsync 的目的就是强制刷盘。延伸考点:顺序读、mmap、零拷贝(sendfile)都是围绕"减少磁盘访问、减少用户态与内核态拷贝"展开。
常见文件系统对比
ext4 是 Linux 默认文件系统(inode 索引 + 日志);NTFS 是 Windows 主力(支持权限、压缩、日志);FAT32 兼容性最好,但单个文件不能超过 4GB。所谓日志文件系统(ext4、NTFS、XFS)会先记录操作日志再修改数据,断电重启后可据此恢复,避免元数据损坏。
小结
抓住"dentry 与 inode 分离、数据块如何索引、链接如何共享、page cache 如何提速"这条主线,文件系统相关的面试题基本都能覆盖,也能自然引出 fsync、零拷贝等进阶话题。