分区表基础:分区概念、MBR与GPT分区表格式、分区对齐原则

说到Bootloader,分区表是绕不开的基础。我刚开始接触嵌入式Linux时,总觉得分区表就是个“硬盘分区工具”,直到有一次调试启动失败,折腾了两天才发现是分区表格式不兼容。嗯,从那以后,我对分区表的态度就认真多了。

说白了,分区表就是一张“地图”。它告诉Bootloader:你的内核在哪儿、根文件系统在哪儿、设备树在哪儿。没有这张地图,Bootloader就是个睁眼瞎。

1. 分区概念:为什么需要分区?

分区,就是把存储设备(比如eMMC、NAND Flash)划分成几个逻辑区域。每个区域可以独立使用,互不干扰。

你想想看,如果整个Flash只当一个区用,那内核、设备树、文件系统全混在一起。更新内核时,一不小心就把文件系统覆盖了。这谁受得了?

我在项目中遇到过这样的场景:客户的产品需要OTA升级,但分区规划没做好,升级时总得小心翼翼地算偏移量。后来我建议他们重新规划分区,把bootloader、kernel、dtb、rootfs、数据区全部分开。从此世界清净了。

分区的好处很明显:

  • 隔离性:一个分区坏了,不影响其他分区
  • 可管理性:更新内核只擦写kernel分区,不动别的
  • 安全性:Bootloader分区可以设为只读,防止误操作
  • 灵活性:不同分区可以用不同文件系统,比如rootfs用ext4,数据区用FAT
我的习惯:嵌入式设备至少分4个区——bootloader、kernel+dtb、rootfs、data。如果空间允许,再加一个recovery分区做备份。

2. MBR与GPT:两种主流分区表格式

分区表格式,目前主流就两种:MBR和GPT。MBR是老前辈,GPT是新秀。我刚开始做嵌入式时,基本全是MBR。现在嘛,新项目我基本都用GPT了。

2.1 MBR分区表

MBR(Master Boot Record)诞生于1983年,跟IBM PC/AT一个年代。它的结构很简单:

  • 第0扇区(512字节):存放引导代码和分区表
  • 分区表占64字节,每个分区16字节,最多4个主分区
  • 支持的最大磁盘容量:2TB

MBR的分区表结构长这样:

偏移量  长度    描述
0x1BE   16字节  分区1
0x1CE   16字节  分区2
0x1DE   16字节  分区3
0x1EE   16字节  分区4
0x1FE   2字节   结束标志 0x55AA

每个分区条目包含:引导标志、起始CHS地址、分区类型、结束CHS地址、起始LBA、分区大小。

注意:MBR的2TB限制是硬伤。我曾经在一个项目里用4TB的SSD,结果MBR只认到2TB,剩下的空间全浪费了。后来换成GPT才解决。

MBR还有个问题:它只保存一份分区表。如果MBR扇区坏了,整个盘的数据就全丢了。嗯,这设计确实有点脆弱。

2.2 GPT分区表

GPT(GUID Partition Table)是UEFI时代的产物。它解决了MBR的几乎所有痛点:

  • 支持最大 9.4ZB(你没看错,是泽字节)
  • 理论上分区数量无限制(Windows限制128个)
  • 每个分区有唯一的GUID标识
  • 分区表有备份,安全性更高
  • 使用LBA(逻辑块地址)代替CHS,更现代

GPT的布局是这样的:

LBA 0:    保护MBR(兼容性)
LBA 1:    GPT头部
LBA 2-33: 分区表条目(每个条目128字节)
LBA 34+:  数据区
...
最后33个LBA:分区表备份
最后1个LBA:  GPT头部备份

每个分区条目包含:分区类型GUID、唯一GUID、起始LBA、结束LBA、属性、名称。

关键区别:GPT用GUID标识分区类型,而不是MBR那种用一个字节的“分区类型ID”。比如Linux文件系统在MBR里是0x83,在GPT里是"0FC63DAF-8483-4772-8E79-3D69D8477DE4"。虽然长了点,但不会冲突。

我个人更推荐GPT,原因有三:

  1. 备份分区表,坏了还能恢复
  2. 支持大容量,未来扩展无忧
  3. CRC32校验,数据完整性有保障

3. 分区对齐原则:为什么对齐很重要?

分区对齐,说白了就是让分区的起始地址是某个值的整数倍。这个值通常是1MB(2048个扇区)。

为什么会这样?因为现代存储设备(尤其是SSD和eMMC)的物理擦除块大小通常是512KB、1MB甚至更大。如果分区不对齐,一个写操作可能跨越两个擦除块,导致写放大效应。

我曾经在一个项目里遇到过:同样的eMMC,分区对齐后写入速度是15MB/s,不对齐只有3MB/s。差距就是这么明显。

3.1 对齐的好处

  • 性能提升:减少写放大,提高读写速度
  • 寿命延长:减少不必要的擦除操作,延长Flash寿命
  • 兼容性好:某些Bootloader要求分区必须对齐

3.2 如何对齐?

对齐很简单:确保每个分区的起始LBA是2048的整数倍(对应1MB对齐)。

举个例子:

分区1:起始LBA 2048,大小 1MB
分区2:起始LBA 4096,大小 4MB
分区3:起始LBA 12288,大小 16MB

每个分区的起始地址都是2048的倍数,这就是对齐了。

我的做法:用fdisk分区时,指定起始扇区为2048。或者直接用parted工具,它会自动对齐。

3.3 对齐检查

怎么知道分区有没有对齐?用这个命令:

# 查看分区起始扇区
fdisk -l /dev/mmcblk0

# 检查是否对齐(起始扇区能被2048整除)
cat /sys/block/mmcblk0/mmcblk0p1/start

如果起始扇区除以2048余数为0,那就是对齐了。

避坑指南:我曾经接手过一个项目,前任工程师用dd命令直接写分区表,结果起始地址设成了63扇区(老式MBR的默认值)。这个值不对齐,导致eMMC性能惨不忍睹。后来我重新分区,全部按1MB对齐,性能直接翻倍。

4. 知识体系总览

下面这张图,把分区表的核心知识串起来了:

分区表知识体系 分区概念 隔离性 可管理性 安全性 灵活性 MBR分区表 最多4个主分区 最大2TB 无备份 0x55AA结束标志 GPT分区表 几乎无限分区 最大9.4ZB 有备份 GUID标识 分区对齐原则 起始LBA为2048的整数倍(1MB对齐)

这张图把分区概念、MBR、GPT和对齐原则串在了一起。你想想看,这三个知识点其实是环环相扣的:分区概念告诉你为什么要分,MBR/GPT告诉你怎么分,对齐原则告诉你分的时候要注意什么。

好了,分区表的基础就这些。记住一句话:分区规划做得好,后面调试少烦恼。我在项目里吃过亏,所以现在每次做新板子,第一件事就是先把分区表画清楚。

可可精品资料库