2、分区表的类型:MBR与GPT深度解析

分区表这东西,说白了就是硬盘的“目录索引”。你想想看,一块硬盘动辄几TB,操作系统怎么知道哪里存了你的照片,哪里装了游戏?全靠分区表来指引。我这些年调试过的板子,十有八九的启动失败都跟分区表有关——要么是MBR被写坏了,要么是GPT的备份表丢了。

这一节,咱们就把MBR和GPT这两种主流分区表彻底讲透。我会结合自己在嵌入式项目里踩过的坑,帮你建立对分区表的直觉理解。

2.1 MBR(主引导记录)分区表详解

MBR诞生于1983年,跟IBM PC/AT是同一时代的产物。别看它老,到现在很多嵌入式设备、老旧工控机还在用。我去年维护一个工业相机项目,里面的SD卡就是MBR格式——因为BootROM只认这个。

2.1.1 MBR的物理结构

MBR位于硬盘的第一个扇区(LBA 0),大小固定为512字节。这512字节被分成了三部分:

偏移地址 大小 内容
0x000 - 0x1BD 446字节 第一阶段引导代码(Boot Code)
0x1BE - 0x1FD 64字节 分区表(4个条目,每个16字节)
0x1FE - 0x1FF 2字节 魔数 0x55AA(有效标志)

这里有个关键点:分区表只有64字节,每个分区条目固定16字节。所以MBR最多只能记录4个主分区。你想分更多?那就得用扩展分区和逻辑分区来绕。

MBR分区条目(16字节)结构:

  • 第0字节:引导标志(0x80表示可引导,0x00表示不可引导)
  • 第1-3字节:CHS起始地址(磁头、扇区、柱面)
  • 第4字节:分区类型(0x0C = FAT32,0x83 = Linux,0x07 = NTFS)
  • 第5-7字节:CHS结束地址
  • 第8-11字节:LBA起始扇区号(4字节,小端序)
  • 第12-15字节:分区总扇区数(4字节,小端序)

2.1.2 MBR的致命局限

MBR用4字节(32位)来记录LBA起始地址和扇区数。这意味着:

  • 最大寻址空间: 2^32 × 512字节 = 2TB
  • 最大分区数: 4个主分区(或3主+1扩展)
  • 无备份: MBR只存在一个扇区,坏了就全完

我记得2016年做一个NAS项目,客户买了块3TB的硬盘,插上去只认2TB。折腾了半天才发现是MBR的锅——它根本寻址不了2TB以上的空间。后来换成GPT,问题才解决。

避坑指南: 我曾经在BootROM里直接写死LBA地址来加载MBR,结果换了块大硬盘就翻车了。如果你在嵌入式项目里用MBR,一定要确认硬盘容量不超过2TB,否则分区表会溢出截断。

2.2 GPT(GUID分区表)详解

GPT是UEFI时代的产物,它彻底解决了MBR的痛点。我个人的习惯是:只要是新项目,一律用GPT。除非BootROM明确只支持MBR。

2.2.1 GPT的物理结构

GPT的结构比MBR复杂得多,但它更健壮。它的布局是这样的:

LBA地址 内容 大小
LBA 0 保护MBR(Protective MBR) 512字节
LBA 1 GPT头部(GPT Header) 512字节
LBA 2 - LBA 33 分区表条目(Partition Entries) 32 × 512字节 = 16KB
LBA 34 ~ 数据分区区域 可变
末尾 - LBA 33 备份分区表条目 16KB
末尾 - LBA 1 备份GPT头部 512字节
末尾 - LBA 0 (无,保护MBR只在前端) -

注意看,GPT在硬盘的末尾也存了一份完整的备份。这是MBR想都不敢想的。我遇到过好几次GPT头部被意外擦除的情况,全靠备份表恢复数据。

2.2.2 GPT头部详解

GPT头部(LBA 1)的内容非常关键:

// GPT头部结构(简化版)
typedef struct {
    uint64_t  signature;          // "EFI PART" (0x5452415020494645)
    uint32_t  revision;           // 版本号,当前为 0x00010000
    uint32_t  header_size;        // 头部大小,通常为 92 字节
    uint32_t  header_crc32;       // 头部CRC32校验
    uint32_t  reserved;           // 保留
    uint64_t  my_lba;             // 当前头部所在LBA(通常为1)
    uint64_t  alternate_lba;      // 备份头部所在LBA(硬盘末尾)
    uint64_t  first_usable_lba;   // 第一个可用数据LBA(通常为34)
    uint64_t  last_usable_lba;    // 最后一个可用数据LBA
    GUID      disk_guid;          // 硬盘的唯一GUID
    uint64_t  partition_entry_lba;// 分区表条目起始LBA(通常为2)
    uint32_t  num_partition_entries;  // 分区条目数量(通常为128)
    uint32_t  partition_entry_size;   // 每个条目大小(通常为128字节)
    uint32_t  partition_entry_array_crc32; // 分区条目数组CRC32
} gpt_header_t;

