Linux 中磁盘分区基础知识

磁盘设备名

在新版 Linux 中,IDE 和 SATA 的磁盘命名没有区别。

IDE 接口硬盘

由于一个 IDE 接口可以连接两个 IDE 设备,一般主板可以接 4 个 IDE 设备。在系统中,IDE 设备的命名如下:

IDE(Jumper) Master Slave
IDE1(Primary) /dev/hda /dev/hdb
IDE2(Secondary) /dev/hdc /dev/hdd

SATA 接口硬盘

SATA 接口设备名由 Linux 内核检测到磁盘的顺序从 a 开始排列,与插槽号无关。例如,两块磁盘插到 SATA1 和 SATA5 插槽上,系统中识别为 sda 和 sdb。

磁盘阵列

磁盘阵列(RAID,Redundant Arrays of Inexpensive Disks)即容错廉价磁盘阵列,指通过一些技术(软件或硬件)将多个较小的磁盘整合成一个较大的磁盘设备,并且具有一定数据保护的功能。

磁盘阵列类型

磁盘整列有两种组建方式。

硬件磁盘阵列

硬件(hardware)磁盘阵列通过磁盘阵列卡完成组建任务,拥有专门芯片来处理 RAID 任务。性能比较好,例如用来处理 RAID 5 的同位检查码计算,并不会重复消耗原本系统的 I/O 总线。硬件磁盘阵列的设备文件名为/dev/sd[a-p]。

软件磁盘阵列

软件(software)磁盘阵列利用软件来仿真磁盘阵列功能,与 CPU 运算和 I/O 总线速度关系很大。在 CentOS 中提供的软件磁盘阵列软件为 mdadm,支持以分区为单位组建 RAID0/1/5 等。软件磁盘阵列使用的设备文件名是系统的设备文件/dev/md[0-1]。

磁盘阵列等级

常见磁盘阵列等级有 4 种:RAID 0(等量模式,stripe)、RAID 1(映像模式,mirror)、RAID 0+1 或 RAID 1+0、RAID 5。

RAID 0

此模式下,RAID 会将磁盘先切出等量的区块(名为 chunk,大小 4KB ~ 1MB),写入文件时,该文件依据块大小切割好,依序放到各个磁盘中去。

磁盘可用容量为所有磁盘容量之和。

读写性能最佳。

安全性最糟,任意一块磁盘损坏,所有文件数据将缺损,所有数据都会丢失。

RAID 1

此模式让同一份数据完整保存在两块磁盘上面,写入文件时,该文件复制为两份,并分别写入到各个磁盘中去。

磁盘可用容量为所有磁盘容量之和的一半。

写性能在使用软阵列时不好,因为南桥芯片的 I/O 性能有限,同时写入会导致带宽不够。读取性能和 RAID 0 一样。

安全性最好。

RAID 0+1,RAID 1+0

所谓 RAID 0+1 就是先让两块磁盘组成 RAID 0,再将两组 RAID 0 组成一组 RAID 1。RAID 1+0 则是先组 RAID 0,再组成 RAID 1。

磁盘可用容量和 RAID 1 一样只有一半可用。

读写性能和 RAID 0 一样。

安全性和 RAID 1 一样。

RAID 5

至少需要三块以上磁盘才能组建。在每个循环的写入过程中,每块磁盘还加入一个同位检查数据(Parity),这个数据会记录其他磁盘的备份数据,用于磁盘损坏时的恢复。

磁盘可用容量为总磁盘容量减一块磁盘容量。

读写取性能介于 RAID 1 和 RAID 0 之间。

安全性能方面,只接受损坏不超过一块的硬盘情况下恢复数据。

预备磁盘

磁盘阵列中的磁盘损坏时,可更换坏掉的磁盘并插入新的磁盘,磁盘阵列会主动重建数据。这通常需要在关机重启时进行,但 SAS 支持热插拔,可以避免重启。

为实现系统实时主动重建,需要预备磁盘。预备磁盘是指一块或多块未包含在原磁盘阵列等级中的磁盘。只有在磁盘阵列中出现磁盘损坏时,才会主动将预备磁盘引入磁盘阵列中进行数据重建。

逻辑卷管理器

逻辑卷管理器(LVM,Logical Volume Manager)通过软件组合几个物理分区(PV),将它们称为一块看起来是独立的大磁盘(VG),然后再将这块大磁盘分成可使用分区(LV),最终挂载使用。

物理卷

物理卷(PV,Physical Volume)分区需要通过 fdisk 调整系统标识符(system ID)为 8e(LVM 的标识符),然后通过 pvcreate 命令将其转换为 LVM 的最底层物理卷(PV),才能利用这些 PV。

卷用户组

LVM 将许多 PV 整合成卷用户组(VG,Volume Group),在 32 位系统下每个 VG 最多仅能包含 65534 个 PE。如果使用 LVM 默认参数,则一个 VG 最大可达 256GB 容量。在 64 位系统下已不存在限制。

物理扩展块

