从0到1:一个字节的磁盘之旅

本文从磁盘的物理扇区出发,经过 CHS/LBA 寻址、分区、格式化、挂载、路径解析,直到软硬链接的使用。

这是一条从硬件到用户视角的完整路径,理解它,就能回答"我写的一个字节,到底存在哪里、怎么被找到"这样的终极问题。


第一部分:磁盘物理结构

1.1 机械硬盘的物理组成

一块传统的机械硬盘(HDD)内部包含:

  • 盘片(Platter):圆形磁性介质,数据记录在表面。一块硬盘通常有多个盘片。

  • 磁头(Head):每个盘片表面有一个读写磁头,负责读取和写入。

  • 主轴(Spindle):带动盘片高速旋转(常见 5400/7200 RPM)。

  • 磁臂(Actuator Arm):带动磁头在盘片表面径向移动。

1.2 磁道、柱面、扇区

数据在盘片上的组织方式:

  • 磁道(Track):盘片表面被划分为一圈圈同心圆,每一圈叫一个磁道。

  • 柱面(Cylinder) :所有盘片上半径相同的磁道组成的集合。因为磁头是同步移动的,同一柱面的磁道可以"无寻道"地连续访问。

  • 扇区(Sector) :磁道被划分为若干弧段,每段是一个扇区,是磁盘最小的物理读写单位 。传统扇区大小为 512 字节 ,现代硬盘多为 4096 字节(4K 扇区)。

    复制代码
    盘片俯视图
       ┌─────────────┐
       │   ╭─────╮   │  ← 磁道(同心圆)
       │  ╭───────╮  │
       │ ╭─────────╮ │
       │ │  ● 主轴  │ │
       │ ╰─────────╯ │
       │  ╰───────╯  │
       │   ╰─────╯   │
       └─────────────┘
       扇区是磁道上的一小段弧

1.3 为什么这些概念重要?

磁盘访问时间由三部分组成:

  • 寻道时间:磁头移动到目标磁道所需时间(机械动作,最慢)。

  • 旋转延迟:等待目标扇区转到磁头下方(与转速相关)。

  • 传输时间:读写数据的实际时间。

由此得出一个重要结论:顺序访问连续扇区远快于随机访问。这也是文件系统要尽量让文件数据连续存放的根本原因,也是 Ext4 引入 Extents 和多块分配的动机。


第二部分:CHS 与 LBA 地址

2.1 CHS 寻址:三维坐标定位

早期磁盘使用 CHS(Cylinder-Head-Sector) 寻址,用三个参数定位一个扇区:

  • C:柱面号(Cylinder)

  • H:磁头号(Head),即盘面号

  • S :扇区号(Sector),从 1 开始编号

一个 CHS 地址 (C, H, S) 唯一确定一个扇区。传统 BIOS 的 CHS 参数上限为:

  • 柱面 0--1023(10 位)

  • 磁头 0--255(8 位)

  • 扇区 1--63(6 位)

这样最大可寻址 1024 × 256 × 63 × 512B ≈ 7.8GB,这就是著名的 8GB 寻址壁垒。

2.2 LBA 寻址:一维线性编号

LBA(Logical Block Address) 把整个磁盘的所有扇区从 0 开始连续编号,每个扇区对应一个唯一的整数地址。操作系统和现代硬盘控制器普遍使用 LBA,因为它简单、线性、易于计算。

2.3 CHS 与 LBA 的转换

在传统几何参数下(每磁道 63 扇区,每柱面 255 磁头),转换公式为:

CHS → LBA:

复制代码
LBA = (C × 磁头数 + H) × 每磁道扇区数 + (S - 1)

LBA → CHS:

复制代码
C = LBA / (磁头数 × 每磁道扇区数)
H = (LBA / 每磁道扇区数) % 磁头数
S = (LBA % 每磁道扇区数) + 1

