磁盘分区表 — GPT 与 MBR / Disk Partition Tables: GPT and MBR
📅 创建时间:2026-06-17 🏷️ 标签:#分区表 #GPT #MBR #fdisk #gdisk 📚 前置知识:[[02-firmware-bios-uefi]]
📋 本章目标
- 理解为什么要分区——不只是为了"把数据和系统分开"
- 掌握 MBR 的 512 字节结构——引导代码、分区表、魔数
- 理解主分区/扩展分区/逻辑分区的蹩脚设计及其历史原因
- 掌握 GPT 的结构——Protective MBR、GPT Header、Partition Entry Array
- 理解分区类型 GUID 的作用
- 理解分区对齐(1MiB 偏移)的硬件原因
- 知道
fdisk、gdisk、parted各自的适用场景
第1部分:为什么需要分区?
1.1 分区不是文件夹
┌─────────────────────────────────────────────────────────────┐
│ 分区 vs 文件夹——本质区别 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 文件夹:文件系统内部的概念 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ /home/ 只是一个 inode,指向一些数据块 │ │
│ │ 不涉及磁盘上的物理边界 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 分区:块设备级别的概念 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ /dev/nvme0n1p3 对应磁盘上一段连续的 LBA 区间 │ │
│ │ 分区表记录了这个区间的"起点"和"大小" │ │
│ │ │ │
│ │ 分区表 = 磁盘的"目录" │ │
│ │ 它告诉 OS:"这块磁盘分成以下几段,每段从哪到哪" │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 分区的实际用途: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. 不同文件系统 —— /boot 用 FAT32, / 用 btrfs │ │
│ │ 2. 隔离故障域 —— /home 满了不影响 / │ │
│ │ 3. 多系统共存 —— Windows 和 Linux 各占一段 │ │
│ │ 4. 特殊用途 —— swap 分区不需要文件系统 │ │
│ │ 5. 保护恢复环境 —— 厂商的恢复分区 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
第2部分:MBR — 被 512 字节支配的恐惧
2.1 MBR 的 512 字节完整布局
┌─────────────────────────────────────────────────────────────┐
│ MBR(LBA 0)完整 512 字节布局 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Offset 大小 内容 │
│ ────────────────────────────────────────── │
│ 0x000 440B 引导代码 (Bootstrap Code) │
│ ┌─────────────────────────────────────┐ │
│ │ GRUB 第一阶段 (boot.img) 就塞在这里 │ │
│ │ 只做一件事:加载第二阶段 (core.img) │ │
│ │ │ │
│ │ 非启动磁盘这段可能是 0(没有引导代码) │ │
│ └─────────────────────────────────────┘ │
│ │
│ 0x1B8 4B 磁盘签名 (Windows 磁盘管理用) │
│ │
│ 0x1BC 2B 保留 (0x0000) │
│ │
│ 0x1BE 16B 分区项 #1 ┐ │
│ 0x1CE 16B 分区项 #2 │ 4 条分区项 │
│ 0x1DE 16B 分区项 #3 │ 每条 16 字节 │
│ 0x1EE 16B 分区项 #4 ┘ │
│ │
│ 0x1FE 2B 魔数 0x55 0xAA │
│ │
│ ═══════════════════════════════ │
│ 总计:512 字节 │
│ ═══════════════════════════════ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2.2 分区项(16 字节)的逐字节解读
┌─────────────────────────────────────────────────────────────┐
│ 一个 MBR 分区项 = 16 字节 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Offset 大小 字段 说明 │
│ ──────────────────────────────────────────── │
│ 0x00 1B 活动标志 0x80 = 可启动 (active) │
│ 0x00 = 不可启动 │
│ │
│ 0x01 3B CHS 起始地址 旧式寻址 (基本不再使用) │
│ │
│ 0x04 1B 分区类型 0x83 = Linux │
│ 0x07 = NTFS │
│ 0x0C = FAT32 (LBA) │
│ 0x82 = Linux Swap │
│ 0x05 = 扩展分区 │
│ 0xEE = GPT Protective │
│ │
│ 0x05 3B CHS 结束地址 旧式寻址 │
│ │
│ 0x08 4B LBA 起始扇区 分区第一个扇区的编号 │
│ │
│ 0x0C 4B 扇区总数 分区包含的扇区数 │
│ │
│ ════════════════════════════════════ │
│ 关键字段:LBA 起始扇区 + 扇区总数 │
│ 由此两个数字确定分区在磁盘上的精确范围 │
│ │
│ 限制:32 位扇区数 × 512B = 2TB 最大分区大小 │
│ 超过 2TB 的磁盘必须用 GPT │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2.3 主分区、扩展分区、逻辑分区 — 一个 hack
MBR 只有 4 个分区槽。1980 年代这够了,但很快不够用。于是发明了扩展分区:
┌─────────────────────────────────────────────────────────────┐
│ 主分区 / 扩展分区 / 逻辑分区的结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ MBR (LBA 0): │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 分区项 #1: 主分区 /dev/sda1 (NTFS, Windows C:) │ │
│ │ 分区项 #2: 扩展分区 /dev/sda2 (类型 0x05/0x0F) │ │
│ │ 分区项 #3: 空 │ │
│ │ 分区项 #4: 空 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ │ 扩展分区指向磁盘上的一个区域 │
│ │ 这个区域里有一串 "EBR" (Extended Boot Record) │
│ ↓ │
│ │
│ 扩展分区区域: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ EBR #1 (一个扇区): │ │
│ │ 分区项 #1: 逻辑分区 /dev/sda5 (数据) │ │
│ │ 分区项 #2: 指向下一个 EBR → │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ EBR #2 (一个扇区): │ │
│ │ 分区项 #1: 逻辑分区 /dev/sda6 (数据) │ │
│ │ 分区项 #2: 指向下一个 EBR → │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ EBR #3: 同上... │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 这是一个链表。每个 EBR 只描述一个分区 + 下一块的地址。 │
│ 为什么 /dev/sda 的分区编号跳过 3,4? │
│ → 1-4 保留给主分区/扩展分区 │
│ → 逻辑分区从 5 开始 │
│ │
│ MBR 分区方案的本质问题: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 只有 4 个主分区槽 → 靠扩展分区补丁 │ │
│ │ • 32 位 LBA → 2TB 天花板 │ │
│ │ • 无备份 → 分区表损坏 = 找不到所有数据 │ │
│ │ • 无 CRC/校验 → 不知道分区表是否被篡改 │ │
│ │ • 无分区名称/ID → 全靠"分区类型"一个字节区分 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
第3部分:GPT — 为现代磁盘设计的方案
3.1 GPT 的整体布局
┌─────────────────────────────────────────────────────────────┐
│ GPT 磁盘布局 │
├─────────────────────────────────────────────────────────────┤
│ │
│ LBA 0: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Protective MBR │ │
│ │ │ │
│ │ • 分区项 #1: 类型 0xEE, 覆盖整个磁盘 │ │
│ │ ("这个磁盘已经被 GPT 占用了") │ │
│ │ • 引导代码: 无 (或保护性代码) │ │
│ │ • 目的: 让老工具知道这不是一块"空磁盘" │ │
│ │ 防止 MBR 工具误认为磁盘未分区而覆盖数据 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ LBA 1: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ GPT Header │ │
│ │ │ │
│ │ 签名: "EFI PART" (8 字节) │ │
│ │ GPT 版本: 通常是 0x00010000 │ │
│ │ Header 大小: 92 字节 │ │
│ │ Header CRC32 │ │
│ │ Header 自身 LBA: 1 │ │
│ │ 备份 Header LBA: 磁盘最后一个 LBA │ │
│ │ 第一个可用 LBA: 分区开始位置 │ │
│ │ 最后一个可用 LBA: 分区结束位置 │ │
│ │ Disk GUID: 16 字节全局唯一标识 │ │
│ │ Partition Entry Array 起始 LBA: 通常是 2 │ │
│ │ 分区项总数: 通常是 128 │ │
│ │ 每个分区项大小: 128 字节 │ │
│ │ Partition Entry Array CRC32 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ LBA 2 ~ 33: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Partition Entry Array │ │
│ │ │ │
│ │ 128 条分区项,每条 128 字节 │ │
│ │ (从 LBA 2 到 LBA 33,占用 32 个扇区) │ │
│ │ │ │
│ │ 每条分区项 = 128 字节: │ │
│ │ • 分区类型 GUID (16B) — 分区的"身份证" │ │
│ │ • 分区唯一 GUID (16B) — 这个分区的唯一标识 │ │
│ │ • 起始 LBA (8B) │ │
│ │ • 结束 LBA (8B) │ │
│ │ • 属性标志 (8B) — 只读/隐藏/不自动挂载 │ │
│ │ • 分区名称 (72B) — UTF-16 LE, 36个字符 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ... 实际的分区数据 ... │
│ │
│ 磁盘最后 33 个扇区: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 备份 GPT (Header + Entry Array) │ │
│ │ │ │
│ │ 与开头的 GPT 完全一样,存储在磁盘末尾 │ │
│ │ 如果主 GPT 损坏,可以从备份恢复 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 为什么更可靠: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 1. 有 CRC32 校验 → 能检测损坏 │ │
│ │ 2. 末尾有完整备份 → 分区表损坏可以恢复 │ │
│ │ 3. 128 条分区项 → 不需要扩展分区这种 hack │ │
│ │ 4. 64 位 LBA → 最大寻址 ~9.4ZB │ │
│ │ (9.4 ZB = 9.4 × 10^21 字节 = 足够用到地老天荒) │ │
│ │ 5. 每条分区有名字和 GUID → 可读性好 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
3.2 分区类型 GUID — 分区的"身份证"
┌─────────────────────────────────────────────────────────────┐
│ 常见 GPT 分区类型 GUID │
├─────────────────────────────────────────────────────────────┤
│ │
│ GUID 用途 │
│ ────────────────────────────────────────────────────── │
│ C12A7328-F81F-11D2-BA4B-00A0C93EC93B ESP (EFI 系统分区) │
│ 0FC63DAF-8483-4772-8E79-3D69D8477DE4 Linux 文件系统 │
│ 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F Linux Swap │
│ EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 Windows 基本数据分区 │
│ DE94BBA4-06D1-4D40-A16A-BFD50179D6AC Windows 恢复分区 │
│ E3C9E316-0B5C-4DB8-817D-F92DF00215AE Microsoft Reserved │
│ │
│ 为什么要这么长的 GUID 而不是 1 字节? │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 1 字节 = 256 种类型 → 根本不够用 │ │
│ │ GUID = 16 字节 = 2^128 种 → 永远不会冲突 │ │
│ │ 任何公司/社区都可以注册自己的类型 GUID │ │
│ │ 固件/OS 读到不认识的分区类型 → 安全地忽略它 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
3.3 Protective MBR 的巧妙设计
┌─────────────────────────────────────────────────────────────┐
│ Protective MBR —— 最低成本的兼容 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 问题:GPT 磁盘被插到一台只有 MBR 工具的老系统上会怎样? │
│ │
│ 如果没有 Protective MBR: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 老 fdisk 读取 LBA 0 → 没有 0x55AA 签名 → 认为是空磁盘 │ │
│ │ → 用户可能初始化 MBR → 覆盖 GPT Header │ │
│ │ → 灾难 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 有了 Protective MBR: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 老 fdisk 读取 LBA 0 → 看到一个 0xEE 类型的分区 │ │
│ │ → 占据整个磁盘 │ │
│ │ → "这块磁盘被某种我不认识的格式使用" │ │
│ │ → 老工具不会尝试初始化 │ │
│ │ (除非用户强制执行,但那是自找的) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 这就是"用一个 MBR 分区槽来保护 GPT 磁盘"的巧妙之处 │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
第4部分:分区对齐 — 为什么第一个分区从 2048 开始
4.1 1MiB 对齐的来源
┌─────────────────────────────────────────────────────────────┐
│ 分区对齐——一个物理限制导致的软件约定 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 问题链: │
│ │
│ HDD 物理扇区 → 4K │
│ ↓ │
│ SSD 的 Page → 4K/8K/16K │
│ ↓ │
│ 分区起始 LBA 如果不是 4K 的倍数 → 跨物理扇区读写 │
│ ↓ │
│ 每次跨扇区写入 = Read-Modify-Write = 性能灾难 │
│ │
│ 解法: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 传统 MBR: 第一个分区从 LBA 63 开始 │ │
│ │ (Track 0 被 MBR 占用,Track 1 开始 = 63 扇区 × 512) │ │
│ │ 63 % 8 = 7 → 不对齐 4K! │ │
│ │ │ │
│ │ 现代标准: 第一个分区从 LBA 2048 开始 │ │
│ │ 2048 × 512B = 1 MiB │ │
│ │ 1 MiB 是 4K/8K/16K/32K/64K 所有常见扇区大小的倍数 │ │
│ │ → 永远对齐 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 你的 Arch 安装中 fdisk 默认就是这样做的。 │
│ `fdisk -l` 看到的 `Start=2048` 就是这个原因。 │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
第5部分:工具选择 — fdisk vs gdisk vs parted
┌─────────────────────────────────────────────────────────────┐
│ 分区工具对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 工具 MBR GPT 交互式 非交互 推荐场景 │
│ ──────────────────────────────────────────────────────── │
│ fdisk ✅ ✅ ✅ ❌ 日常手动分区 │
│ gdisk ❌ ✅ ✅ ❌ GPT 专用,类似 fdisk │
│ parted ✅ ✅ ✅ ✅ 脚本化分区 │
│ cfdisk ✅ ✅ ✅ ❌ TUI 半图形界面 │
│ cgdisk ❌ ✅ ✅ ❌ GPT 版 cfdisk │
│ │
│ 实用建议: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 交互式手动分区 → fdisk (支持 MBR+GPT) │ │
│ │ • shell 脚本里分区 → parted --script │ │
│ │ • 查看分区信息 → fdisk -l 或 parted -l │ │
│ │ • 修复 GPT 表 → gdisk (gdisk 的诊断模式更强) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
核心总结
总结1:MBR 的一身病
MBR 结构:440B引导 + 64B分区表 + 2B魔数 = 512B
核心限制:4 个主分区 → 扩展分区 hack →
32 位 LBA → 2TB 天花板 →
无校验、无备份 → 出问题就是灾难2
3
4
总结2:GPT 的六个改进
1. 128 条分区项 → 不需要扩展分区
2. 64 位 LBA → 9.4ZB 寻址
3. CRC32 校验 → 能检测损坏
4. 末尾备份 → 可以恢复
5. 分区类型 GUID → 人类可读的分区"身份证"
6. Protective MBR → 防止老工具误判空磁盘2
3
4
5
6
总结3:对齐 1MiB 的理由
LBA 2048 = 1MiB 偏移 → 是 4K/8K/16K/...所有常见扇区大小的倍数
避免跨物理扇区写入 → 避免 Read-Modify-Write → 保证性能2
章节测试
测试1:MBR 分区的最大数量
MBR 最多支持几个主分区?如果想超过这个数量怎么办?
测试2:2TB 限制
MBR 为什么不能支持超过 2TB 的磁盘?
测试3:Protective MBR
什么是 Protective MBR?它的作用是什么?
测试4:GPT 备份
GPT 的备份放在哪里?为什么有备份?
测试5:分区对齐
你的 fdisk 显示分区从 LBA 2048 开始。如果手动改为 LBA 63,会发生什么?
参考答案
测试1答案
MBR 最多 4 个主分区(分区表只有 4 个 16B 槽位)。想超过 4 个分区时,必须将一个主分区改为扩展分区,在其中创建逻辑分区(链表结构)。逻辑分区的编号从 5 开始(sda5, sda6...)。这是纯软件层面的 hack,硬件并不理解"扩展分区"这个概念。
测试2答案
MBR 分区项的"扇区总数"字段只有 4 字节(32 位)。最大扇区数 = 2^32。2^32 × 512B = 2TB。对于 4K 原生扇区,理论上可以到 16TB,但大多数 MBR 实现仍然按 512B 逻辑扇区计算。
测试3答案
Protective MBR 是 GPT 磁盘 LBA 0 处的 MBR 结构,包含一个类型为 0xEE 的分区项占据整个磁盘。它的作用是防止老式 MBR 工具误认为磁盘未分区而覆盖 GPT 数据。它不是用来启动的——只是占位符。
测试4答案
GPT 的备份(Header + Partition Entry Array)存储在磁盘的最后 33 个扇区。有备份是因为主 GPT 如果损坏(比如被覆盖),可以从末尾的备份恢复整个分区表。这是 MBR 没有的保护机制。
测试5答案
如果分区从 LBA 63 开始,63 % 8 = 7,不对齐 4K 物理扇区。每次文件系统执行跨逻辑扇区的 4K 写入时,磁盘固件内部会触发 Read-Modify-Write——先读整个 4K 物理扇区,修改其中 512B,再写回整个 4K。这会显著降低随机写入性能。现代工具默认 LBA 2048 = 1MiB = 对任何常见扇区大小都对齐。
相关笔记
- [[02-firmware-bios-uefi]] - GPT 和 UEFI 的关系——为什么 GPT 配 ESP
- [[04-filesystem-concepts]] - 分区里放的文件系统是什么结构
- [[10-linux-disk-practice]] - 实战操作 fdisk/gdisk 分区
下一步学习
- [ ] 阅读 04 - 文件系统核心概念
学习状态:🟡 开始学习