计算机那些事(1)——硬盘

硬盘接口

常见的硬盘接口有:IDESATASASUSBSCSI,其中 SATA 是目前的主流接口,IDE 则几乎不再使用。

设备文件

计算机的各种硬件设备在 Linux 中都有对应的设备文件,甚至不同的接口也对应着不同的设备文件,从而使用不同的驱动程序来操作硬件设备。对于硬盘,实体设备的文件名一般是 /dev/sd[a-];虚拟设备(虚拟机中的硬盘)的文件名一般是 /dev/vd[a-]

有时,系统中会有 /dev/sda/dev/sdb...等设备文件,它们之间又是什么关系呢?实际上,/dev/sd[a-] 是 SATA/USB/SAS 等硬盘接口对应的设备文件,这类接口都使用 SCSI 模块作为驱动程序。abc...则是按系统检测到的顺序来排列的,与实际插槽顺序无关。

我们知道硬盘是可以被分区成多个分区(partition),如在 Windows 中可以将一块硬盘分区成 C:D:E: 盘。那么,不同的分区是否也有对应的设备文件呢?

硬盘结构

提到分区,我们需要先了解一下硬盘的结构。不同寻址方式的硬盘,其结构也不同。硬盘的寻址方式主要有两种:

  • CHS 寻址方式:由柱面数(Cylinders)、磁头数(Headers)、扇区数(Sectors)组成 3D 参数,简称 CHS 寻址方式,硬盘容量相对较小。如传统的机械硬盘(Hard Disk Drive,HDD)。
  • LBA 寻址方式:线性寻址,以逻辑区块为单位进行寻址,全称为 Logic Block Address(即扇区的逻辑块地址),硬盘容量相对较大。如固态硬盘(Solid State Disk,SSD)

CHS 寻址方式

如下图所为 CHS 寻址方式的硬盘结构,硬盘主要由盘片、机械手臂、磁头、主轴马达组成。盘片是数据存储的媒介,圆形,通过机械手臂读写数据,盘片需要转动才能够让机械手臂读写。因此,可以将盘片同心圆分割成一个个的小区块,这些区块组成一个圆形,可以让机械手臂的磁头进行读写。这个小区块就是硬盘的最小物理存储单位,即 扇区(sector)。位于同一个同心圆上的扇区组成的圆环,即 磁道(track)。硬盘中可能包含多个盘片,在所有盘片上的同一个磁道组成了所谓的 柱面(cylinder),柱面是文件系统的最小单位,也是分区的最小单位。

LBA 寻址方式

LBA 寻址方式的硬盘使用集成电路代替物理旋转磁盘,主要由主控与闪存芯片组成。数据的读写速度远远高于 CHS 寻址方式的硬盘。

硬盘分区

了解了硬盘结构,再来看硬盘分区。

关于硬盘分区,首先思考一个问题:为什么要分区?其实主要有两个原因:

  1. 数据的安全性。由于每个分区的数据是独立的,使得数据更加安全。
  2. 访存的高效性。对于 CHS 寻址方式的硬盘,由于分区将数据集中在某个柱面的区段,如第一个分区位于柱面号 1~100。当需要对该分区进行访存时,硬盘只会在 1~100 柱面范围内进行操作,从而提升了数据的访存性能。

既然硬盘能被分区,那么其分区信息是如何保存的呢?答案就是分区表。但是对于不同寻址方式的硬盘,其分区表的格式也不同,主要有两种:

  • MBR 分区表:多用于 CHS 寻址方式的硬盘
  • GUID 分区表:多用于 LBA 寻址方式的硬盘

分区表有存储在哪里呢?和绝大多数文件将自身的基本描述信息放在文件的开头类似,分区表作为硬盘的基本信息,同样保存在硬盘最前面的存储区域。

下面分别介绍 MBR 分区表和 GUID 分区表。

MBR 分区表

MBR 分区表保存在硬盘的 第一个扇区,由于第一个扇区主要记录了两个重要信息,也称为 主引导记录区(Master Boot Record,MBR)。这两个信息分别是:

  • MBR 分区表:记录整个硬盘的分区信息,容量为 64 Bytes。
  • 引导程序(Boot Loader):容量为 446 Bytes。

MBR 分区表

分区表占据了 MBR 64 Bytes 的空间,最多只能记录 4 组分区信息,每组分区信息记录了该分区的 起始与结束的柱面号,这 4 组分区信息称为 主要分区(primary partition)延伸分区(extended partition)

假设上述硬盘的设备文件名为 /dev/sda,则这四个分区在 Linux 中的设备文件名如下所示,重点在于文件名后面会再接一个数字,这个数字与分区在硬盘中的位置有关。

  • P1:/dev/sda1
  • P2:/dev/sda2
  • P3:/dev/sda3
  • P4:/dev/sda4

由于分区表只有 64 Bytes,最多只能记录 4 组分区信息,那么是否意味着一个硬盘最多只能分割成 4 个分区呢?当然不是!虽然第一个扇区的分区表只能记录 4 组分区信息,但是利用其中的延伸分区信息进一步索引到一个新的分区表,从而记录更多分区信息。如下图所示:

