Linux——Ext系列文件系统

理解硬件

磁盘、服务器、机柜、机房

  • 机械磁盘是计算机中唯一的一个机械设备
  • 随机读写速度慢
  • 容量大,价格便宜

磁盘核心物理部件

  1. 盘片(Platter)
  • 磁盘的数据真正存储载体,材质为铝合金 / 玻璃基底,表面喷涂磁性涂层。
  • 数据以磁性磁极方向记录二进制 0、1,盘面正反两面都可存储数据。
  1. 磁头(Head)
  • 负责读取、写入盘面磁性数据的感应元件,每一张盘面都对应独立磁头。
  • 写入:改变盘面磁极方向;读取:感应磁极信号,转化为电信号数据。
  1. 磁臂(Arm)
  • 固定所有磁头的支架,可做径向伸缩摆动
  • 作用:带动磁头在盘片同心圆轨迹之间移动,切换不同磁道位置。
  1. 主轴电机(Spindle Motor)
  • 驱动所有盘片同步高速旋转的动力核心。
  • 转速单位:RPM 转 / 分钟,转速越高,数据读取等待时间越短。
  • 常见规格:家用 7200 转,企业服务器 10000 转、15000 转。
  1. 密封盘腔 + 外部电路板
  • 密封腔体:内部真空无尘,杜绝灰尘划伤高速运转的盘片,灰尘会直接造成磁盘坏道。
  • 电路板:磁盘的控制中枢,接收主板读写指令、缓存临时数据、转换电信号与磁信号。

磁盘的存储结构




注意:传动臂上的磁头是共进退的

1. 磁道 Track

  • 形成原理:盘片高速旋转,磁头保持静止,在盘面划过一圈同心圆轨迹,即为一条磁道。
  • 作用:磁头定位到指定磁道,才能继续读取内部扇区数据。

2. 扇区 Sector

  • 磁盘最小物理存储单元
  • 传统标准扇区:512 字节
  • 形态:盘片被径向切割成无数扇形小块,每一块就是一个扇区
  • 读写约束:硬件只能整扇区读写,哪怕只修改 1 个字节,也要读取整个扇区、修改后再整扇写回

3. 柱面 Cylinder

  • 一块硬盘内部所有盘片上,半径完全相同的多条磁道,纵向堆叠形成一个虚拟圆柱面,称为柱面

如何定位一个扇区呢?(CHS地址定位法)

  1. 定位柱面:磁盘控制器驱动音圈电机,带动磁臂径向移动,将磁头对准指定柱面
  2. 选定磁头 :电路切换,启用对应编号的磁头,对准目标盘面
  3. 等待扇区轮转:盘片高速旋转,直到目标编号扇区转动到磁头正下方

计算磁盘容量公式:
磁盘总容量 = 磁头数 × 柱面数(磁道数) × 每磁道扇区数 × 单扇区字节数

磁盘的逻辑结构

理解过程


真实过程

所以,磁盘的真实情况是:

磁道:

某一盘面的某一磁道展开:

即:一维数组

柱面:

整个磁盘所有盘面的同一个磁道,即柱面展开:

  • 柱面上的每个磁道,扇区个数是一样的
  • 这不就是二维数组吗

整盘:

  • 整个磁盘不就是多张二维的扇区数组表(三维数组?)

所以,寻址一个扇区:先找到哪一个柱面(Cylinder) ,再确定柱面内哪一个磁道(其实就是磁头位置,Head),最后确定扇区(Sector),所以就有了 CHS

总结:

不管是二维数组还是三维数组,其实都是一维数组:

所以,每一个扇区都有一个下标,我们叫做 LBA(Logical Block Address) 地址,其实就是线性地址

CHS 寻址 与 LBA 寻址

CHS、LBA 是磁盘两种扇区定位编码体系 ,核心作用只有一个:唯一确定磁盘上任意一个物理扇区

  • CHS :贴合磁盘机械物理结构的三维坐标寻址,老式磁盘标准
  • LBA :抹平物理差异的一维线性逻辑寻址,当前 Linux、文件系统、硬盘通用标准