这里有个设计细节很巧妙:CRC32校验。GPT头部和分区条目各自有独立的CRC32。如果头部被篡改,BootROM可以通过CRC32检测到,然后自动切换到备份表。我曾在项目里故意破坏GPT头部来测试BootROM的容错能力——结果它完美地fallback到了备份表。

2.2.3 GPT分区条目

每个GPT分区条目固定128字节,结构如下:

typedef struct {
    GUID      partition_type_guid; // 分区类型GUID(如EFI系统分区、Microsoft基本数据分区)
    GUID      unique_partition_guid; // 分区唯一GUID
    uint64_t  starting_lba;       // 起始LBA(64位,支持超大容量)
    uint64_t  ending_lba;         // 结束LBA(64位)
    uint64_t  attributes;         // 属性标志位
    uint16_t  partition_name[36]; // 分区名称(36个UTF-16字符)
} gpt_entry_t;

关键优势:

  • 64位LBA: 最大支持 2^64 × 512字节 ≈ 9.4ZB(这容量够用到下个世纪)
  • 分区数量: 理论上无限制(Windows限制128个,Linux无限制)
  • GUID标识: 每个分区有唯一的GUID,不会因为插拔顺序变化而搞混
  • 分区名称: 可以给分区起名字(比如"BootLoader"、"RootFS"),调试时一目了然

我的经验: 在嵌入式Linux项目中,我习惯给每个分区起一个有意义的名字。比如"uboot"、"kernel"、"rootfs"。这样在调试时,用gdisk -l /dev/mmcblk0一看就知道哪个分区是干嘛的,不用再去翻设计文档。

2.3 MBR与GPT的对比

咱们直接上对比表,一目了然:

对比项 MBR GPT
诞生时间 1983年 2000年代(UEFI规范)
最大容量 2TB 9.4ZB(约94亿TB)
主分区数量 4个(需扩展分区突破) 128个(Windows限制)
备份机制 无备份 头部+条目双备份(硬盘首尾各一份)
校验机制 仅0x55AA魔数 CRC32校验(头部+条目独立校验)
分区标识 1字节类型码(如0x83) 128位GUID(全球唯一)
引导方式 BIOS模式(Legacy) UEFI模式
兼容性 所有操作系统和BootROM 需要UEFI或支持GPT的BootROM

你可能会问:既然GPT这么好,为什么MBR还没被淘汰?

原因很简单:兼容性。很多老旧的BootROM、单片机、嵌入式芯片,它们的第一阶段引导代码只认MBR。我手头有个基于STM32MP1的项目,它的BootROM就只支持从MBR分区加载。这种情况下,你只能用MBR,或者用混合方案(GPT + 保护MBR)。

选型建议:

  • 新项目、大容量(>2TB)、UEFI环境: 无脑选GPT
  • 老旧嵌入式设备、BootROM只支持MBR: 只能用MBR
  • 需要双启动(Legacy BIOS + UEFI): 可以用混合MBR(Hybrid MBR),但我不推荐——容易搞乱

2.4 知识体系总览

下面这张图把MBR和GPT的核心结构、差异点、以及它们与BootROM的关系串起来了。你可以把它当作本章的思维导图:

分区表类型:MBR与GPT对比总览 分区表类型:MBR vs GPT MBR 分区表 GPT 分区表 LBA 0 512字节 4个主分区(16字节/个) 最大 2TB 无备份 · 无CRC LBA 0~33 16KB+ 128个分区(128字节/个) 最大 9.4ZB 双备份 · CRC32校验 BootROM 兼容性决定选择 MBR:Legacy BIOS / 老BootROM GPT:UEFI / 新BootROM 注:保护MBR(LBA 0)使GPT在老系统上显示为“未知分区”,防止误格式化 对比

这张图把MBR和GPT的核心差异都标出来了。你可以看到,MBR结构简单但功能有限,GPT复杂但健壮。中间那三个黄色框是关键——你的BootROM支持哪种,就选哪种。别硬上不兼容的格式,否则板子连启动都做不到。