上图所示,硬盘第一个扇区中的四个分区记录仅仅使用了两个,P1 为 主要分区,P2 为 延伸分区。延伸分区的目的是使用额外的扇区来记录分区信息。通过延伸分区所指向的那个区块继续记录分区信息。上图延伸分区索引的分区表继续分出了 5 个分区,这 5 个有延伸分区分出来的分区,称为 逻辑分区(logical partition)

同理,上图中的分区在 Linux 中的设备文件名如下所示。其中的 /dev/sda3/dev/sda4 则保留给主要分区和延伸分区了,所以逻辑分区的设备文件名从 5 开始。

  • P1:/dev/sda1
  • P2:/dev/sda2
  • L1:/dev/sda5
  • L2:/dev/sda6
  • L3:/dev/sda7
  • L4:/dev/sda8
  • L5:/dev/sda9

MBR 主要分区、延伸分区、逻辑分区的特性 - 主要分区与延伸分区最多可以有 4 个(硬盘的限制) - 延伸分区最多只有一个(操作系统的限制) - 逻辑分区是由延伸分区持续分割出来的分区 - 主要分区和逻辑分区可以被格式化;延伸分区不能被格式化 - 逻辑分区的数量上限由操作系统决定

引导程序(Boot Loader)

Boot loader 是操作系统安装在 MBR 中的一套软件,但 MRB 仅仅提供 446 Bytes 的空间给 boot loader,所以 boot loader 是极其精简的。其主要完成以下任务:

  1. 提供菜单:用户可以选择不同的开机项目
  2. 载入核心文件:直接指向可开机的程序区段来启动操作系统
  3. 转交其他 loader:将开机管理功能转交给其他 loader 负责,主要用于多系统引导。

对于第 3 项,表示计算机系统中可能具有两个以上的 boot loader。事实上,boot loader 不仅可以安装在 MBR 中,还可以安装在每个分区的 开机扇区(boot sector) 中。

假设 MBR 中安装的是可以识别 Windows/Linux 的 boot loader,那么整个流程如下图所示:

由上图可知,MBR 的 boot loader 提供两个菜单选项:选项 1(M1)可以直接载入 Windows 的核心文件进行开机;选项二(M2)可以将开机管理任务交给第二个分区的开机扇区(boot sector)。如果用户选择选项 2,第二分区的开机扇区中的 boot loader 将会载入 Linux 的核心文件进行开机。

关于多系统安装 Linux 安装时,可以将 boot loader 安装在 MBR 或其他分区的开机扇区,Linux 的 boot loader 可以手动设置菜单(即上图的 M1、M2),因此可在 Linux 的 boot loader 中加入 Windows 开机的选项 Windows 安装时,其安装程序会主动覆盖 MBR 以及自己所在分区的开机扇区,并且没有选择的机会,也没有让用户自己选择的菜单的功能 结论:安装多系统时应该先安装 Windows 系统

GUID 分区表

MBR 主要有以下限制:

  • 操作系统无法寻址容量超过 2.2TB 的磁盘
  • MBR 只有一个区块,若被破坏后,很难对数据进行恢复
  • MBR 的引导程序所能使用空间只有 446 Byte,无法容纳更多的代码

GUID 则解决了 MBR 的这些问题。

下图所示为 GUID 的结构示意图。与 MBR 使用扇区作为寻址单位不同,GUID 使用 逻辑区块(Logical Block) 作为寻址单位,即采用 LBA(Logical Block Address)寻址方式。MRB 仅使用第一个扇区 512 Bytes 的空间记录分区信息,GUID 则使用 34 个 LBA 区块(每个区块容量默认为 512 Bytes)记录分区信息。MBR 仅有一个扇区保存分区信息,GUID 除了使用硬盘前 34 个 LBA,还是用最后 33 个 LBA 作为备份。

这里有个疑问:为何前面使用 34 个 LBA,后面使用 33 个 LBA。因为第一个 LBA(LBA0)是用来兼容 MBR 的。

LBA0(MBR 兼容区块)

LBA0 为了兼容 MBR,该区块也分为两个部分,分别用于存储 MBR 分区表和引导程序。因为LBA0 是针对 MBR 兼容模式,因此其分区表中仅仅存放一个特殊标志的分区表信息,用来标识此硬盘为 LBA 寻址方式。

LBA1(GUID 分区表表头)

LBA1 记录了分区表本身的位置和大小,同时记录了备份分区表的位置(即最后 33 个 LBA)。此外还存放了分区表的校验码(CRC32),表示硬盘的完整性。

LBA2~33(分区表表项)

从 LBA2 开始,每个 LBA 都可以记录 4 组分区信息。默认情况下,总共可以有 4 * 32 = 128 组分区信息。因为每个 LBA 有 512 Bytes,所以每组分区信息可使用 128 Bytes 的空间。这 128 Bytes 的分区信息中,分别提供了 64 Bits 用于记录分区对应的 起始/结束 区块号。因此,GUID 能够支持的硬盘的最大容量为 2^64 * 512Byte = 233 TB

参考

  1. 硬盘寻址方式
  2. SSD固态硬盘的结构和基本工作原理概述
  3. 《鸟哥的 Linux 私房菜——基础学习篇》
  4. 《Linux 系统架构和应用技巧》
  5. 《Linux 系统架构与目录解析》