上层操作系统、文件系统只使用 LBA;磁盘硬件底层最终会转换为 CHS 完成机械定位,二者可以相互换算

CHS 三维寻址

全称与坐标形式

  • Cylinder (柱面) + Head (磁头) + Sector (扇区)
    用一组三维坐标 (C, H, S) 锁定单个扇区。

CHS 物理定位全过程

  1. 控制器依据柱面号,驱动磁臂移动到目标径向位置
  2. 电路切换,启用指定编号磁头,对准对应盘面
  3. 盘片高速旋转,等待目标扇区转动至磁头正下方
  4. 锁定位置,执行数据读取或写入操作

寻址容量瓶颈

早期 CHS 采用固定位数存储坐标数值,可表示的柱面、磁头、扇区数量有上限,最大只能支持 GB 级小容量硬盘,无法满足如今 TB 级大容量存储需求。

CHS 优缺点

优点

  • 完全匹配磁盘机械结构,硬件底层理解直观
  • 小容量硬盘寻址响应直接

缺点

  • 三维坐标计算繁琐,程序调用复杂度高
  • 地址位数受限,容量扩展性极差

现存使用场景

仅保留在主板 BIOS、磁盘固件底层做兼容适配,现代OS不会直接下发 CHS 地址指令。

LBA 一维逻辑寻址

全称
Logical Block Address 逻辑块寻址

核心原理:抛弃磁盘三维物理结构概念,将所有物理扇区扁平化处理,按顺序编成一维连续数字编号,只用单个数字就能唯一定位一个扇区,彻底解决老式 CHS 寻址的容量瓶颈与兼容难题

LBA 核心设计思想

  • 忽略盘片、柱面、磁头的物理形态,把立体的磁盘存储空间,拉伸成一条笔直的线性存储空间
  • 每一个 LBA 编号,严格对应磁盘上唯一一个物理扇区
  • 软硬件分层解耦:上层系统只操作一维数字地址,无需关心硬件结构;磁盘固件内部自动完成逻辑地址到物理坐标的转换

扇区编排排序规则

通俗排布流程

  1. 先遍历第 0 号柱面,依次切换每一个磁头;
  2. 每个磁头对应的磁道里,按扇区顺序逐个编号;
  3. 第 0 柱面全部扇区编号完成后,继续编号第 1 柱面、第 2 柱面...... 直至整块磁盘所有扇区编完。

即:

LBA 完整寻址执行流程

  1. 系统下发逻辑地址:操作系统、文件系统计算出目标 LBA 编号,仅向磁盘控制器传递这一个数字。
  2. 固件自动地址转换 :磁盘内置固件接收 LBA 值,按照换算公式,自动把一维 LBA 地址,转换成硬件可识别的CHS 三维物理坐标
  3. 机械物理定位:磁盘根据柱面、磁头、扇区坐标,驱动磁臂移动、切换磁头、等待盘片旋转,精准找到目标物理扇区
  4. 完成数据读写:对定位到的扇区执行读取或写入操作,数据原路返回上层系统

LBA 与 CHS 地址换算原理

LBA 只是逻辑编号,最终定位依旧依靠物理 CHS 坐标,二者存在固定数学映射关系

设定参数:

  • Htotal = 磁盘总磁头数
  • Strack = 单条磁道包含扇区数
  • 磁头数 * 每磁道扇区数(Htotal × Strack)= 单个柱面的扇区总数

1. CHS → LBA

  • LBA = 柱面号( C ) × 单个柱面的扇区总数(Htotal × Strack) + 磁头号( H ) × 单条磁道包含扇区数(Strack) + 扇区号(S) − 1

  • 减 1 原因:CHS 扇区从 1 编号,LBA 从 0 编号,对齐数值偏移

