4 mins
Linux文件系统与磁盘管理

本文深入探讨 Linux 磁盘管理的各个维度,从基础的文件系统原理、磁盘分区等角度介绍

在 Linux 中,有一个让人困惑的问题就是:为什么我用 df -h 查看到磁盘空间已满,但用 du -sh * 加起来却找不到那些占用空间的大文件?

这个问题不仅仅是命令使用上的区别,它直指 Linux 文件系统的核心机制:文件句柄和磁盘块管理。

df和du的本质区别h2

df查看文件系统元数据,直接读取文件系统头部信息中记录的空闲和已使用的数据块总量,报告文件系统整体的磁盘空间占用情况。

du则是遍历文件系统目录树,从指定的目录开始,递归地读取目录下所有文件的大小,然后累加,报告特定文件或目录在目录结构中占用的空间。

当df报告的已用空间大于du的总和时,几乎可以断定是“幽灵文件”,即已被删除但尚未释放磁盘空间的文件。

何为文件句柄h3

文件句柄(File Handle),在 Linux 中通常被称为文件描述符(File Descriptor),是操作系统内核分配给进程的唯一标识符(一个整数),用于引用该进程打开的文件。

只要一个文件被任何进程打开并持有其句柄,即使该文件的目录条目被移除,内核也不会释放文件所占用的物理磁盘空间。

模拟这个过程h3

  1. 我们使用dd命令创建一个500MB的文件,并记录df和du的初始值。
Terminal window
# 1. 创建 500MB 文件
root@machine:/tmp# dd if=/dev/zero of=test_file.dat bs=1M count=500
500+0 records in
500+0 records out
524288000 bytes (524 MB, 500 MiB) copied, 1.65991 s, 316 MB/s
# 2. 检查文件大小
root@machine:/tmp# ls -lh test_file.dat
-rw-r--r-- 1 root root 500M Dec 17 09:55 test_file.dat
# 3. 记录 df 基准(查看文件系统整体占用)
root@machine:/tmp# df -h .
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 39G 13G 24G 36% /
# 此时,文件系统已用空间为 13GB (36%)。
# 4. 记录 du 基准(查看该文件占用)
root@machine:/tmp# du -sh test_file.dat
501M test_file.dat
  1. 打开文件并删除,模拟幽灵文件的诞生(我们使用tail -f进程在后台打开并持续监视该文件,然后使用rm命令删除它)
Terminal window
# 1. 后台打开文件,进程持有文件句柄
root@machine:/tmp# tail -f test_file.dat &
PID=$!
[1] 11225
# 2. 删除文件
root@machine:/tmp# rm test_file.dat
# 3. 检查 du (文件名已消失)
root@machine:/tmp# du -sh .
200K .
# 结论:du 报告的文件大小急剧下降(从 501M 降至 200K),因为它找不到文件名了。
# 4. 检查 df (空间仍被占用)
root@machine:/tmp# df -h .
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 39G 13G 24G 36% /
# 结论:df 报告的已用空间(13G, 36%)保持不变! df 和 du 出现不一致。
  1. 杀死进程并释放空间,模拟幽灵文件消亡(终止持有文件句柄的进程,观察磁盘空间是否被释放)
Terminal window
# 1. 终止持有句柄的进程 (PID=11225)
root@machine:/tmp# kill $PID
[1]+ Terminated tail -f test_file.dat
# 2. 再次检查 df
root@machine:/tmp# df -h .
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 39G 12G 25G 34% /
# 结论:df 报告的已用空间下降到 12GB (34%)! 500MB 空间终于被释放。

这证明了,df统计的磁盘块,只有在文件句柄被关闭后(即使文件早已被rm),操作系统内核才会真正释放其所占用的磁盘空间。

Comments