注意扇区号在 CHS 中从 1 开始,在 LBA 中从 0 开始,所以公式里有 S - 1 和 + 1。

2.4 现代磁盘的真实情况

现代硬盘早已不暴露真实的物理 CHS 几何结构,固件内部进行地址映射。操作系统看到的"CHS"只是兼容性的逻辑几何。LBA 才是现代存储的事实标准。SSD 更是完全没有物理磁道和扇区,但对外仍以 LBA 扇区为单位呈现。


第三部分:分区

3.1 什么是分区?

一块物理磁盘可以被划分为多个分区,每个分区是一段连续的 LBA 地址范围,可以独立格式化为不同的文件系统,独立挂载。分区表记录了每个分区的起止位置、类型等信息。

3.2 MBR 分区表

MBR(Master Boot Record) 位于磁盘的第一个扇区(LBA 0),共 512 字节,布局为:

偏移 大小 内容
0 446 字节 引导代码
446 64 字节 分区表(4 个 16 字节表项)
510 2 字节 结束标志 0x55AA

MBR 的限制:

  • 最多 4 个主分区(或 3 主分区 + 1 扩展分区,扩展分区内再划分逻辑分区)。

  • 分区表项中用 32 位记录起始 LBA 和扇区数,配合 512 字节扇区,最大支持 2TB 磁盘。

3.3 GPT 分区表

GPT(GUID Partition Table) 是为解决 MBR 限制而设计的现代分区方案:

  • 支持最多 128 个分区(可扩展)。

  • 使用 64 位 LBA 寻址,支持超大磁盘。

  • 每个分区有唯一的 GUID 标识。

  • 分区表在磁盘开头和末尾各存一份,互为备份。

  • 磁盘开头保留一个保护性 MBR,防止旧工具误判。

3.4 分区操作

bash 复制代码
# 查看磁盘和分区
lsblk
sudo fdisk -l /dev/sda
sudo parted /dev/sda print

# 使用 fdisk 交互式分区(MBR/GPT 均可)
sudo fdisk /dev/sdb
#   n 新建分区
#   d 删除分区
#   p 打印分区表
#   t 修改分区类型
#   w 写入并退出

# 使用 parted 创建 GPT 分区表
sudo parted /dev/sdb mklabel gpt
sudo parted /dev/sdb mkpart primary ext4 1MiB 10GiB

分区完成后,内核中会出现 /dev/sdb1、/dev/sdb2 等设备节点。


第四部分:Ext 系列文件系统原理

4.1 块组布局

每个块组包含:超级块(备份)→ 块组描述符表 → 块位图 → inode 位图 → inode 表 → 数据块。

4.2 inode 与数据寻址

  • Ext2/3:直接块 + 一级/二级/三级间接块。

  • Ext4 :Extents (起始块号, 长度)组成的树,小文件的 extent 树直接内嵌在 inode 中。

4.3 三代演进要点

Ext2 Ext3 Ext4
日志 无 有 有 + 校验
寻址 间接块 间接块 Extents
分配 即时单块 即时单块 延迟分配 + 多块
容量 2TB/16TB 2TB/16TB 16TB/1EB

4.4 关键结构速查

  • 超级块:文件系统全局参数。

  • GDT:各块组的位置和空闲统计。

  • 位图:块和 inode 的分配状态。

  • inode 表:所有文件的元数据。

  • 目录项(dentry):目录文件中"文件名 → inode 号"的映射。


第五部分:格式化

5.1 格式化做了什么?

"格式化"在 Linux 语境下通常指创建文件系统 (mkfs),而不是低级格式化。以 mkfs.ext4 为例,它会在分区上:

  1. 写入超级块,记录块大小、inode 总数等全局参数。

  2. 划分块组,为每组写入 GDT、位图、inode 表。

  3. 初始化根目录 inode(inode 2) 和根目录的数据块。

  4. 建立日志区域(Ext3/4)。

  5. 将空闲块和空闲 inode 在位图中标记为可用。