2. LBA → CHS

  • 柱面号( C ) = LBA ÷ 单个柱面的扇区总数(Htotal × Strack)
  • 磁头号( H ) = (LBA ÷ 单条磁道包含扇区数(Strack))% 总磁头数(Htotal)
  • 扇区号( S ) = (LBA % 单条磁道包含扇区数(Strack))+ 1

引入文件系统

原始磁盘分区只有物理扇区,操作系统无法直接高效管理文件。文件系统的核心作用就是将无序的磁盘物理空间,规整为有序的逻辑空间,实现文件的存储、检索、权限管理。这里引入三个核心基石概念:块、分区、inode

块(Block):文件系统最小读写单元

磁盘最小物理单元是512字节扇区,操作系统如果以扇区读写,效率极低。因此文件系统将多个连续扇区组合为一个块,作为系统读写的最小单位

块的标准定义

  • 物理构成 :由一段连续的物理扇区聚合而成
  • 层级属性:纯软件逻辑概念,磁盘硬件本身不存在块
  • 是文件系统最小读写单位 和文件系统最小空间分配单位

Linux Ext文件系统默认块大小:4KB(8个512字节扇区),可在格式化时指定(1K/2K/4K)

注意:

  • 磁盘就是一个三维数组,我们把它看待成为一个"一维数组",数组下标就是LBA,每个元素都是扇区
  • 每个扇区都有LBA,那么8个扇区一个块,每一个块的地址我们也能算出来。
  • 知道LBA:块号 = LBA / 8
  • 知道块号:LBA = 块号 * 8 + n (n是块内第几个扇区)

分区(Partition):磁盘空间隔离机制

核心逻辑:磁盘→分区→格式化(生成文件系统)→挂载→可读写文件

物理上整块硬盘依旧完整一体,但软件层面实现彻底隔离:

  • 格式化、清空、损坏某一个分区,不会篡改、破坏其他分区的扇区数据;
  • 系统读写文件时,只会访问当前分区对应的 LBA 区间,不会越界访问其他分区

柱面是分区的最小单位,我们可以利用参考柱面号码的方式来进行分区,其本质就是设置每个区的起始柱面和结束柱面号码。

inode(索引节点):文件的唯一身份证

Linux中文件分为两部分,缺一不可:

  1. 元数据:文件属性(大小、权限、所有者、修改时间、数据块编号),存储在 inode 中。
  2. 数据:文件真实内容,存储在 Data Block(数据块)中

本质:inode 是一份文件的身份档案 + 寻址路标,只存文件属性与数据位置,不存放文件名,也不存放文件实际内容。

inode 内部存放的信息

  • inode 编号:分区内文件唯一标识 ID
  • 文件类型:普通文件、目录、符号链接、设备文件、管道文件
  • 访问权限:r 读 w 写 x 执行,管控用户访问权限
  • 所有者 UID、所属组 GID:记录文件归属用户
  • 文件大小:占用存储空间字节数
  • 硬链接计数:统计有多少个文件名指向该 inode
  • 三个时间戳
    atime:最后访问读取时间
    mtime:最后修改文件内容时间
    ctime:最后修改文件属性 / 权限时间
  • 数据块指针数组(核心)
    共 15 个指针,指向存放真实内容的数据块编号,用来寻址文件内容

inode 核心特性

  • 分区内编号唯一,跨分区可重复
  • 不存储文件名,文件名归属目录管理
  • 每个文件有且仅有一个唯一 inode 号,是文件的唯一标识
  • 删除文件不会立刻擦除磁盘数据
  • inode的大小一般是128字节或者256,我们后面统一128字节

查看 inode 命令

  1. 查看文件 inode 编号
c 复制代码
ls -il
  1. 查看完整 inode 所有属性
bash 复制代码
stat 文件名

示例:

ext2 文件系统

宏观认识

我们想要在硬盘上存储文件,必须先把硬盘格式化为某种格式的文件系统,才能存储文件。文件系统的目的就是组织和管理硬盘中的文件

