↑ 顶部/笔记 2026-10-25 · 约 8 分钟

文件系统与链接

一句话总结:文件系统把分区“装修”成 superblock + inode + data block,文件名只是目录里的一条映射,链接就是围绕 inode 做文章。 适用:Rocky Linux / CentOS 9,ext4 / xfs。示例目录 /tmp/fs。

更新于 2026-10-25 · 正文约 3016 字

一、文件系统是什么

文件系统是操作系统里控制硬盘、组织数据的一套程序。

  • 分区:把一块硬盘“打隔断”,分成一个个小空间;
  • 文件系统:对每个小空间“做装修”,负责把里面的数据组织好。

所以:每个分区都要有一个文件系统,格式化(mkfs)就是“装修”的过程。

使用者 ──> block 块(文件系统管理单位) ──> n 个扇区(硬盘最小读写单位)

扇区通常 512B,文件系统以 block(默认 4K)为单位分配空间,一个 block 包含 8 个扇区。

二、文件系统的三大类块

一个文件由元数据 + 内容数据两部分组成,分别落在不同的块里:

块类型 存什么 数量
superblock 超级块 整个文件系统的整体信息:inode/block 的总量、已用、剩余、文件系统格式 一个文件系统只有一个
inode block 索引节点 一个文件的元数据:权限、属主、属组、大小、时间戳、数据块指针、链接数 一个文件一个 inode
data block 数据块 文件真正的内容(cat 看到的东西);目录的 data block 存“子文件名 → inode 号” 一个文件可以有多个
/etc/passwd  ──>  [ inode #12345 ] ──> [ data block 1 ][ data block 2 ] ...
                    元数据              真正的文本内容

重要结论:文件名不存 inode 里。文件名和 inode 号的对应关系存在目录的 data block 里。这也是硬链接、软链接原理的根源。

三、查看文件系统

命令 作用 例子
df -T 看挂载点和文件系统类型 df -T
df -h 看空间使用量(带单位) df -h
df -i 看 inode 使用量 df -i
lsblk -f 看分区、文件系统、UUID、挂载点 lsblk -f
mount 看当前挂载 mount
stat 文件 看 inode 号、块数、三个时间 stat /etc/passwd
ls -i 只看 inode 号 ls -i /etc/passwd
findmnt 树形查看挂载关系 findmnt /
df -T
df -h
df -i
lsblk -f

四、磁盘“满”的两种情况

这是运维面试和故障排查的高频点:df -h 显示还有空间,但就是写不进去。

情况 原因 怎么查 怎么造
inode 耗尽 小文件太多,inode 号用光了(空间可能还有富余) df -i,IUse% 到 100% 循环 touch 几百万个空文件
磁盘空间耗尽 单个大文件把 block 占满 df -h,Use% 到 100% dd 生成超大文件
# 造 inode 耗尽(300 万个空文件,别在生产上试)
for ((i=1;i<=3000000;i++)); do touch $i.txt; done

# 造空间耗尽(30G 零字节文件)
dd if=/dev/zero of=/tmp/1.txt bs=10G count=3

# 动态观察 inode 使用
watch -n 1 "df -i | grep sda1"

快速释放一个已被进程打开的超大文件:直接 rm 可能不释放空间(进程还拿着 fd)。正确做法是先清空内容:> /path/bigfile(或 : > bigfile),再删。

清理 inode:先定位哪个目录小文件最多。

for d in /var/*; do echo -n "$d "; find "$d" -xdev -type f 2>/dev/null | wc -l; done
find /var/spool -type f -name "*.tmp" -delete

五、打开一个文件的底层流程

以 cat /etc/passwd 为例:

1. 从根目录 / 的 inode 开始(根 inode 号固定,ext4 通常是 2)
2. 读 / 的 data block,找到 "etc" 对应的 inode 号
3. 读 etc 的 data block,找到 "passwd" 对应的 inode 号
4. 读 passwd 的 inode,拿到权限、属主、数据块指针
5. 按指针把 data block 里的内容读进内存,交给 cat 输出

关键点:

  • 目录也是文件:它的 inode 存元数据,data block 存“子文件名 → inode 号”的列表;
  • 路径里每一级都要有 x 执行权限才能进去;
  • 进程打开文件后,内核在进程的文件描述符表里记一项,指向系统的“打开文件表”,再指向 inode。所以 fd 是“进程视角的编号”,inode 是“磁盘视角的身份”。

六、硬链接与软链接

ln /1.txt /2.txt
  • 本质:两个文件名指向同一个 inode,inode 的链接数 +1。
  • 特点:
特点 说明
内容同步 改一个文件内容,另一个跟着变(本来就是同一份数据)
元数据同步 改权限、属主,另一个也变(同一个 inode)
删源文件 只是解除“文件名 → inode”的关联,链接数 -1,数据还在,另一个名字照常用
不能跨分区 ln: 无法创建硬链接 ... 无效的跨设备连接
不能给目录做 内核禁止(防止目录环)
ln /1.txt /2.txt
ls -li /1.txt /2.txt      # inode 号相同,链接数变成 2
rm /1.txt
cat /2.txt                # 依然能读
ln -s /1.txt /4.txt
  • 本质:新建一个文件(有自己的 inode),它的 data block 里存的是目标文件的路径字符串。
  • 特点:
特点 说明
内容同步 通过软链接读写,实际操作的还是源文件
元数据不同步 改源文件权限,软链接自己的权限不变(不同 inode)
删源文件 软链接变成“断链”,访问报 No such file or directory
可以跨分区 因为它只存路径字符串
可以给目录做 ln -s /data/app /opt/app
ln -s /1.txt /4.txt
ls -li /1.txt /4.txt      # inode 号不同,4.txt 类型是 l
readlink /4.txt           # 看它指向谁

6.3 一表看懂

对比 硬链接 软链接
创建命令 ln 源 目标 ln -s 源 目标
inode 与源文件相同 自己独立一个有 inode
文件类型 普通文件 - 链接 l
链接数 +1 源文件链接数不变
跨分区 不行 可以
链接目录 不行 可以
删源文件 数据保留,另一个名字可用 断链,失效
改元数据 互相影响 互不影响
典型用途 同一份数据多个入口、防误删 版本切换、路径简化(/usr/local/nginx -> /opt/nginx-1.24)

发布场景:程序解压到 /opt/app-1.24,再建软链接 /opt/app -> /opt/app-1.24。升级只改软链接,回滚也只改软链接,服务配置里始终写 /opt/app。

速查表

df -T; df -h; df -i
lsblk -f; findmnt; mount | column -t
stat /etc/passwd; ls -i /etc/passwd
ln a b; ln -s a b; ls -li; readlink b
dd if=/dev/zero of=/tmp/big bs=10G count=1
> /path/bigfile            # 清空已被进程占用的文件
watch -n 1 "df -i | grep sda1"

常见坑

  1. df -h 有空间但写不进去 → 先看 df -i,多半是 inode 耗尽。
  2. 删了文件空间没释放 → 进程还开着这个文件,lsof | grep deleted 查,重启进程或清空文件。
  3. 硬链接跨分区必失败,这不是权限问题。
  4. 软链接用相对路径创建,链接被移动后会断,建议用绝对路径。
  5. rm 删除的是“文件名”,不是 inode;只有链接数归零且没有进程打开,空间才真正释放。
  6. 目录的 x 权限决定能否进入,r 决定能否列出文件名,w 决定能否在里面增删文件。

练习(14 题)

先自己做,再点开答案核对 0 / 14 已查看

01

文件系统、分区、扇区、block 之间是什么关系?

查看答案

硬盘被分成扇区(最小读写单位,通常 512B),分区是把硬盘划分成独立空间,文件系统负责组织分区里的数据,以 block(默认 4K,8 个扇区)为单位分配。

02

superblock、inode、data block 各存什么,数量上有什么区别?

查看答案

superblock 存整个文件系统的总量/使用/格式,一个文件系统只有一个;inode 存单个文件的元数据和数据块指针,一个文件一个;data block 存内容,一个文件可以有多个。

03

一个 10G 的分区,df -h 显示还有 2G,但创建文件报 No space left on device,最可能是什么原因?用什么命令确认?

查看答案

inode 耗尽。用 df -i 看 IUse% 是否 100%。

04

写出制造 inode 耗尽的测试思路(不要在生产环境执行)。

查看答案

在测试分区循环创建大量空文件,例如 for ((i=1;i<=3000000;i++)); do touch $i.txt; done,同时用 watch -n 1 "df -i" 观察。

05

如何动态观察某个分区的 inode 使用率?

查看答案
watch -n 1 "df -i | grep sda1"
06

一个被进程打开着的大日志文件,直接 rm 后空间没释放,怎么处理?

查看答案

先清空内容释放空间:> /path/bigfile(或 : > bigfile),再删文件;或者重启占用它的进程。用 lsof | grep deleted 找到进程。

07

简述 cat /etc/passwd 时内核的查找流程。

查看答案

根目录 inode → 根 data block 找 etc 的 inode 号 → etc 的 data block 找 passwd 的 inode 号 → 读 passwd inode 拿到数据块指针 → 读 data block 输出。

08

目录的 data block 里存的是什么?

查看答案

存该目录下“子文件名(子目录名)→ inode 号”的映射列表。

09

创建硬链接和软链接的命令分别是什么?

查看答案
ln /1.txt /2.txt        # 硬链接
ln -s /1.txt /4.txt     # 软链接
10

硬链接为什么不能跨分区?软链接为什么可以?

查看答案

硬链接要求同一个 inode,而 inode 号只在单个文件系统内唯一;软链接只是一个存路径的普通文件,路径可以指向任何分区。

11

删除源文件后,硬链接和软链接分别是什么结果?

查看答案

硬链接:链接数减 1,数据仍在,另一个名字还能用;软链接:变成断链,访问报 No such file or directory。

12

修改源文件的权限,硬链接和软链接哪个会跟着变?为什么?

查看答案

硬链接会变,因为两者是同一个 inode;软链接不变,因为它有自己的 inode,只存路径。

13

用 ls -li 判断两个文件是否是硬链接,依据是什么?

查看答案

ls -li 第一列 inode 号相同即为硬链接(且链接数 ≥2)。

14

发布目录 /opt/app-1.24,如何做到“改软链接就完成升级和回滚”?

查看答案
ln -s /opt/app-1.24 /opt/app        # 首次
ln -sfn /opt/app-1.25 /opt/app      # 升级
ln -sfn /opt/app-1.24 /opt/app      # 回滚

-f 覆盖已有链接,-n 防止把链接建到目录里面;服务配置始终指向 /opt/app。

文件系统与链接 · 生成于 2026-10-26 00:46