5.2 常用命令

bash 复制代码
# 创建 Ext4 文件系统
sudo mkfs.ext4 /dev/sdb1

# 指定块大小和卷标
sudo mkfs.ext4 -b 4096 -L "mydata" /dev/sdb1

# 查看文件系统信息
sudo dumpe2fs -h /dev/sdb1
sudo tune2fs -l /dev/sdb1

5.3 格式化的本质

格式化不擦除数据,它只是重建元数据结构。原数据块的内容可能仍残留在磁盘上,直到被新数据覆盖。这也是数据恢复工具能够工作的原理之一。


第六部分:挂载与路径解析

6.1 挂载是什么?

Linux 没有 Windows 那样的"C 盘、D 盘"概念,所有文件系统都被组织在一棵以 / 为根的目录树 中。挂载就是把一个文件系统"接"到目录树的某个节点(挂载点)上,使其内容在该节点下可见。

bash 复制代码
# 挂载
sudo mount /dev/sdb1 /mnt/data

# 查看当前挂载
mount | grep sdb1
findmnt /mnt/data

# 卸载
sudo umount /mnt/data

6.2 挂载时内核做了什么?

  1. 读取分区上的超级块,识别文件系统类型。

  2. 创建 vfsmount 结构,记录挂载点和文件系统信息。

  3. 将该文件系统的根目录 inode 与挂载点目录的 inode 关联起来。

  4. 此后访问挂载点路径,就会进入新文件系统的根目录。

6.3 VFS:统一抽象层

Linux 的 VFS(Virtual File System) 为所有文件系统提供统一接口。无论底层是 Ext4、XFS、NFS 还是 procfs,上层都通过相同的 open/read/write 系统调用访问。挂载的本质就是让 VFS 在路径解析时"切换"到另一个文件系统的根。

6.4 持久化挂载:/etc/fstab

bash 复制代码
# /etc/fstab 示例
UUID=xxxx-xxxx  /mnt/data  ext4  defaults  0  2

字段含义:设备、挂载点、文件系统类型、挂载选项、dump 标志、fsck 顺序。

6.5 路径解析过程

当执行 open("/home/alice/doc.txt") 时,内核的路径解析大致如下:

  1. 从根目录 inode(inode 2) 开始。

  2. 在根目录的数据块(目录项列表)中查找 "home",得到其 inode 号。

  3. 读取该 inode,确认是目录,进入其数据块。

  4. 查找 "alice",得到 inode 号,进入。

  5. 查找 "doc.txt",得到最终 inode 号。

  6. 检查权限,返回文件描述符。

每一步都会查询 dentry 缓存 (目录项缓存),命中则跳过磁盘读取。/、.、.. 有特殊处理:. 指向当前目录自身,.. 指向父目录。

6.6 挂载点与路径解析的交互

如果 /mnt/data 是一个挂载点,路径解析走到 /mnt/data 时,VFS 会检测到该目录是一个挂载点,自动切换到被挂载文件系统的根目录继续解析。这就是挂载"透明"的原因。


第七部分:软链接与硬链接

7.1 硬链接(Hard Link)

本质 :多个目录项指向同一个 inode。它们共享同一份数据,没有"原文件"和"副本"之分。

bash 复制代码
ln original.txt hardlink.txt
  • inode 的链接计数(link count) 加 1。

  • 删除其中一个名字,只是链接计数减 1;计数归零时 inode 和数据块才真正释放。

  • 硬链接不能跨文件系统(inode 号只在单个文件系统内唯一)。

  • 硬链接不能指向目录(防止目录树出现环,简化路径解析)。

查看:

bash 复制代码
ls -li original.txt hardlink.txt
# 两个文件 inode 号相同,链接计数为 2

7.2 软链接(Symbolic Link)

本质 :一个独立的文件 ,有自己的 inode,其数据内容是目标文件的路径字符串。

