前言
为了对一块磁盘(特别是硬盘)上的空间进行有组织的充分利用,通常会把它按照某种标准进行切分,分割成为更小的部分。磁盘称为 Disk,切分成的部分则被称作 Partition,中文名译为分区。
切分的方式并不止一种,最广为人知的被叫做 MBR 布局,近年来因为 UEFI 的普及,以及苹果电脑的流行,另一种叫作 GPT 的布局方式也开始被广为人知。本篇以 MBR 为主要叙述对象。
正文
扇区,以及磁盘访问的单位与寻址方式
受传统的磁盘工艺的影响,磁盘的最小访问单元被命名为扇区(Sector),在其上还有磁道(Track)或柱面(Cylinder)。磁道主要在软盘(Floppy)时代提及较多,到了更大容量的硬盘时代,单盘里可能存在若干个上下摞在一起的存储盘片,因此访问每个盘片就需要动用各自对应的磁头(Head),多了一个维度,而垂直方向上的磁道集合就成其为柱面了。于是访问时需要指定柱面、磁头、扇区的组合来进行,也就是看相关资料时会看到的 CHS 参数集。扇区、磁道/磁头、柱面之间的关系,可以不严谨地比喻为门牌号、小区、街道这样的关系。再往后,随着磁盘容量的不断增长,CHS 被 LBA 寻址方式取代。从逻辑层面,使用扇区进行线性编号已经足以在整个磁盘内进行定位,因此结合柱面和磁头来进行寻址定位的使用场合也就越来越少。事实上,由于 SSD 的兴起,柱面和磁道/磁头的概念正在消失。
MBR
磁盘的第一个扇区(物理机械硬盘的 0 柱面、0 磁头、1 扇区,偏移为 0),会在操作系统安装时,或者用工具对磁盘进行分区/格式化的时候,被写入一些用于描述本磁盘的情况的信息。位于磁盘上的操作系统,是否能够正常运行起来,与这个扇区有着莫大的关系,因此,这个扇区被称作主引导扇区,其上的内容被称作主引导记录(Master Boot Record),也即 MBR。久而久之,MBR 成为这种分区布局规格的代名词。
一个扇区的容量只有区区 512 字节,靠近尾部的 66 个字节被硬性设计为 64 字节的磁盘分区表(Disk Partition Table,DPT)和作为标识的固定签名(即大名鼎鼎的 55 AA 两字节),前部就只剩下了 446 字节可用。于是,几乎所有的主引导记录都会被精心设计,以求在不突破此限制的前提下拥有更强更灵活的能力。在说到引导能力时,这 446 字节的部分往往也被人用 MBR 来指称,有的地方甚至会把第一个扇区直接称为 MBR,大家阅读资料文献时请自行根据上下文辨别。
备注:硬盘的 0~62 扇区(即前 63 个扇区)为保留扇区,目前只有 MBR 占用其中的第一个或前几个扇区,但有的引导管理程序会占用不止一个扇区。
DPT 是一个用于可容纳最多四条记录的空间,每条记录占 16 字节。这个记录数的限制,也就是 MBR 格式的硬盘顶级分区的数量限制;这里所说的顶级分区,就是指主分区和扩展分区,事实上扩展分区如果有的话也只能有一个。DPT 中的每条记录都反映了磁盘上一块连续空间的相关信息,诸如标识、类型、起止等。全 0 的记录是无效记录,但是逐个处理的时候不能因为遇到了一条全是 0 的记录就结束。实践中遇到过唯一一条有效记录是存储在第二条的位置上的实例。
每条分区表记录的 16 个字节含义如下(其中的 CHS 表达与 LBA 表达在分区容量适当的时候可以相互转换,前者的使用已经并不常见)。
1 2 3 4 5 6 |
00 - Partition Flag。 00 不可引导(非活动分区),80 可以引导(活动分区) 01~03 - Start CHS。 分区开始的 CHS 值(磁头 Head、扇区 Sector,柱面 Cylinder) 04 - Partition Type。 分区/文件系统的类型,如 83-linux、82-SWAP、8e-LVM、07-NTFS 05~07 - End CHS。 分区结束的 CHS 值 08~11 - Start LBA。 相对的起始扇区号(当前分区=上一个分区起始扇区号+上一个分区的扇区数量) 12~15 - Size。 该分区所拥有的扇区数量 |
分区文件系统的类型,除表格里的几个例子外,常见的还有:
– 05
:CHS 寻址模式的扩展分区,容量最大为 2GB
– 0F
:LBA 寻址模式的扩展分区,容量最大为 2TB
– 0B
:CHS 寻址模式的 FAT32,容量最大为 2GB
– 0C
:LBA 寻址模式的 FAT32,容量最大为 2TB
电脑加电以后,BIOS 会自动将 MBR 读取到内存中并开始执行上图中的 Bootloader 部分。该部分代码通常的功效是:在 DPT 中寻找表示自己为可引导的活动分区,并加载执行该分区上的 PBR。
PBR(分区引导记录)
PBR,指 Partition Boot Record,位于一个分区的第一个扇区。PBR 是由硬盘的 MBR 加载的程序段。PBR 被加载入内存后即开始执行,其主要功能是完成操作系统的自举并将控制权交给操作系统。尽管每个分区都有 PBR,但只有活动分区的 PBR 才会被 MBR 加载执行。
以 DOS 的 PBR(又被称作 DBR)为例,PBR 主要由下列几个部分组成:
1. 跳转指令,3 个字节。将执行流跳转至引导代码。
2. 厂商标识和 DOS 版本号,共 8 个字节。
3. BPB(BIOS Parameter Block, BIOS 参数块),共 19 个字节。
4. 操作系统引导程序,共 480 个字节。
5. 结束标识,2 个字节,其值也为 AA55
(也即 55 AA
)。
要注意的是,PBR 中的内容除了第五部分结束标识固定不变之外,其余四个部分都是不确定的,其内容将随格式化所用的操作系统版本及硬盘的逻辑盘参数的变化而变化。
对于 MS-DOS,PBR 会寻找 io.sys 和 msdos.sys 文件;对于 Windows XP,则是 ntldr 文件,再往后的 Windows Vista 等,就是 bootmgr 了;而对于 Grub,PBR 会寻找 grldr 文件。
PBR 扇区后面,一般就紧接着存放该分区的文件系统相关信息了。文件系统通常会对 PBR 存储一个备份,NTFS 下备份在分区的最后一个扇区,FAT32 下一般备份在第六个扇区。
在中文资料里 PBR 出现的次数不少,但在维基百科上,PBR 几乎是不见踪迹,完全被 VBR(卷引导记录)这一术语取代,V 指 Volume。
EBR(扩展分区引导记录)
扩展分区(Extended Partition)是为了突破顶级分区数最大为 4 而设计的,在扩展分区内可以创建若干多个逻辑分区(Logical Partition)。EBR 是扩展分区的第一个扇区,其组织方式借鉴了 MBR,不过主要借鉴的是 MBR 里的 DPT 的位置与结构。同时,考虑到 MBR 的 DPT 有上限为 4 的局限性,EBR 做了一个调整:它只使用 DPT 中的前两项,第一项用于描述当前逻辑分区的信息,第二项用于描述下一个**区域**的信息。这里特别没有使用分区这个术语,是因为从结构上,下一个区域完全等同于一个独立的扩展分区。也即该区域的第一个扇区,也是一个 EBR 扇区。这个游戏可以像俄罗斯套娃一样做下去,直至某个 EBR 中的 DPT 的第二项全为 0。理论上,逻辑分区是没有限制的,但事实上,不同的操作系统都有实践上的上限,最好不要用创建大量逻辑分区的魔幻操作去挑战系统。
保留扇区 —— 紧随 MBR/EBR 的空白区域
尽管,无论是 MBR 还是 EBR,它们本身都只占一个扇区,但是,在磁盘划分分区时,紧随其后的分区的第一个扇区(显然应该是个 PBR)往往并不会与 MBR/EBR 紧密相邻。
在机械硬盘时代,这个区域被称为保留扇区,而且通常只存在于 MBR 之后(参见前文)。到了固态硬盘时代,出于对存储颗粒读写寿命的保护,通常会使每个分区的起始扇区都位于 MB 的边界上,从而使得 EBR 之后也有了保留扇区(有的工具或者资料里称之为 partition gap)。究其原因,是因为 1MB 是常见的各种 SSD 的分页大小的最小公倍数,无论是 512 字节,还是 4KB、128KB、512KB,或者 1MB。
实际观察的结果:在一块 80GB 的东芝机械硬盘上,第一个分区的起始扇区是 3F
,即 63,与前文对保留扇区的说明相符;同时,在一块 256GB 的三星 SSD 上,第一个分区的起始扇区是 00 08
,也即 0800
,说明确实保留了 0~2047 共 2048 个扇区,总计 1MB 的空间。
以上扇区的编号还可以说明,在 LBA 寻址方式下,扇区是从 0 开始的。
限制与不足
在分区时,各分区都是不允许跨柱面的,即均以柱面为单位,这就是通常所说的分区粒度。有时候我们分区时输入的分区大小为 7000 MB,分出来却是 6997 MB,就是这个原因。 DPT记录偏移 02
和偏移 06
处的扇区和柱面参数中,扇区占 6 位(bit),柱面占 10 位。以偏移 06
为例,其低 6 位用作扇区数的二进制表示,其高两位做柱面数 10 位中的高两位,偏移 07
的 8 位做柱面数 10 位中的低 8 位。由此可知,实际上用这种方式表示的分区容量是有限的,柱面和磁头从 0 开始编号,扇区从 1 开始编号,所以最多只能表示 1024 个柱面 × 63 个扇区 × 256 个磁头 × 512 字节 = 8455716864 字节。即通常的 8.4 GB(实际上应该是 7.8 GB 左右)限制。实际上磁头数通常只用到 255(由汇编语言的寻址寄存器决定),即使把这 3 个字节按线性寻址,依然力不从心。
在后来的操作系统中,超过 8.4 GB 的分区其实已经不通过 C/H/S 的方式寻址了。而是通过偏移 0C
~0F
共 4 个字节 32 位线性扇区地址来表示分区所占用的扇区总数,此即上文提到过的 Logical Block Address,也即 LBA 寻址方式。可知,通过 4 个字节可以表示 2^32 个扇区,即 2 TB = 2048 GB。对于大多数计算机而言,这已经是个挺大的数字了。
在未超过 8.4 GB 的分区上,C/H/S 的表示方法和线性扇区的表示方法所表示的分区大小是一致的。也就是说,两种表示方法是具有同一性的。如果不一致,则应该以线性寻址为准(可能在某些系统中会提示出错)。超过 8.4 GB 的分区,其结束 C/H/S 一般填充为 FE FF FF
,即 C/H/S 所能表示的最大值。有时候也会用柱面对 1024 的模来填充。不过这几个字节是什么其实都无关紧要了。
虽然现在的系统均采用线性寻址的方式来处理分区的大小,但不可跨柱面的原则依然没变。本分区的扇区总数加上与前一分区之间的保留扇区数目依然必须是柱面容量的整数倍。
在 MBR 分区表中,一个分区最大的容量为 2 TB,且每个分区的起始柱面必须在磁盘的前 2 TB 内。一个 3 TB 的硬盘,根据要求至少要把它划分为 2 个分区,且最后一个分区的起始扇区要位于硬盘的前 2 TB 空间内。如果硬盘太大,则 MBR 分区方式可能根本无法满足需要,必须改用 GPT。
尽管看到的资料都是这么说,但个人认为时至今日(2020 年)上面柱面相关的部分应该是适用于机械硬盘。
参考资料
– https://www.jianshu.com/p/9aa66f634ed6
– https://blog.csdn.net/scyatcs/article/details/82770833
– https://blog.csdn.net/hilavergil/article/details/79270379
还有一篇非常详尽的文档:
– http://thestarman.narod.ru/asm/mbr/index.html