ext2 是将物理磁盘空间组织成可管理文件体系的软件抽象层 ,通过块组化管理 实现资源分散与并行访问,通过inode 索引机制 实现文件身份标识与数据寻址,通过位图管理实现高效资源分配与回收。

ext2 文件系统将整个分区划分成若干个同样大小的块组 (Block Group),如下图所示。只要能管理一个分区就能管理所有分区,也就能管理所有磁盘文件

上图中启动块(Boot Block/Sector)的大小是确定的,为1KB,由PC标准规定,用来存储磁盘分区信息和启动信息,任何文件系统都不能修改启动块。启动块之后才是ext2文件系统的开始。

块组(Block Group)

块组 = 分区拆分出来的微型独立小文件系统,各自管理本组内的块、inode、空闲资源,实现分片自治管理

层级嵌套

bash 复制代码
物理磁盘
   ↓ 划分
磁盘分区
   ↓ 均等切分
多个大小相同的块组
   ↓ 内部组成
逻辑块 Block
   ↓ 聚合
物理扇区 Sector

核心规则

  • 一个分区包含多个块组
  • 同一个分区内所有块组尺寸、内部结构完全一模一样
  • 块组从 0 开始顺序编号,连续铺满整个分区空间
  • Ext 系列默认:每个块组固定包含 8192 个逻辑块

块组的内部构成

1. 超级块(Super Block)

本质 :整个文件系统的全局总控制台账,记录分区整体规格与资源统计信息

存储特点

  • 并非每一个块组都完整存放,只在0、1、3、5、7... 质数编号块组做冗余备份
  • 块组 0 一定包含完整超级块,是系统挂载识别入口
  • 格式固定为ext2_super_block结构体

核心存放信息

  1. 标识类:文件系统魔数(0xEF53),用来识别是不是 Ext2
  2. 规格类:块大小、inode 大小、每组块数量、每组 inode 数量
  3. 统计类:分区总块数、总 inode 数、空闲块数、空闲 inode 数
  4. 时间类:最后挂载时间、最后写入时间、检查时间

作用

  • 系统挂载时校验文件系统合法性
  • 全局统计磁盘整体使用情况
  • 副本备份防止超级块损坏导致分区无法访问

2. 块组描述符表 Group Descriptor Table(GDT)

本质 :记录所有块组基础属性与位置的索引表,每一条描述符对应一个块组

核心存放字段

  1. 本组块位图所在块号
  2. 本组 inode 位图所在块号
  3. 本组 inode 表起始块号
  4. 本组空闲块数量、空闲 inode 数量
  5. 本组内部目录文件个数

作用

  • 快速定位当前块组内位图、inode 表的物理位置
  • 实时统计本组资源余量,新建文件优先挑选富余块组
  • 是连接超级块与单个块组内部资源的中间索引

3. 块位图(Block Bitmap)

本质二进制位状态表,专门标记当前块组内每一个逻辑块的空闲 / 占用状态

核心规则

  • 1 个比特位 对应 1 个逻辑块
  • 比特值 = 0 → 块空闲,可分配存储数据
  • 比特值 = 1 → 块已被文件占用,不可分配

工作逻辑

  • 新建文件:检索比特 0,置为 1,分配对应块
  • 删除文件:对应比特改回 0,回收空间

作用:极速管理本组数据块资源,避免全局遍历查找空闲块

4. inode 位图(Inode Bitmap)

本质 :和块位图原理完全一致,专门标记inode 索引节点的空闲占用状态

工作逻辑:创建文件分配 inode、删除文件回收 inode,都依靠位图快速判定状态

5. inode 表(Inode Table)

本质 :连续存储空间,按编号顺序整齐存放本组所有 inode 结构体

基础属性

  • Ext2 默认单个 inode 大小:128 字节
  • 块组内 inode 数量格式化固定,顺序排列、编号唯一

