Linux文件系统与inode机制
理解 inode,就理解了 Linux 文件系统的底层逻辑。
一、核心概念
1.1 什么是 inode?
inode(index node) 是 Linux 文件系统中存储文件元数据的数据结构。
每个文件(包括目录、设备文件、符号链接等)都有且仅有一个 inode,用于描述文件的属性信息。
1.2 inode 包含哪些信息?
| 字段 | 说明 |
|---|---|
| 文件类型 | 普通文件/目录/符号链接/设备文件等 |
| 权限 | rwxrwxrwx(9位权限位) |
| 硬链接数 | 指向该 inode 的文件名数量 |
| 所有者 uid / gid | 文件所有者和所属组 |
| 文件大小 | 字节数 |
| 时间戳 | 访问时间 atime / 修改时间 mtime / 状态改变时间 ctime |
| 数据块指针 | 指向文件实际数据所在的磁盘块 |
⚠️ inode 不包含文件名! 文件名存在目录项(dentry)里。
1.3 文件名的查找过程
用户输入 ls 或 cat 文件名
↓
系统在目录文件中查找对应的 dentry(文件名 → inode 号映射)
↓
通过 inode 号找到 inode 结构
↓
通过 inode 中的数据块指针读取文件数据
二、inode 与 数据块 的分离
2.1 磁盘结构
磁盘块
├── inode 表(固定数量,格式化时确定)
├── 数据块区(存储文件内容)
└── 超级块(文件系统整体信息)
2.2 读取一个文件的过程
1. 在目录中查找文件名 → 获得 inode 号
2. 根据 inode 号读取 inode 表 → 获得文件属性和数据块指针
3. 根据数据块指针读取磁盘 → 获得文件内容
2.3 inode 号与文件名的关系
- 一个 inode 号 → 唯一一个文件(不考虑硬链接)
- 一个文件名 → 指向一个 inode 号
- 多个文件名 → 可以指向同一个 inode 号(硬链接)
三、硬链接与软链接
3.1 硬链接(Hard Link)
file1 ──→ inode 12345 ←── file2 (两个文件名共享同一个 inode)
- 指向同一个 inode 号
- 删除任意一个文件名,只要还有硬链接存在,数据不丢失
- 不能跨文件系统(因为 inode 号在不同文件系统间不通用)
- 不能链接目录(防止循环引用)
ln file1 file2 # 创建硬链接
ls -li file1 file2 # 可以看到相同的 inode 号
3.2 软链接 / 符号链接(Symbolic Link)
file1 → inode 12345
symlink → 指向 file1 这个路径名(不是 inode)
- 是一个独立的文件,有自己的 inode
- 文件内容是目标路径名
- 可以跨文件系统
- 可以链接目录
ln -s file1 symlink # 创建软链接
3.3 硬链接 vs 软链接
| 维度 | 硬链接 | 软链接 |
|---|---|---|
| inode | 共享同一 inode | 独立 inode |
| 跨文件系统 | ❌ 不可以 | ✅ 可以 |
| 跨目录 | ❌ | ✅ |
| 链接目录 | ❌ | ✅ |
| 原文件删除后 | 数据仍存在 | 链接失效(broken) |
四、ext2/ext3/ext4 inode 结构
4.1 inode 大小与数量
# 查看 inode 总数与使用情况
df -i /dev/sda1
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 655360 20000 635360 3% /
4.2 数据块指针
inode 中使用三级指针间接寻址,支持不同大小的文件:
┌─────────────────────────┐
│ inode (256 bytes) │
│ [直接指针 x 12] │ ← 文件 ≤ 12 块时直接定位
│ [一级间接指针] │ ← 文件 ≤ 12+256 块
│ [二级间接指针] │ ← 文件 ≤ 12+256+256² 块
│ [三级间接指针] │ ← 文件 ≤ 12+256+256²+256³ 块
└─────────────────────────┘
为什么 inode 大小是 256 字节?历史原因,磁盘块大小通常是 4096 字节。
五、常见命令与 inode 操作
5.1 查看 inode 号
ls -i file.txt
# 输出: 12345 file.txt
stat file.txt
# 输出详细信息,包含 inode: 12345
5.2 通过 inode 号删除文件
# 当文件名包含特殊字符无法删除时
find /path -inum 12345 -delete
5.3 inode 耗尽排查
# 查看哪个目录 inode 使用最多
df -i
# 定位 inode 异常耗尽的目录
find / -xdev -type f -printf '.' | wc -c # 慢但精确
5.4 硬链接实验
echo "hello" > file1
ln file1 file2 # 硬链接
ln -s file1 symlink # 软链接
ls -li file1 file2 symlink # 查看 inode 号
六、常见面试题
Q1: inode 耗尽但磁盘空间还有很多,是什么原因?
大量小文件(inode 耗尽但数据块空闲)。每个文件至少占一个 inode,当 inode 全部用完时即使磁盘空间还有剩余,也无法创建新文件。
Q2: 删除一个文件后,如何判断磁盘空间是否真正释放?
使用
lsof | grep deleted查看是否有进程仍持有已删除文件的文件描述符。若有,空间不会真正释放直到进程退出。
Q3: cp 命令会复制 inode 吗?
不会。
cp创建新文件(新 inode),复制文件内容到新的数据块。硬链接ln才是共享 inode。
Q4: inode 和 dentry 的区别?
inode 描述文件是什么(属性+数据块指针),dentry 描述文件在哪里(文件名→inode号的映射,存在目录中)。