人人都会AI编程

4.3 inode 与块:文件存储的底层结构

更新时间:2026-07-12

在日常使用 Linux 时,我们习惯用文件名来指代一个文件,比如 report.txt/etc/passwd。但实际上,文件名只是给用户看的一个标签,真正定义“这个文件是谁、属于谁、数据在哪里”的核心数据结构,是 inode(索引节点)。而文件的实际内容,存储在磁盘上一块块固定大小的 数据块(block) 里。理解 inode 和块的关系,是理解 Linux 文件系统中“删除为何能恢复”“为什么目录不能存太多文件”“硬链接和软链接到底差在哪”等一系列实际问题的关键。

inode:文件在文件系统里的“身份证”

每个文件(包括目录、设备、管道等)在文件系统中都有且仅有一个唯一的 inode 编号,以及一个对应的 inode 结构体,里面记录了除文件名和文件内容之外的所有“元数据”:

  • 文件类型与权限:是普通文件、目录还是符号链接?属主、属组和其他人的读、写、执行权限。
  • 所有者和组 ID:记录文件的 uid 和 gid。
  • 文件大小:以字节为单位的长度。
  • 时间戳
  • ctime(change time):元数据最近被修改的时间(如权限变更、所有者变更)。
  • mtime(modification time):文件内容最近被修改的时间。
  • atime(access time):文件最近被访问的时间(可能因挂载选项和性能优化而延迟更新)。
  • 链接计数:记录有多少个目录项(文件名)指向这个 inode。
  • 指向数据块的指针:保存文件实际数据在磁盘的哪些块上。

使用命令可以直观地查看一个文件的 inode 编号和详细元数据:

ls -i report.txt          # 显示 inode 号
stat report.txt           # 显示完整 inode 信息

输出示例:

  File: report.txt
  Size: 2048            Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d      Inode: 131072      Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/   user)   Gid: ( 1000/   user)
Access: 2025-01-15 10:30:00.000000000
Modify: 2025-01-15 09:00:00.000000000
Change: 2025-01-15 09:00:00.000000000

数据块:实际内容的存放地

文件系统的存储空间被分割成一个个大小固定的 块(block),典型值为 4 KB。一个文件占用整数个块,即使文件内容只有几个字节,也会分配至少一个完整的块(但可通过碎片或内联存储优化,我们在实际使用中用 duls -l 看到的差异往往由此而来)。

inode 中并不直接存储文件内容,而是存储指向这些数据块的指针。对于小文件,inode 里有一组直接指针,指向保存数据的前几个块;当文件变大时,会引入 间接块——先用一个指针指向一个特殊的数据块,这个数据块里存的不是文件内容,而是更多指向数据块的指针。文件系统通过这种多层索引的方式,既能高效管理小文件,也支持超大文件。

inode 表与超级块

一个分区在格式化时,就会划分出固定的区域来存放所有 inode(称为 inode 表),同时还有一个 超级块(superblock) 记录整个文件系统的全局信息,如块大小、inode 总量、空闲块数等。因此,一个文件系统能容纳的文件总数,在创建时就受限于 inode 表的预设大小。如果耗尽所有 inode,即使磁盘空间还很充裕,也无法再创建新文件。

可以用 df -i 查看 inode 的使用情况:

df -i /

输出会显示总 inode 数、已用和可用 inode。当 IUse% 达到 100% 时,创建文件会失败,报错“No space left on device”,而 df -h 可能显示磁盘仍有剩余空间。这种情况在存放海量小文件(如邮件队列、缓存目录)的场景中十分常见。

硬链接与软链接:inode 的不同“面具”

硬链接 是多个目录项(文件名)指向同一个 inode。内核通过 inode 里的链接计数追踪有多少个名字引用它。创建硬链接:

ln file1 file2

此时,file1file2 在文件系统层面完全平等,删除其中一个并不会删除数据,只有当链接计数降为 0 且没有进程打开文件时,内核才会释放该 inode 和关联的数据块。硬链接不能跨越文件系统,也不能指向目录(防止形成环)。

软链接(符号链接) 自身是一个独立的小文件,拥有自己的 inode 和数据块,其内容存储的是目标文件的路径字符串。

ln -s /path/to/target linkname

删除目标文件后,软链接仍然存在但会“悬空”,访问时报错。软链接可以跨文件系统,也可以指向目录,比硬链接灵活,但多一次寻址开销。

删除文件时究竟发生了什么?

执行 rm 命令并不是立即擦除数据,而是:

  1. 从目录中移除文件名,将 inode 的链接计数减 1;
  2. 如果链接计数为 0 且无进程占用,释放 inode 和数据块(标记为空闲,内容仍在盘片上,可被后续写入覆盖);
  3. 如果进程仍在使用该文件(如日志服务打开了文件),数据会继续存在,直到进程关闭,这就是为什么有些服务可以“删除日志却继续写”的原因,也是 lsof 恢复被误删文件的原理基础。

小结

  • inode 是文件的“户口本”,包含权限、大小、时间、数据块指针等所有元数据,但不包含文件名。
  • 数据块 是实际存储文件内容的磁盘单位。
  • ls -istatdf -i 是掌握 inode 状态的三个核心命令。
  • 理解硬链接和软链接的差异,关键就在于是否共享同一个 inode。
  • 遇到“磁盘未满但无法新建文件”,第一时间检查 df -i 是否 inode 耗尽。

掌握这些底层结构,不仅能帮你快速定位日常工作中的“诡异”问题,也为进一步学习文件系统故障修复、磁盘配额和性能调优打下坚实的地基。