作用

  • 存储文件身份信息、元数据、数据寻址地址,是文件在块组里的核心标识
  • 一个 inode 唯一对应一个普通文件 / 目录 / 链接文件

6. 数据块(Data Blocks)

本质 :块组内容量最大的区域,真正存放二进制真实数据的空间

按用途分为 4 类块
1. 普通数据块

存放文本、图片、程序、日志等用户真实文件内容

2. 目录块

存放目录项结构:inode编号 + 文件名 + 文件类型

实现文件名到 inode 的映射关系

3. 间接索引块

不存业务数据,只存放下级数据块指针,支撑大文件多级寻址

4. 符号链接块

存放软链接指向的目标文件路径

特性

  • 文件内容优先全部存放在同一个块组,减少跨组寻道
  • 超大文件空间不足时,才向相邻块组申请数据块

注意:

  • inode和数据块是跨组编号的
  • inode和数据块不能跨分区
  • 所以,在同一个分区内部,inode编号和块号都是唯一的

inode与Data Blocks映射

inode核心功能之一就是通过指针找到文件的数据块,Ext2 inode中定义了 i_block[EXT2_N_BLOCKS] 数组(EXT2_N_BLOCKS = 15),共15个指针,采用直接+间接的映射机制,适配不同大小的文件,兼顾读写速度与存储容量:

