【Linux第十四章】文件系统
前言 在日常开发里我们几乎每天都在和文件打交道打开源码、读取日志、写入配置、删除临时文件。但从操作系统的视角看磁盘上天然存在的并不是“文件”这种概念底层真正能被访问的是一块一块的存储单元。文件系统的价值正是在这种底层块设备之上建立出一套便于命名、组织、查找和管理数据的规则。很多初学者在学习 Linux 文件系统时容易把一堆术语割裂开来记扇区、块、LBA、inode、目录项、挂载、硬链接、软链接……单个概念似乎都不难但一旦连起来就常常不知道它们之间到底是什么关系。这篇文章就按照“磁盘如何定位数据 → 文件系统如何组织数据 → Linux 如何通过路径找到文件”的主线把文件系统的关键知识串起来。读完之后ls -li、df -h、mount、ln、ln -s这些命令背后的模型会更清晰。一. 文件系统到底在解决什么问题 文件系统首先要解决的不是“怎么显示文件名”而是如何在速度慢、访问粒度固定、结构复杂的存储设备上高效地组织和定位数据。1.1 为什么存储设备天然比 CPU 慢传统机械硬盘依赖盘片旋转和磁头移动来完成读写这里面存在明显的机械寻道和旋转延迟因此它的访问速度天生不可能接近 CPU 和内存。即便到了没有机械结构的 SSD存储访问依然远慢于寄存器、缓存和主存。这意味着操作系统不能把底层存储设备的复杂性直接暴露给应用程序而是必须额外做两件事一是把底层设备抽象成统一的逻辑访问模型二是通过缓存、预读、延迟写回等手段尽量平衡速度差距。因此文件系统本质上是一层抽象层。它屏蔽了底层介质的复杂结构让用户看到的是“文件”和“目录”而不是柱面、磁头、扇区或者闪存页。1.2 为什么磁盘被称为块设备磁盘之所以叫块设备核心原因在于它不是按“一个字节”或“一个文件”进行原子读写而是按固定大小的块状单位访问。这里需要区分两个容易混淆的概念概念所属层次含义常见大小sector扇区设备层存储设备的基本寻址/传输单位512B或4KiBblock文件系统块文件系统层文件系统分配和管理数据的基本单位常见为4KiB很多资料会把“扇区”和“块”混着说这在入门阶段可以接受但严格来说两者不是同一个概念。sector更偏硬件block更偏文件系统。也正因为底层按块访问所以哪怕只改一个很小的内容最终也常常要落到某个块上的读写。1.3 文件系统到底提供了什么能力从使用者视角看文件系统至少提供了下面几类能力用文件名和路径代替底层逻辑块号用目录树来组织数据而不是让用户手工维护块编号记录权限、属主、时间戳等元信息维护空闲空间和已使用空间支持通过路径快速定位到具体文件内容。所以文件系统做的事情本质上是把“对存储空间的管理”转成“对逻辑对象的管理”。这也是为什么用户看到的是文件、目录和路径而内核真正管理的是 inode、目录项和数据块。二. 从 CHS 到 LBA磁盘上的数据是怎么定位的 理解文件系统之前先要搞清楚一个更底层的问题数据在磁盘上到底是怎么被找到的。2.1 早期的 CHS 寻址模型在传统机械硬盘模型里磁盘可以粗略理解为由多个盘片组成每个盘片表面有很多同心圆磁道每条磁道又被分成若干扇区。早期系统经常使用CHS来描述一个扇区的位置CCylinder柱面HHead磁头SSector扇区。这种方式非常贴近物理结构便于理解机械磁盘是如何定位数据的。但随着磁盘容量增大、控制器能力增强操作系统已经不再适合直接使用这种“按几何结构寻址”的方式。2.2 为什么现代系统主要使用LBA现代系统更常见的是LBALogical Block Address逻辑块地址。它不再要求操作系统关心具体是哪个柱面、哪个磁头、哪个扇区而是把整个磁盘抽象成一个从0开始编号的线性块数组第0块第1块第2块……这样一来操作系统面对的就不再是复杂的机械几何结构而是一个逻辑上连续的编号空间。至于LBA如何映射到底层真实物理位置通常由设备固件、控制器或者更底层驱动负责。这一层抽象非常关键。因为从这里开始操作系统对磁盘的管理就逐渐从“管理物理结构”转成了“管理逻辑块数组”。后续文件系统再在这个逻辑块数组之上建立自己的块分配规则、目录结构和元数据体系。2.3 从物理设备到文件的抽象链路把整个过程串起来可以用下面这条链路来理解物理磁盘 - 设备层扇区/页 - LBA 逻辑块地址 - 文件系统块 - 文件与目录也就是说文件系统并不是“直接去找文件”而是先通过元数据找到该文件占用了哪些逻辑块再根据这些块号去读出真正的数据内容。三. 分区、格式化与挂载为什么磁盘不能直接拿来存文件 即便磁盘已经能按LBA访问了也还远远不够。因为“能访问存储空间”和“能按文件的方式管理存储空间”是两回事。3.1 分区先划定管理边界一整块磁盘通常不会作为一个完全无边界的整体直接使用而是会先被划分成多个partition分区。不同分区可以承载不同用途也可以使用不同文件系统例如一个分区使用ext4一个分区使用xfs一个分区作为swap一个分区用来放引导相关数据。分区的意义本质上是一种“先分治、再管理”的思想。先把大磁盘划成几个边界明确的区域再让每个区域各自维护自己的文件系统结构。3.2 格式化不是简单清空而是写入文件系统元数据很多人把格式化理解成“把数据删干净”这其实只是表象。更准确地说格式化是在一个分区里写入某种文件系统所需要的管理结构例如超级块位图inode表数据区其他和块组管理相关的元数据。所以格式化的本质不是“擦除”而是“初始化文件系统”。只有这些结构建立起来之后这块分区才真正具备“按照文件来管理数据”的能力。3.3 挂载把文件系统接到 Linux 目录树上分区格式化完成后也不能自动通过路径访问还必须经过挂载。挂载的本质是把某个文件系统接入当前系统统一的目录树。sudomount/dev/sdb1 /mnt这条命令并不是“把文件复制到/mnt”而是把/dev/sdb1上的文件系统挂接到目录树中的/mnt节点。挂载之后再访问/mnt/a/b.txt实际上访问的就是这个分区里的文件。查看当前挂载关系时常用命令是df-h其中Mounted on这一列就展示了各个文件系统当前被挂载到哪个目录节点。学习资料里的示例里根文件系统被挂载到了/这正是 Linux 统一目录树模型的直接体现。 避坑指南分区、格式化、挂载是三个不同阶段千万不要混为一谈。分区划定存储边界格式化写入某种文件系统所需的结构挂载把这个文件系统接到当前目录树上。四. ext 文件系统的核心组织inode、位图和数据块 ⚙️理解 Linux 文件系统时经典的ext2模型非常适合作为教学入口。虽然现代 Linux 更常见的是ext4但很多核心思想在ext家族中是一脉相承的。4.1 一个分区内部通常包含哪些关键结构一个典型的ext文件系统通常会包含这些关键部分superblock超级块group descriptor table块组描述符表block bitmap数据块位图inode bitmapinode 位图inode tableinode 表data blocks数据区。为了便于管理文件系统还会把空间划分成多个block group块组。这样可以让相关的元数据和数据尽量保持局部性从而降低分配和查找的开销。有些材料会提到boot block。更准确地说它通常是文件系统前部保留给引导代码或兼容用途的区域不应简单理解成“文件系统靠它来启动”。真正描述整个文件系统状态的核心元数据还是superblock及其相关结构。4.2 超级块、位图、inode 表各自负责什么这些结构分工非常明确结构作用superblock保存文件系统整体信息如块大小、总块数、inode 总数等inode bitmap标记哪些 inode 已被分配block bitmap标记哪些数据块已被占用inode table保存每个 inode 的元信息data blocks保存文件真实内容或目录项数据其中superblock可以理解为整个文件系统的总说明书。它非常重要因此实际实现中通常还会保留若干副本用来提高文件系统损坏后的恢复能力。4.3inode保存的到底是什么inode是 Linux 文件系统中最关键的对象之一。它保存的是文件本体的元信息而不是文件名。通常会包含以下内容文件类型权限位属主与属组文件大小时间戳链接计数指向数据块的地址信息。这里一定要记住一个非常核心的结论inode不保存文件名。文件名存在目录项中目录项保存的是“名字到 inode 编号”的映射关系。也正因此在 Linux 世界里“文件名”和“文件对象”其实是分开的。ls -li之所以能看到一列 inode 编号正是在帮助你观察这种映射关系。4.4 文件内容是怎么通过inode找到的为了快速定位文件内容inode内部会保存一组块指针。以经典ext2模型为例inode里的i_block通常有15个入口下标0 ~ 11直接块下标12一级间接块下标13二级间接块下标14三级间接块。很多学习笔记里会写成“0-12 直接映射、13 间接映射、14 三级映射”这是一种口语化记法但严格来说数组下标应该按上面的方式理解。这样设计的好处很明显小文件通常只依赖直接块访问开销低文件变大后再借助一级、二级、三级间接块扩展寻址范围。五. 目录、路径与dentry内核到底是怎么找到文件的 理解了inode之后还需要再回答一个问题用户平时输入的是路径内核最终却靠inode和数据块定位内容那路径是怎么被翻译过去的5.1 目录本质上也是文件在 Linux 中目录并不是某种脱离文件系统的特殊容器它本质上仍然是一种文件。只不过目录文件的数据区里存放的不是普通业务数据而是一组目录项。每个目录项都可以大致理解为文件名 - inode 编号因此目录真正的作用是维护名字和 inode 之间的映射。用户看到的是名字内核最终拿到的是 inode。5.2 路径解析其实是逐级查目录假设要访问这样一个路径/home/user/code/main.cpp内核的大致处理过程可以理解为路径 /home/user/code/main.cpp从根目录或挂载点开始查找 home 目录项得到 home 对应 inode继续查找 user继续查找 code找到 main.cpp 对应 inode根据 inode 读取数据块这说明两个关键事实第一路径解析本质上是目录层层展开的过程第二真正定位文件内容时依赖的不是文件名本身而是文件名背后的 inode 和数据块。5.3 为什么高频路径会更快dentry cache如果每次都从根目录一路向下解析代价会很高。因此 Linux 在内核里引入了目录项缓存也就是常说的dentry cache。它缓存的是路径解析过程中常用的目录项结果从而减少重复查找。同一个路径被高频访问时后续解析速度往往会更快。可以把它简单理解为inode负责描述“这个文件是什么数据在哪里”dentry负责描述“这个名字映射到谁”。两者并不等价但会在路径解析过程中紧密配合。六. 硬链接与软链接同样像“别名”本质却完全不同 链接机制是 Linux 文件系统里非常容易混淆的一部分因为它们表面看起来都像是在给文件取别名但内部实现差异非常大。6.1 硬链接多个目录项指向同一个inode硬链接不是复制文件也不是新建一个独立文件副本。它的本质是再创建一个目录项让另一个名字也指向同一个 inode。lnlog log.hard.link执行之后log和log.hard.link是两个文件名但它们对应同一个inode修改任意一个名字访问到的内容另一个都会同步体现。因此硬链接没有独立 inode。更准确地说它不是一个独立文件对象而是同一个文件对象的另一个名字。6.2 软链接它自己就是一个独立文件软链接则不同ln-slog log.soft.link软链接本身会拥有自己的 inode它保存的不是目标文件的数据内容而是目标文件的路径字符串。也就是说软链接更像一种“跳转指示”。这也是为什么软链接很像 Windows 里的快捷方式访问软链接时系统会先读出它指向的目标路径再继续去找真正的文件。6.3 两者最关键的差异对比项硬链接软链接是否有独立 inode否是指向对象直接共享同一个 inode保存目标路径跨文件系统通常不支持通常支持目标删除后只要仍有其他硬链接数据仍可访问往往失效变成悬空链接对目录的支持普通用户一般不能创建可以创建6.4 为什么 Linux 一般不允许给目录创建硬链接如果允许用户随意给目录创建硬链接整个目录树结构就可能从“树”变成“有环图”。一旦路径遍历出现环查找和递归遍历都可能陷入死循环。因此Linux 一般不允许普通用户对目录创建硬链接。目录中的.和..虽然本质上也体现了特殊的引用关系但它们属于文件系统内部维护的保留目录项不是普通用户可以随意构造的通用硬链接。6.5 文件什么时候才算真正被删除很多人以为执行rm a.txt后文件立刻就彻底不存在了。更准确的过程其实是删除一个目录项映射inode的链接计数减一当链接计数归零并且没有进程仍持有该文件的打开引用时相关数据块才会被真正回收。所以删除一个文件名不等于立刻删除文件内容。这也是硬链接能够成立的重要前提之一。七. 学习文件系统时最容易混淆的几个点 7.1inode和文件名不是一回事这是最核心、也最容易被忽略的点。文件名存在目录项里而inode代表的是文件对象本体及其元信息。一个文件对象可以有多个文件名因此不能把文件名直接等同于文件本体。7.2 “一个文件一个inode”要结合语境理解在入门教学里经常会说“一个文件对应一个 inode”。这句话并不算错但它更适合帮助初学者建立第一层理解。如果从严格语义上说应该表述为一个 inode 对应一个文件对象而一个文件对象可以被多个目录项引用。硬链接正是这种关系的直接体现。7.3 设备层最小单位和文件系统层最小单位不要混淆设备层有扇区、页等概念文件系统层有块、块组等概念。两层抽象不同职责也不同。如果在性能分析、空间分配或者 I/O 理解时把它们混为一谈后面的很多判断都会失真。7.4CHS更适合理解历史和原理LBA才是现代主流CHS非常适合帮助理解机械磁盘的物理布局但现代 Linux 和现代存储系统主要面对的是逻辑地址模型。学习CHS的价值更多在于帮助建立底层结构感而不是把它当成今天最常用的实际接口。总结 文件系统可以概括为一句话它把底层块设备上的离散存储空间组织成用户容易理解、程序容易使用、内核能够高效管理的命名数据体系。沿着这条主线许多零散知识点就能自然串起来磁盘之所以是块设备是因为它按固定粒度读写LBA把复杂的物理结构抽象成逻辑块数组便于操作系统统一管理分区负责划边界格式化负责初始化文件系统结构挂载负责把文件系统接入统一目录树inode保存的是文件元信息和块定位信息目录项保存的是文件名 - inode映射路径解析本质上是逐级查目录dentry cache则负责加速这个过程而硬链接与软链接虽然都像“别名”却分别对应“共享 inode”和“保存路径”两套完全不同的机制。真正把这些概念理解透之后再去看ls -li、df -h、mount、ln、ln -s这些命令就不再只是记住了用法而是能看清它们背后对应的文件系统模型。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2461011.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!