LVM 默认使用 4MB 的物理扩展块(PE,即 Physical Extent),它是整个 LVM 中最小的存储块,类似于文件系统中的 block 大小。

逻辑卷

VG 会被切分成逻辑卷(LV,即 Logical Volume),这个 LV 就是最后可以被格式化使用的分区。

LV 的大小与此 LV 内的 PE 总数有关。

为了方便用户利用 LVM 管理其系统,LV 的设备文件名通常指定为 /dev/vgname/lvname 的样式。

更改文件系统容量本质是通过交换 PE 来进行数据转换,将原本 LV 内的 PE 转移到其他设备中以降低 LV 容量,或将其他设备的 PE 加到此 LV 中以增大容量。

对 LV 数据写入机制有两种:

  • 线性模式(linear):如果有两个分区 sdb1 和 sdb2 加入到 VG 中,并且整个 VG 只有一个 LV 时,数据会先将 sdb1 写满,再开始写 sdb2。

  • 交错模式(striped):类似于 RAID 0 的模式,同时向两个分区内写入数据。

LVM 的重点在于可以弹性调整文件系统容量,而不是性能优先,因此默认使用线性模式进行读写。

MBR 分区表

目前主流分区表格式有 MBR 和 GPT。早期的 Linux 系统为了兼容 Windows 磁盘,使用的是支持 Windows 的 MBR。

MBR 分区表无法支持 2T 以上容量的硬盘。

第一个扇区

MBR 分区表第一个扇区(512Bytes)用来记录三个重要的信息:

  • 主引导分区(MBR,Master Boot Record):用来安装引导加载程序的地方,有 446Bytes 大小。

  • 分区表(Partition Table):记录整块硬盘的分区状态,有 64Bytes 大小。

  • 引导记录标识(BRID):用来判断设备是否可以用于启动,只有 2 Bytes 大小。值为 55 或 AA 表示可引导。

如果第一个扇区出现物理坏道,整块硬盘都不可用。

主引导分区

MBR 只有 446Bytes,主要提供以下功能:

  • 提供菜单,可以选择不同开机选项,实现多重引导;
  • 载入内核文件,指向可开机的程序区段开启动系统;
  • 转交其他 Loader,将引导加载功能转交给其他 Loader 负责。

分区表

分区表记录了每个分区的起始柱面号,分区只是针对那 64Bytes 的分区表进行设置。由于只有 64Bytes 大小,所以仅能写入四组分区信息。这四组分区信息分为主(Primary)或扩展(Extended)分区。

主分区和扩展分区在 Linux 系统中表示为 sda[1-4]

分区的最小单位为柱面(Cylinder),通常每个分区都包含一个或多个柱面。

扩展分区

扩展分区是指利用额外的扇区来记录分区信息,但无法进行格式化。可以在扩展分区中创建逻辑分区,具体做法是在每个逻辑分区的最前面几个扇区记录分区信息。需要注意的是,一个磁盘最多只能有一个扩展分区,这是操作系统的限制。

为了确保磁盘的连续性,通常将扩展分区的柱面号分配在所有主分区之后。这样可以更好地利用磁盘空间,并有助于提高磁盘读写效率。

逻辑分区

从扩展分区分出的分区也称为逻辑分区(Logical Partition)。在 Linux 系统中,逻辑分区从 hda5 开始计算。

在一个扩展分区内,相邻的逻辑分区可以合并。如果不相邻,则只能重建扩展分区。

需要注意的是,如果扩展分区被破坏,所有的逻辑分区将被删除,因为逻辑分区的信息都记录在扩展分区中。

GPT 分区表

GPT 分区表是为了适应 4K 扇区的硬盘和固态硬盘而设计的,它抛弃了原先以柱面为单位的计算法,改用逻辑区块位址(LBA,Logical Block Address)来规划分区。默认大小为 512Bytes,第一个 LBA 为 LBA0。

GPT 分区表使用前 34 个 LBA 区块来记录分区信息。此外,磁盘最后 33 个 LBA 区块会用于存储分区表备份,以保障分区信息的安全。

MBR 兼容区块

GPT 分区表中的 LBA0 用来兼容 MBR 格式。不同之处在于,原本分区表记录段仅放入一个特殊标志的分区,用来表示此磁盘为 GPT 磁盘。

GPT 表头记录

GPT 分区表中的 LBA1 记录了分区表本身的位置和大小,备份分区表存放位置,以及分区表校验机制码(CRC32)。如果系统检测到分区表有错误,可以通过这个记录区来获取备份分区表并进行恢复。

分区表

分区表存放在 LBA2-33 位置。从 LBA2 开始,每个 LBA 都可以记录 4 笔分区记录,所以默认可以记录 128 个分区记录。

每笔记录占用 128 字节空间,具体内容如下表:

起始字节 长度 内容
0 16 字节 分区类型 GUID
16 16 字节 分区 GUID
32 8 字节 起始 LBA(小端序)
40 8 字节 末尾 LBA
48 8 字节 属性标签(如 bit60 表示“只读”)
56 72 字节 分区名,可以包括 36 个 UTF-16(小端序)字符