1. 前 12 个直接指针(i_block[0] ~ i_block[11]

  • 寻址规则:指针内直接存储数据块编号,无任何中间跳转
  • 访问路径:inode → 逻辑块号 → 数据块(读取内容)
  • 可寻址总容量:12×4KB=48KB

2. 一级间接指针(i_block[12]

  • 位置:第 13 个指针
  • 寻址规则:该指针不指向数据块 ,而是指向一个一级间接块;间接块内部连续存放 1024 个数据块编号。
  • 访问路径:inode → 一级间接块号 → 读取间接块 → 取出数据块号 → 数据块
  • 可寻址总容量:1024×4KB=4MB

3. 二级间接指针(i_block[13]

  • 位置:第 14 个指针
  • 寻址规则:两层间接跳转
    指针 → 二级间接块(存放一级间接块编号)→ 一级间接块(存放数据块编号)→ 数据块
  • 访问路径:两次间接块读取,跳转层级更深。
  • 可寻址总容量:1024×1024×4KB=4GB

4. 三级间接指针(i_block[14]

  • 位置:第 15 个指针
  • 寻址规则:三层间接跳转,是层级最多的寻址方式。
  • 可寻址总容量:1024×1024×1024×4KB≈4TB

系统会根据文件大小,按需启用不同层级的指针,不会强制使用全部 15 个指针

结论:

  • 分区之后的格式化操作,就是对分区进行分组,在每个分组中写入SB、GDT、Block Bitmap、Inode Bitmap等管理信息,这些管理信息统称:文件系统
  • 只要知道文件的inode号,就能在指定分区中确定是哪一个分组,进而在哪一个分组确定是哪一个inode

问题:知道一个文件的inode编号,如何找到这个文件的所有内容和属性?

答:

逻辑流程:

bash 复制代码
已知 inode 编号 → 定位 inode 表 → 读取 inode 结构体 → 直接获取【所有文件属性】
               ↓
               解析 15 级指针 → 遍历所有数据块 → 拼接得到【文件全部内容】

补充:创建一个文件的底层流程

bash 复制代码
用户命令 touch test.txt
    ↓
系统调用 open(O_CREAT)
    ↓
VFS路径解析 → 定位父目录 /home/user/
    ↓
选择块组 → 查找inode位图 → 分配空闲inode
    ↓
初始化inode:权限、时间、链接数=1、指针为空
    ↓
父目录数据块 → 新增目录项(test.txt → inode号)
    ↓
更新超级块、块组描述符、位图
    ↓
加载dentry缓存 + inode缓存
    ↓
返回文件描述符 → 文件创建成功

详细过程:

  • 分配空闲 inode :读取 inode 位图 (Bitmap),找到第一个为 0 的位,标记为 1(占用),记录分配到的 inode 编号 ,从 inode 表 中,取出对应的空闲 inode 结构体
  • 初始化 inode 元数据 :内核向新分配的 inode 写入所有文件属性(文件类型、权限、所有者 UID / 所属组 GID等等)
  • (空文件跳过)分配数据块 :如果是创建非空文件 (如 echo hello > test.txt):读取 块位图 ,找到空闲逻辑块,标记块位图为已占用,将块号写入 inode 的直接指针,写入数据到数据块。
  • 创建目录项(文件名 ↔ inode 绑定) :找到父目录的数据块 ,在父目录中新增一条目录项,将新目录项写入父目录的数据块(磁盘 / 缓存)
  • 更新全局元数据
    1.更新 块组描述符表(GDT) :本块组空闲 inode 数 -1;
    2.更新 超级块(Superblock) :分区总空闲 inode 数 -1;
    3.(如果分配了数据块)同步更新块相关统计。
  • 更新内核缓存 :创建内存 dentry:绑定文件名 + inode,将新 inode 加入 inode 缓存 ,将父目录、新文件加入 路径缓存(dcache)
  • 返回文件描述符,完成创建

目录与文件名

目录本质是一种特殊文件,和普通文件一样拥有 inode 和数据块

目录与普通文件的核心差异

对比维度 普通文件 目录(文件夹)
inode 类型标记 标记为「普通文件」 标记为「目录文件」
数据块内容 文本、程序、二进制业务数据 一条条 目录项(文件名 + inode 映射)
核心作用 存储用户数据 组织文件层级、管理文件名与 inode 的对应关系
权限语义 r/w/x 控制文件内容读写、执行 r/w/x 控制目录的浏览、增删、进入(语义完全不同)

目录项定义 :目录的数据块中,按照固定格式存储的一条条记录,就叫做目录项
目录项的作用:建立 文件名对应文件/子目录 inode 编号 的映射关系

用户通过文件名操作文件,系统底层永远通过 inode 识别文件,目录项就是二者的翻译器

文件名只存在于「父目录」的目录项中,绝对不会存放在 inode、文件自身的数据块里

路径解析

我们访问任何文件,都必须得有路径

所以,找到任何Linux文件,都必须从根目录开始,进行路径解析,直到找到相应文件

路径解析流程

以 绝对路径 /home/alice/note.txt 为例,演示系统如何从路径找到文件内容

  1. 起点:根目录 /:系统默认获取根目录 inode(Ext2 根 inode 固定为 2),读取根目录的数据块
  2. 遍历根目录目录项 :在目录项中匹配名称 home,拿到 home 目录的 inode 编号
  3. 进入 home 目录 :根据 inode 读取 home 目录的数据块,遍历内部目录项
  4. 匹配子目录 alice :找到 alice 目录项,获取其 inode 编号,读取对应目录数据块
  5. 匹配目标文件 note.txt :在 alice 的目录项中找到 note.txt,拿到该文件的 inode 编号
  6. 访问文件

问题:访问任何文件,都要从根目录开始进行路径解析吗?

答:原则上是,但是这样太慢,所以Linux会缓存历史路径结构。

问题:Linux目录的概念,是怎么产生的?

答:打开的文件是目录的话,由OS自己在内存中进行路径维护

路径缓存

频繁的路径逐层解析会消耗大量内核资源,因此Linux引入路径缓存 机制:OS在进行路径解析的时候,会把我们历史访问的所有的目录(路径),形成一棵多叉树,进行保存。再次访问相同路径时,直接从缓存读取inode,无需逐层遍历磁盘目录,大幅提升文件访问速度

Linux中,在内核中维护树状路径结构的内核结构体叫做: struct dentry

struct dentry(directory entry,目录项 )是 Linux 内核 VFS 层 定义的纯内存数据结构,专门用于在内存中表示文件名 / 目录名inode 的映射关系。

它是路径缓存(dentry cache) 的最小存储单元,也是路径解析的核心操作对象

内核源码:

c 复制代码
struct dentry {
	atomic_t d_count;
	unsigned int d_flags; /* protected by d_lock */
	spinlock_t d_lock; /* per dentry lock */
	struct inode *d_inode; /* Where the name belongs to - NULL is
					* negative */
	/*
	* The next three fields are touched by __d_lookup. Place them here
	* so they all fit in a cache line.
	*/
	struct hlist_node d_hash; /* lookup hash list */
	struct dentry *d_parent; /* parent directory */
	struct qstr d_name;
	struct list_head d_lru; /* LRU list */
	/*
	* d_child and d_rcu can share memory
	*/
	union {
		struct list_head d_child; /* child of parent list */
		struct rcu_head d_rcu;
	} d_u;
	struct list_head d_subdirs; /* our children */
	struct list_head d_alias; /* inode alias list */
	unsigned long d_time; /* used by d_revalidate */
	struct dentry_operations *d_op;
	struct super_block *d_sb; /* The root of the dentry tree */
	void *d_fsdata; /* fs-specific data */
#ifdef CONFIG_PROFILING
	struct dcookie_struct *d_cookie; /* cookie, if any */
#endif
	int d_mounted;
	unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};

注意:

  • 每个文件其实都要有对应的dentry结构,包括普通文件。这样所有被打开的文件,就可以在内存中形成整个树形结构
  • 整个树形节点也同时会隶属于LRU(Least Recently Used,最近最少使用)结构中,进行节点淘汰
  • 整个树形节点也同时会隶属于Hash,方便快速查找
  • 更重要的是,这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何文件,都在先在这棵树下根据路径进行查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry结构,缓存新路径

分区挂载

磁盘分区格式化Ext2文件系统后,依然无法直接使用,必须经过挂载(mount)

挂载核心本质:将分区的文件系统,关联到Linux根文件系统的某个目录节点,让该目录成为分区的访问入口。

  • 系统所有文件、目录、设备都统一归属到 / 开始的唯一树形结构下,不支持多棵独立目录树并存。必须通过挂载,把分散的分区 "接入" 这棵大树。
  • 挂载后,访问挂载目录等价于访问对应磁盘分区的所有数据。
  • 卸载(umount)则是切断目录与分区的关联,目录恢复原有状态。

挂载点(Mount Point)

挂载点是全局目录树中一个已经存在的目录,有两条硬性规则:

  1. 目录必须提前创建,不能使用不存在的路径;
  2. 推荐使用空目录
  • 若目录非空,挂载后原有文件 / 目录会被临时隐藏(并非删除);
  • 卸载分区后,原目录内容会自动恢复。

模拟分区挂载:

  1. 制作一个大的磁盘块,当做一个分区
bash 复制代码
dd if=/dev/zero of=./disk.img bs=1M count=5
  1. 格式化写入文件系统
bash 复制代码
mkfs.ext4 disk.img
  1. 将分区挂载到指定目录
bash 复制代码
sudo mount -t ext4 ./disk.img ./dir
  1. 查看磁盘分区挂载
bash 复制代码
df -h
  1. 卸载分区
bash 复制代码
sudo umount ./dir

结论 :所以,可以根据访问目标文件的"路径前缀"准确判断我在哪一个分区。

文件系统总结

核心设计思想

  • 分区块组化:化整为零、分片自治,提升效率、降低碎片、隔离故障;
  • inode + 数据块分离:元数据与内容分开存储,统一寻址规则;
  • 树形目录 :Linux 全局唯一根目录树,无盘符,依靠挂载接入外部分区;
  • 缓存加速:路径缓存 (dentry) 替代重复磁盘 IO,用空间换性能。

完整知识闭环图

bash 复制代码
物理磁盘(扇区)
    ↓ 分区
独立分区(MBR/GPT)
    ↓ 格式化 → 生成Ext文件系统
分区 → 块组 → 超级块/位图/inode表/数据块
    ↓
inode(元数据+15级指针) ←→ 数据块(内容/目录项/间接块)
    ↓
磁盘目录项(文件名+inode)
    ↓ 加载到内存
struct dentry + 路径缓存(加速解析)
    ↓
路径解析(绝对/相对路径)
    ↓
文件增删改查、权限控制、软硬链接、挂载卸载


软硬链接

链接是Linux文件系统的特色机制,分为硬链接和软链接,二者底层原理、特性、用途完全不同,其本质依托于前文的inode与文件名映射关系

硬链接

硬链接本质是给同一个inode新增一个文件名,多个文件名共用同一个inode、同一套数据块,没有创建新文件,仅新增目录项记录

核心特性:

  1. 所有硬链接共享同一个 inode、权限、所有者、时间戳、数据块。修改任意一个链接的文件内容,所有链接同步变化
  2. 链接计数机制
  • 创建硬链接:i_links_count + 1
  • 删除一个硬链接(文件名):仅删除对应目录项,i_links_count - 1
  • 只有当 i_links_count == 0 时,内核才会将该 inode 和对应数据块标记为空闲,文件本体真正被删除。
  1. 不支持跨分区、跨文件系统(inode仅在当前分区唯一)
  2. 不支持目录硬链接(避免目录环路,造成文件系统混乱)

创建硬链接:

bash 复制代码
ln 源文件 硬链接名称

示例:

软链接

软链接又称符号链接,是独立的新文件 ,拥有自己的独立inode和数据块。其数据块中不存储真实文件数据,仅存储目标文件的路径

核心特性:

  • 软链接拥有独立inode号,与原文件是两个不同文件
  • 支持跨分区、跨文件系统、跨主机链接
  • 删除原文件,软链接失效,成为无效链接
  • 支持对目录创建软链接
  • 软链接的文件大小,就是其数据块中存放的路径字符字节数,和原文件大小无关

创建软链接:

bash 复制代码
ln -s 源文件/源目录 软链接名称

示例:

软硬链接对比

对比维度 硬链接(Hard Link) 软链接(Symbolic/Soft Link)
核心本质 同一 inode 对应多条目录项(纯别名) 独立特殊文件,数据块存储目标路径(快捷方式)
inode 归属 与源文件共用同一个 inode 拥有全新独立 inode
数据块 共用源文件数据块,不新增存储块 独立数据块,仅存放路径字符串
链接计数 依赖 inode 的 i_links_count(创建 + 1、删除 - 1) 无链接计数,与源文件计数相互独立
跨分区 / 跨挂载 完全不支持 支持(可跨磁盘、跨文件系统)
目录支持(普通用户) 禁止(会造成目录树环路) 允许,目录别名场景高频使用
文件大小 和源文件大小完全一致 等于路径字符串的字节长度
权限生效规则 共用源文件权限,修改同步生效 自身 rwx 权限基本无效,以目标文件权限为准
源文件删除后 链接数>0:链接正常可用;数 = 0 才回收文件本体 变为悬空 / 死链接,跳转失败,无法访问内容

软硬链接的用途

硬链接:

  • 防止重要文件被误删除
  • 同一文件多路径访问,避免重复复制
  • 文件备份

软链接:

  • 简化超长 / 深层路径(路径别名)
  • 跨分区 / 跨磁盘 / 外接设备访问
相关推荐
AlfredZhao3 小时前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334669 小时前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪10 小时前
linux 拷贝文件或目录到指定的位置
linux
大树881 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠1 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质1 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush41 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5201 天前
Linux 11 动态监控指令top
linux
小宇宙Zz1 天前
Maven依赖冲突
java·服务器·maven
Inhand陈工1 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信