bash 复制代码
ln -s /path/to/target symlink
  • 类型为 l,ls -l 显示为 symlink -> /path/to/target。

  • 可以跨文件系统,可以指向目录。

  • 目标被删除后,软链接变成悬空链接(dangling),访问会失败。

  • 访问软链接时,内核解析其内容得到目标路径,再重新进行路径解析。

7.3 对比总结

特性 硬链接 软链接
本质 同一 inode 的另一个名字 独立文件,内容是目标路径
inode 号 与原文件相同 与原文件不同
跨文件系统 不可以 可以
指向目录 不可以 可以
原文件删除后 数据仍可访问(计数未归零) 变成悬空链接
创建命令 ln src dst ln -s src dst

7.4 使用场景

  • 硬链接 :节省空间地给同一文件起多个名字(如备份快照、包管理器中的多版本共存);rsync --link-dest 增量备份就大量使用硬链接。

  • 软链接 :指向库的版本(libfoo.so -> libfoo.so.1.2);跨目录、跨文件系统引用;配置文件切换(如 current -> releases/v1.2)。


第八部分:完整链路串讲

把本文的内容串成一条线:

bash 复制代码
物理磁盘(盘片/磁道/扇区)
        │  用 CHS 或 LBA 定位
        ▼
分区表(MBR/GPT)划分出分区 /dev/sdb1
        │  mkfs.ext4 写入元数据
        ▼
Ext4 文件系统(块组、超级块、inode、数据块)
        │  mount 到 /mnt/data
        ▼
VFS 目录树,路径解析逐级查找 inode
        │  open("/mnt/data/doc.txt")
        ▼
返回文件描述符,读写通过页缓存与磁盘交互
        │  ln / ln -s
        ▼
硬链接共享 inode,软链接存储路径

小结

主题 核心要点
磁盘物理结构 盘片、磁道、柱面、扇区;顺序访问远快于随机访问
CHS 与 LBA CHS 三维坐标;LBA 线性编号;转换公式;现代以 LBA 为准
分区 MBR(4 主分区、2TB 限制)vs GPT(128 分区、64 位 LBA、备份表)
Ext 系列 块组、超级块、GDT、位图、inode;间接块 → Extents;日志与校验
格式化 mkfs.ext4 重建元数据结构,不擦除数据
挂载 VFS 统一抽象,把文件系统接到目录树节点;/etc/fstab 持久化
路径解析 从根 inode 开始逐级查目录项,dentry 缓存加速,挂载点自动切换
软硬链接 硬链接共享 inode,软链接是存路径的独立文件

这条从物理扇区到目录树的链路,是理解 Linux 存储的完整地图。打开终端,把分区、格式化、挂载、链接都亲手做一遍,会有"打通任督二脉"的感觉!

相关推荐
SEO_juper1 小时前
手写 llms.txt 验证器:让 AI 更愿意引用你的网站(GEO)
开发语言·人工智能·python·聚类·seo·独立站
比兔代理1 小时前
纯净IP是什么?从IP信誉、黑名单与ASN角度原理解析
开发语言·php
运维小斌1 小时前
麒麟 V10 ARM64 离线部署 OceanBase:8 步实施手册
linux·数据库·oceanbase·麒麟
着迷不白1 小时前
生产环境标准的Linux系统安装到服务器
linux·云计算
benjiangliu1 小时前
恩培趣味计算机视觉-01-conda环境和Python库
开发语言·python·conda
艾莉丝努力练剑1 小时前
【AI大模型接入SDK】ChatServer接口实现
c++·人工智能·学习·ai·架构·大模型·sdk
我喜欢就喜欢1 小时前
DeepSeek Harness 开源贡献手记:从零到合入主线
开发语言·人工智能
要练八块腹肌1 小时前
AVL树的讲解与实现
c++
吹什么轩1 小时前
linux系统复习:进程优先级与O(1)调度
java·linux·算法