Linux中文件系统

发布时间:2026/9/15 6:56:57
Linux中文件系统 磁盘物理结构扇区扇区是磁盘存储数据的基本单位512字节块设备特点操作系统不直接以扇区为单位管理文件扇区是磁盘硬件的概念。块文件系统的磁盘空间分配最小单位1 个块 连续多个扇区。例如块大小 4KB每个扇区 512B则 1 块 8 个扇区。保存文件实际数据内容。规则哪怕文件只有 1 字节也要占用至少 1 个块大文件占用多个块。简单理解扇区是磁盘硬件的最小格子块是 Linux 文件系统打包后的大格子Linux 管理磁盘时用这个大格子。inode(索引节点)inode不存文件内容只存文件的属性信息文件大小、权限、所有者、时间戳指向保存文件数据的块编号记录数据存在磁盘哪些块里每个文件唯一对应一个 inode 号。类比inode 是文件的档案卡片记录文件信息以及数据放在哪些块块是存放文件正文的格子扇区是硬盘底层最小物理碎片。总结扇区硬件最小单元磁盘硬件块文件系统分配单元Linux 格式化后inode文件信息索引不存文件内容CHS和LBA磁盘扇区寻址承接前面扇区 / 块 /inode概念两者都是定位磁盘上某一个扇区的寻址方案CHS 是老的三维物理坐标LBA 是现代一维线性编号Linux 现在用 LBACHS三个参数C Cylinder 柱面所有盘片上同一个半径的同心圆磁道叠在一起就是一个柱面。磁头臂移动一次性切换整个柱面。H Head 磁头对应盘片的盘面一个盘面一个磁头用来读这一面的磁道。S Sector 扇区磁道被切分出来的扇形小块就是图里你那张磁盘图的扇区定位步骤移动磁头臂到目标柱面 C→ 选中对应的磁头 H→ 盘片旋转等待目标扇区 S转到磁头下完成读写特点是早期 IDE 硬盘的寻址方式直接暴露磁盘物理几何结构给操作系统编号规则柱面 C、磁头 H 从 0 开始扇区 S 从 1 开始致命限制老式 BIOS 的 CHS 参数上限1024 柱面、16 磁头、63 扇区最多只能寻址8.4GB 硬盘大硬盘无法使用现代硬盘内部是 ZBR外圈磁道扇区更多CHS 的 “每磁道扇区数固定” 假设已经不符合真实硬件LBA把磁盘上全部扇区从头到尾从 0 开始连续编号成一串一维数字只需要一个数字就能定位一个扇区不再关心这个扇区在哪个柱面、哪个磁头。LBA0磁盘第一个扇区MBR 分区表就在 LBA0LBA1第二个扇区依次往后排磁盘固件硬盘自己内部芯片自动把 LBA 编号翻译成硬盘真实物理位置操作系统不用管硬盘内部几何结构特点一维线性地址只需要一个数字定位扇区简单突破容量限制28 位 LBA最大寻址 128GB48 位 LBA现代硬盘标准理论支持超大容量PB 级别TB 级硬盘都用 48 位 LBALinux、GPT 分区、SATA、NVMe 全部默认使用 LBA 寻址屏蔽硬件细节不管硬盘内部物理布局是什么样操作系统只需要给 LBA 编号即可读写扇区CHSLBA转换公式前提每柱面扇区数 磁头数 × 每磁道扇区数\(\boldsymbol{LBA C \times H_{max} \times S_{max}H \times S_{max}(S-1)}\)C 柱面号H 磁头号S 扇区号S 从 1 开始所以减 1举个例子Hmax16 磁头Smax63 扇区 / 磁道 CHS (C0,H0,S1) → LBA0也就是硬盘第一个扇区项目CHSLBA寻址维度三维C,H,S 三个数一维单个数字原理基于磁盘物理几何扇区线性顺序编号屏蔽物理细节编号起点C/H 从 0扇区 S 从 1LBA 从 0 开始容量上限~8.4GB传统 BIOS 限制48 位 LBA 支持超大硬盘使用时代老式 IDE 硬盘、MBR 早期现代硬盘、Linux、GPT 分区逻辑结构将磁盘这样展开就形成了一个面柱⾯上的每个磁道扇区个数是⼀样的 这不就是⼆维数组CHS转成LBA• 磁头数*每磁道扇区数单个柱⾯的扇区总数• LBA柱⾯号C*单个柱⾯的扇区总数磁头号H*每磁道扇区数扇区号S-1• 即LBA柱⾯号C*(磁头数*每磁道扇区数)磁头号H*每磁道扇区数扇区号S-1• 扇区号通常是从1开始的⽽在LBA中地址是从0开始的• 柱⾯和磁道都是从0开始编号的• 总柱⾯磁道个数扇区总数等信息在磁盘内部会⾃动维护上层开机的时候会获取到这些参 数。LBA转成CHS• 柱⾯号CLBA//(磁头数*每磁道扇区数)【就是单个柱⾯的扇区总数】• 磁头号H(LBA%(磁头数*每磁道扇区数))//每磁道扇区数• 扇区号S(LBA%每磁道扇区数)1• //: 表⽰除取整文件系统宏观认识核心思想把磁盘分区划分为多个块组Block Group每个块组独立保存元数据 数据目的是减少磁盘寻道提升性能同时超级块、GDT 会做多份备份防止磁盘损坏丢失文件系统信息。视图认识文件系统1. Disk整块磁盘磁盘最开头是MBR主引导记录后面划分出 4 个主分区Partition1~4。MBR位于磁盘第一个扇区包含引导代码 分区表记录磁盘上有哪些分区、分区起始位置。一块硬盘可以切分成多个独立分区。2. Partition单个分区每个分区由两部分组成Boot SectorEXT2 File SystemBoot Sector分区引导扇区存放分区引导代码。EXT2 File System这个分区内部就是我们的 ext2 文件系统。一个分区只能有一种文件系统这里是 ext2。3. EXT2 File Systemext2 文件系统把整个分区平均切分成很多个Block Group块组Block Group0、Block Group1 … Block Group N。划分块组目的把文件尽量放在同一个块组减少磁盘寻道距离超级块 / GDT 在多个块组备份提升容错。4. Block Group块组核心将整个分区均等切分成若干块组。 每个块组都拥有一套完整的管理信息超级块、GDT、位图、inode 表、数据块。每个块组内部固定顺序Super Block→GDT→Block Bitmap→inode Bitmap→inode Table→Data BlocksSuper Block 超级块保存整个文件系统全局信息块大小、总 inode 数、总块数不是只属于当前块组多个块组会备份超级块。GDT 块组描述符表记录所有块组的信息每个块组里位图、inode 表的磁盘位置、空闲块数量。Block Bitmap 块位图bit 标记 Data Block 是否空闲。inode Bitmap inode 位图bit 标记 inode 是否空闲。inode Table inode 表连续存放一堆 inode 节点。Data Blocks 数据块真正存放文件内容 / 目录项的地方。5. inode Tableinode 表图中最下层inode 表是由一条条 inode 记录组成inode 不存储文件名单个 inode 包含字段Inode Numberinode 编号文件唯一标识File Type文件类型普通文件 / 目录 d / 软链接等Permission权限如 644、755Link count硬链接计数UID / GID文件所属用户、所属组 IDsize文件大小pointer数据块指针数组直接 / 间接指针指向 Data Blocks找到文件内容结合图的重点考点总结磁盘→分区→ext2 文件系统→多个块组是层层包含的关系。目录是特殊文件目录的 inode 指向 Data Block数据块里面存目录项文件名 inode 号。查找文件路径时先在目录的数据块通过文件名拿到 inode 号再去 inode 表读取 inode再用 inode 的 pointer 找到文件数据块。文件名存在目录的数据块inode 里面没有文件名。inode和datablock映射inode 里面保存了15 个指针用来定位文件的数据块分为 4 类12 个直接块指针 1 个一级间接指针 1 个二级间接指针 1 个三级间接指针1. 12 个直接块指针前 12 项指针直接指向普通数据块读取文件前 12 个块时inode 里拿到指针 → 直接访问对应数据块 ✅ 优点一次磁盘 IO 就读到数据速度快适合小文件❌ 局限只能覆盖文件的前 12 块2. 一级间接块索引表指针第 13 个指针这个指针不指向文件数据而是指向一块「索引块数据块索引表」索引块里面存储一堆指针每一个指针再指向真正的文件数据块 读取流程inode → 一级间接指针 → 索引表块 → 多个数据块指针 → 文件数据块3. 二级间接块索引表指针第 14 个指针两层索引inode → 二级间接指针 → 第一层索引块 → 多个一级索引块 → 数据块指针 → 文件数据块先找到第一层索引块里面存多个一级间接索引块的地址再去每个一级索引块拿到最终数据块指针。4. 三级间接块索引表指针第 15 个指针三层嵌套索引inode → 三级间接指针 → 一级索引块 → 二级索引块 → 一级索引块 → 文件数据块用来支持超大文件层级越多访问文件需要读的磁盘块越多速度越慢。计算前提约定块大小1KB 1024 Byte每个块指针占4 Byte存放一个块号核心公式一个索引块最多能放多少个指针 块大小 ÷ 单个指针大小每个指针对应 1 个数据块每个数据块大小 块大小第一步算一个索引块可以存多少指针指针数量 1024 B ÷ 4 B 256 个指针 1 个索引块里最多写256 个块指针每个指针指向 1 个真实数据块。1直接块12 个inode 里直接放 12 个指针每个指针直接指向数据块。 总大小12 × 1KB 12KB✅ 对应文件前 12KB 内容访问只需要 1 次读盘。2一级间接第 13 个指针inode 里这1 个指针指向索引块索引块里面存 256 个数据块指针。一级间接能管理的数据块数量 256 块 一级间接空间 256 × 1KB 256KB 文件从 12KB ~ (12256) KB 这一段走一级间接。 读取流程读索引块1 次 IO 读数据块1 次 IO一共 2 次磁盘 IO。3二级间接第 14 个指针inode 的这 1 个指针指向一级索引块 这个一级索引块里面有 256 个指针每个指针又指向一个一级索引块 每一个下层索引块又能放 256 个数据块指针。二级间接的数据块总数 256 × 256 二级间接空间 256 × 256 × 1KB 65536 KB 64MB读取要读 3 次磁盘顶层索引块→下层索引块→数据块4三级间接第 15 个指针嵌套三层索引块三级间接的数据块总数 256 × 256 × 256 三级间接空间 256³ × 1KB 16777216 KB 16GB✅ ext2 文件最大总容量全部加起来总 直接 一级间接 二级间接 三级间接 12KB 256KB 64MB 16GB数据块 Data Block存放文件真实内容普通文件、目录项索引块索引表块就是一级 / 二级间接里那个 “存放一堆指针清单” 的块它本身也是磁盘上的一个块目录与文件名• ⽬录也是⽂件但是磁盘上没有⽬录的概念只有⽂件属性⽂件内容的概念。• ⽬录的属性不⽤多说内容保存的是⽂件名和Inode号的映射关系1. 目录是什么目录文件夹是特殊文件它也有自己独立的inodeinode 里面同样有那套权限、大小、15 个直接 / 间接块指针和普通文件 inode 结构完全一样目录 inode 的指针指向的Data Block数据块不存文章 / 图片内容专门存放「目录项」。2. 目录项directory entry是什么目录的数据块里存很多条目录项每一条目录项结构【文件名】 【inode编号】 类型 长度✅ 关键点文件名只存在目录文件的数据块里面inode 里面只有文件属性、块指针完全没有文件名同一个 inode 号可以出现在多个目录项里这就是硬链接多个不同文件名指向同一个 inode3. 查找文件的完整过程路径解析例如/mydir/test.txt根目录固定 inode 号 2读取根目录 inode拿到它的数据块在根目录的数据块目录项列表查找名字mydir→ 得到 mydir 的 inode 编号读取mydir这个目录的 inode拿到 mydir 目录的数据块在 mydir 的数据块里查找名字test.txt→ 拿到 test.txt 的 inode 编号读取 test.txt 的 inode用 inode 里的块指针找到存放文本内容的数据块路径解析就是一层一层打开目录文件在目录项里匹配文件名拿到 inode 号。4. 结合前面 inode 映射知识串起来目录 特殊文件 → 有 inode目录 inode 的指针 → 指向目录的数据块目录的数据块存放目录项文件名 inode编号通过文件名拿到 inode 号 → 去 inode 表取出 inodeinode 里面的 15 个指针直接、一级、二级间接→ 找到文件内容的数据块5. 常见考点❌ 错误文件名保存在 inode 中 ✅ 正确文件名保存在目录文件的数据块.代表当前目录本身..代表父目录这两个也是目录项硬链接原理不同目录项文件名不同但inode 编号相同指向同一个文件 inode简单类比目录就像一本书目录文件书的 inode这本书的属性大小、权限书的书页数据块写满目录清单目录项清单写着「名字 页码 (inode 号)」 你看书输入文件名就是在清单里搜索名字拿到 inode 号再找到真正文件。举例访问/mydir/test.txt开始要打开 /mydir/test.txt ↓ ① 找到根目录inode2 ↓读取根目录的inode ↓通过inode里的块指针读取根目录【数据块】 ↓根目录数据块存放一堆目录项文件名 inode号 在目录项里查找名字mydir ↓查到mydir → inode27 ↓ ② 拿到mydir的inode编号27 ↓读取inode表中编号27的inodemydir目录的inode ↓通过这个inode的块指针读取mydir目录的【数据块】 ↓mydir的数据块存放它自己的目录项列表 在目录项里查找名字test.txt ↓查到test.txt → inode15 ↓ ③ 拿到test.txt的inode编号15 ↓读取inode表中编号15的inode普通文件test.txt的inode ↓inode里面有15个块指针直接/一级/二级间接 ↓用指针找到存放txt文本内容的数据块 ↓读取数据块内容得到文件内容 结束路径缓存问题1Linux磁盘中存在真正的⽬录吗答案不存在只有⽂件。只保存⽂件属性⽂件内容问题2访问任何⽂件都要从/⽬录开始进⾏路径解析答案原则上是但是这样太慢所以Linux会缓存历史路径结构问题3Linux⽬录的概念怎么产⽣的答案打开的⽂件是⽬录的话由OS⾃⼰在内存中进⾏路径维护Linux中在内核中维护树状路径结构的内核结构体叫做 struct dentry• 每个⽂件其实都要有对应的dentry结构包括普通⽂件。这样所有被打开的⽂件就可以在内存中 形成整个树形结构• 整个树形节点也同时会⾪属于LRU(LeastRecentlyUsed最近最少使⽤)结构中进⾏节点淘汰• 整个树形节点也同时会⾪属于Hash⽅便快速查找• 更重要的是这个树形结构整体构成了Linux的路径缓存结构打开访问任何⽂件都在先在这 棵树下根据路径进⾏查找找到就返回属性inode和内容没找到就从磁盘加载路径添加dentry 结构缓存新路径挂载分区Linux 的目录树是一套虚拟的、统一的全局目录树。磁盘分区带有 ext2 文件系统本身是独立的一套文件系统它不会自动并入全局目录树必须执行挂载mount把这个分区的「根目录」挂到全局目录树的某一个空目录挂载点上我们才能访问分区内的文件。挂载点就是全局目录树上一个预先存在的空目录挂载之后这个目录就不再访问原来目录内容转而访问分区文件系统的根。举例子比如mount /dev/sdb1 /mnt/mydisk/dev/sdb1磁盘分区里面是 ext2 文件系统它自己有独立的块组、超级块、inode 表有属于自己的根 inode/mnt/mydisk挂载点全局目录树上的空目录挂载完成后 访问/mnt/mydisk等价于访问sdb1 这个 ext2 分区的根目录。 分区内部的文件/a.txt在主机全局目录树上的路径就是/mnt/mydisk/a.txt✅ 挂载底层流程配合前面 ext2 结构图mount 命令读取分区/dev/sdb1读取分区里 ext2 文件系统的超级块 Super Block校验文件系统。找到这个 ext2 分区自己的根 inodeinode2。在内核的全局目录树里把挂载点目录/mnt/mydisk和这个分区的根 inode 做关联。之后当你访问/mnt/mydisk时内核会切换到这个分区的文件系统使用该分区自己的块组、inode 表、位图做路径解析。⚠️重点 不同分区有完全独立的 inode 编号空间。 分区 A 的 inode2 和 分区 B 的 inode2不是同一个 inodeinode 编号只在同一个文件系统同一个分区内部有效。卸载 umountumount /mnt/mydisk切断全局目录树和分区文件系统的关联。内存中该文件系统元数据、dcache 缓存被清理。卸载后/mnt/mydisk变回原来普通空目录访问不到分区里的文件。实验现象对应你大纲 3-8-1不挂载直接去看磁盘镜像 / 分区底层只能看到块、超级块、inode 这些原始二进制不能用ls、cat访问文件。挂载之后内核把这个 ext2 文件系统接入全局目录树就可以像普通目录一样ls /mnt/mydisk执行路径解析查找 inode、数据块。考试结论3-8-2Linux 只有一颗统一的虚拟目录树所有磁盘分区都需要挂载才能接入这颗目录树。挂载点只是全局树上的目录挂载后访问挂载点就访问该分区文件系统的根。inode 号只在单个文件系统内唯一跨分区inode 号会重复没有意义。一个分区同一时间只能挂载到一个挂载点一个挂载点同一时间只能挂载一个分区。文字流程图执行 mount /dev/sdb1 /mnt/mydisk ↓ 读取分区/dev/sdb1 → 读取ext2超级块确认是ext2文件系统 ↓ 取出该分区文件系统的根inodeinode2 ↓ 内核关联全局目录树中的挂载点 /mnt/mydisk ↔ 分区的根inode ↓ 后续访问 /mnt/mydisk/xxx ↓ 内核使用【这个分区自己的块组、inode表】进行路径解析 ↓ 读取分区内文件的inode、数据块得到文件内容常见易错点❌ 错误挂载是把磁盘里的文件复制到挂载点目录 ✅ 正确不是拷贝只是建立内核层面的关联映射文件仍然保存在磁盘分区上现在我们 ext2 整条链路串起来磁盘 MBR→分区→ext2 文件系统多个块组→块组内超级块 / GDT / 位图 /inode 表 /data block → inode 块指针映射 →目录项保存文件名 →路径解析 →分区挂载接入全局目录树。总结ext2 文件系统整条完整链路磁盘 → 分区 → ext2 文件系统 → 块组 → inode → 目录项 → 路径解析 → 挂载 适合直接背应付简答、画图题一、磁盘与分区宏观结构整块磁盘开头是MBR 主引导记录包含引导代码和分区表把磁盘划分为多个分区。 每个分区内部可以格式化为 ext2 文件系统分区内包含引导扇区 ext2 文件系统。ext2 会把整个分区平均切分成多个块组 Block Group。划分块组目的文件尽量放在同一块组减少磁盘寻道超级块、GDT 做多副本提升容错。二、块组内部 6 个组成按磁盘顺序Super Block 超级块存放整个文件系统全局信息块大小、总块数、总 inode 数量不属于单个块组在多个块组留有备份用于故障恢复。GDT 块组描述符表记录每一个块组信息块位图、inode 位图、inode 表的磁盘位置以及空闲块、空闲 inode 数量。Block Bitmap 块位图bit 标记数据块是否空闲1 占用0 空闲用来分配 / 回收数据块。inode Bitmap inode 位图bit 标记 inode 节点是否空闲1 占用0 空闲管理 inode 分配回收。inode Table i 节点表连续存放大量 inode 节点。Data Blocks 数据块存放文件真实内容目录文件的数据块存放目录项。三、inode索引节点inode 记录文件元数据不存储文件名。 inode 包含i 结点编号、权限、属主、时间戳、文件大小以及15 个块指针i_block [15]。 15 个指针分为 4 类实现数据块映射12 个直接块指针指针直接指向数据块小文件访问速度最快。一级间接指针指向索引块索引块内存储多个数据块指针。二级间接指针两层索引块嵌套用于更大文件。三级间接指针三层索引块嵌套支持超大文件。层级越多读取磁盘次数越多访问速度越慢。计算题核心公式块大小 1KB指针占 4B 单个索引块可存放指针数量 1024/4 256 个指针直接12×1KB 12KB一级间接256 ×1KB256KB二级间接256×256×1KB64MB三级间接256×256×256×1KB16GB四、目录、文件名、目录项目录是一种特殊文件目录本身有自己的 inode。 目录 inode 的块指针指向目录的数据块目录的数据块存放多条目录项。 目录项结构文件名 inode编号✅重点文件名保存在目录的数据块inode 里面没有文件名。.代表当前目录 inode..代表父目录 inode。 硬链接原理多个不同目录项文件名不同但inode 编号相同指向同一个 inode。五、路径解析例/mydir/test.txt根目录 inode 固定为 2读取根目录 inode通过块指针读取根目录数据块在目录项中查找mydir拿到 mydir 的 inode 号。读取mydir目录的 inode读取 mydir 的数据块在目录项查找test.txt拿到 test.txt 的 inode 号。读取 test.txt 的 inode使用 inode 内部 15 个块指针找到存放文件内容的数据块读取文件数据。dcache 目录项缓存内核将已经解析成功的文件名→inode号映射缓存到内存避免重复磁盘 IO加速路径查找。缓存位于内存重启失效。六、分区挂载 mountLinux 拥有单一、统一的全局虚拟目录树。 磁盘分区上的 ext2 是独立文件系统不会自动并入全局目录树必须挂载。挂载点全局目录树上预先存在的空目录。挂载后访问该挂载点等价于访问这个分区文件系统的根目录。挂载底层读取分区超级块拿到该分区根 inode在内核建立【挂载点目录 ↔ 分区根 inode】的映射。⚠️inode 编号只在同一个文件系统同一个分区内部唯一不同分区 inode 号可以重复。卸载 umount切断全局目录树和分区文件系统关联清空相关元数据缓存。易错点挂载不是复制文件只是内核建立映射关系文件数据依旧保存在磁盘分区。七、ext2 整体总结ext2 将磁盘分区划分为多个块组每个块组包含超级块、GDT、块位图、inode 位图、inode 表、数据块。 inode 保存文件属性与数据块指针不存文件名文件名保存在目录文件的数据块目录项。访问文件需要逐级进行路径解析dcache 缓存加速查找。 分区的 ext2 文件系统必须挂载到 Linux 全局目录树的挂载点才能被用户访问。inode 通过直接 / 多级间接指针完成文件到磁盘数据块的映射。补充高频简答真题Qinode 里面存放文件名吗 A不存放。文件名存放在目录文件的数据块的目录项中。inode 存放文件元数据权限、大小、时间戳和数据块指针。Q什么是块组为什么要划分块组 A将 ext2 整个文件系统均等切分成多个块组。目的文件尽量存放在同一块组减少磁盘寻道时间超级块、GDT 多副本保存提升文件系统容错能力。Q简述 ext2 中打开/a/b.txt的路径解析过程 A从根目录 inode2 开始读取根目录数据块查找目录项得到 a 目录 inode读取 a 目录 inode读取 a 目录数据块查找 b.txt 的 inode读取 b.txt 的 inode利用块指针读取文件数据块获取内容。Q挂载的作用是什么 ALinux 只有一棵全局目录树磁盘上独立的 ext2 文件系统需要挂载将分区根目录关联到全局目录树的挂载点才能访问分区内的文件。挂载只是建立映射不会拷贝文件。Q直接块和间接块的区别 A直接块指针直接指向数据块访问速度快适合小文件间接块指针指向索引块索引块再存放数据块指针用来寻址更大的文件层级越多 IO 次数越多速度越慢。