Linux 硬盘与文件系统 

Last Update: 2023-11-06

目录

EXT4 文件系统

df -h 命令报告 Size > Used + Avail

创建文件系统时,ext 系列文件系统默认保留 5% 的空间仅供 root 用户使用。目的是在极端情况下为 root 用户提供操作空间。

执行 tune2fs -l <device-partition> 查看设备分区的信息。其中 Reserved block count 记录了为 root 用户保留的 block 的数量。

执行 tune2fs -m 0 <device-partition> 可以释放分区所有的保留空间。

注: mdadm raid 设备 (比如 /dev/md0) 按分区处理。

驱动器命名

软盘驱动器命名:

SCSI 驱动器命名:

IDE 驱动器命名:

硬盘分区通过在硬盘名称后面附加一个十进制数字来表示: sda1 和 sda2 代表系统里的第一个 SCSI 硬盘驱动器的第一个和第二个分区。

给一个例子。假设系统有两个 SCSI 硬盘,一个 SCSI 地址是 2,另外一个地址是 4。第一个硬盘 (在 2 上) 会被命名为 sda,第二个 (在 4 上) 会被命名为 sdb。如果 sda 驱动器有 3 个分区,它们将被命名为 sda1, sda2 和 sda3。这个规律同样适用于 sdb 及其分区。

注意: 如果有两个 SCSI 主机总线适配器 (控制器),设备的顺序可能会比较混乱。最好的解决方案是观察引导信息。如果能知道驱动器型号和/或者容量,也能容易地分辨设备。

扇区与 4K 对齐的分区

最初的物理扇区 (sector) 大小是 512B,这是硬盘一次读写行为操作的最小单位。后来随着硬盘容量越来越大,物理扇区的大小变成了 4096B。

然而,有很多程序依旧按照 512B 的扇区大小来与硬盘交互。为了兼容这些程序,硬盘厂家在硬盘驱动中添加了兼容 512B 扇区的操作逻辑,这种 512B 的扇区叫做逻辑扇区。

比如,很多 boot loader 在代码层面写死了一次只操作 512B 的数据。

实际上,如果程序真的一次操作 512B 的数据,那么硬盘必须先把这 512B 所在的 4K 扇区读到硬盘的缓存中,再从缓存里的这 4K 数据中找要程序要的这 512B 数据返回给程序。

如果这 512B 数据需要修改,程序把这 512B 数据发给硬盘后,如果硬盘在读取这 512B 数据时产生的缓存没有失效,就直接把这 512B 数据覆盖回缓存中的这 4K 数据对应的位置,再把这 4K 数据从硬盘缓存写回到硬盘。如果缓存失效,就必须先把这 512B 数据所在的 4K 扇区中的数据读到缓存里才能继续下一步覆盖、回写的操作。

还有一种更差的情况: 程序要读写的这 512B 数据横跨了两个扇区。这时候就需要把两个 4K 扇区的数据都读出来,然后再在每个扇区中取程序需要的那部分拼起来再返回给程序。

让分区 4K 对齐的目的就是避免出现程序要操作的数据横跨了两个扇区的情况。

操作系统需要使用文件系统来与硬盘交互,而文件系统一次操作的最小单位是一个 block,它的大小可以在建立文件系统时调整。通常,一个 block 的大小是 4K,就是硬盘上一个物理扇区的大小。

所以,让分区 4K 对齐的目的是,在文件系统与硬盘交互时,文件系统每次读写操作的对象正好是一个物理扇区。

前面说过,物理扇区是硬盘一次读写操作的最小单元,即,按照硬盘的读写逻辑,可以认为硬盘是由无数个物理扇区组成的。

如果一个分区从某个扇区的中间开始,那么文件系统要读写的每个 4K block 都会横跨两个 4K 扇区。但如果一个分区从某一个扇区开始的位置开始,从某一个扇区结束的位置结束,那么文件系统要读写的每个 4K block 就只有一个扇区。

所以,简单来说,在硬盘分区时,让分区的边界处于某个物理扇区的边界,就是 4K 对齐。

如何使用分区工具在分区时做到 4K 对齐,看下一节。

硬盘分区

硬盘分区工具

debian 系统中,root 以外的用户没有把 /usr/sbin 加入环境变量,所以用 fdisk 命令时要自己补全路径。

查看硬盘信息 /usr/sbin/fdisk -l ,确定要分区的硬盘设备后,执行 /usr/sbin/fdisk /dev/<device> 后进入命令行。按需输入命令:

cat /proc/partitions 可以查看目前分区情况。

一些老旧系统上的旧版 fdisk 工具只支持 mbr 格式的分区方式,这种方式只能处理 2T 容量及以下的硬盘,如果用它处理 2T 以上的盘,硬盘将只有 2T 可用。当然,新版的 fdisk 已经支持了 gpt 格式的分区方式来处理 2T 以上容量的硬盘。

在这些老旧系统上执行 apt install parted 使用 parted 可以管理容量大于 2T 的硬盘。

执行 parted /dev/<device> 进入命令交互模式,开始分区:

  1. (parted) mklabel gpt 创建 GPT 分区表
  2. (parted) mkpart <primary | logical | extended> [ext4 | xfs |...] <[0% 100%] | [1K,M,G,T 5K,M,G,T]> 创建分区
  3. (parted) name <partition number> <name> 重命名分区
  4. (parted) print 查看硬盘分区
  5. (parted) quit 退出

让分区 4K 对齐

给一个硬盘分区的例子,这个硬盘的分区已经做好了 4K 对齐:

root@gen10:~# fdisk -l /dev/sdc
Disk /dev/sdc: 7.28 TiB, 8001563222016 bytes, 15628053168 sectors
Disk model: HGST HUS728T8TAL
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 99CE863D-073B-CA4B-8272-DBE1C94B7E43

Device     Start         End     Sectors  Size Type
/dev/sdc1   2048 15569258495 15569256448  7.3T Linux filesystem

这是一块西数 HC320 8T 硬盘,从例子第 5 行可以看到,硬盘的逻辑扇区的大小是 512B,物理扇区的大小是 4096B。

还有另一种获取扇区大小的方法:

root@gen10:~# cat /sys/class/block/sdc/queue/logical_block_size
512
root@gen10:~# cat /sys/class/block/sdc/queue/physical_block_size
4096

logical_block_size 的含义是内核进行读写操作的最小单元,physical_block_size 的含义是硬盘执行读写操作的最小单元。也就是说,此时,内核使用 512B 的扇区大小与硬盘交互 (即,使用上文提到的硬盘驱动中的 512B 逻辑扇区兼容层)。

硬盘的扇区号从 0 开始,并且,从前面的信息可以知道,当前系统使用 512B 大小的逻辑扇区与硬盘交互。那么第一个物理扇区 (4096B) 由前 8 个逻辑扇区 (512B) 组成,这 8 逻辑扇区的扇区号是 0-7。以此类推,第二个物理扇区对应的逻辑扇区的扇区号是 8-15。

那么,不难推出:

  1. 如果一个分区的起始逻辑扇区号可以被 8 整除,那么这个分区一定开始于某个物理扇区的开始
  2. 如果一个分区的逻辑扇区数量可以被 8 整除,那么这个分区中一定含有整数个物理扇区

满足以上两个条件就可以认为这个分区做好了 4K 对齐。

注: 注意细节,第一个关键字是扇区号,它从零开始;第二个关键字是扇区数量,它是 fdisk 命令输出中 Sectors 字段对应的值。

在实际操作时 fdisk 做了一些优化: 第一个分区默认的逻辑扇区的扇区号是 2048,它是 fdisk 命令输出中 Start 字段对应的值,它默认满足第一个条件。第二个分区默认开始于第一个分区的最后一个逻辑扇区的下一个逻辑扇区。在分第二个分区时要做好计算。

让内核重新读取分区表

注: 一次执行不成功可执行多次。

硬盘分区上的文件系统

注 1: 一些程序如果在磁盘上检测到了有效的文件系统或 raid 签名 (magic string),就会停止操作该硬盘。如果硬盘之前被用在其他的系统中,则最好先擦除硬盘上的文件系统信息或 raid 签名。

比如,如果硬盘以前在 VMware 全家桶上使用,现在要将其加入 PVE 或者 Ceph 系统。如果硬盘没有做全盘写 0 这种彻底的数据擦除,那么在硬盘初始化阶段中,系统在硬盘中找到了 VMFS_volume_member 信息就会导致初始化失败。解决这个问题需要清理硬盘上已有的文件系统信息或 raid 签名。

手动执行 dd 命令是一种方式,比如 VMFS volume memberVMFS filesystem 的超级块分别位于距离分区起始位置的 1024 KiB 和 2048 KiB 偏移量处,因此 dd if=/dev/zero of=/dev/<disk-device> bs=4M count=1 可以擦除硬盘前 4 MiB 的块来清除残留数据。

当然,也可以使用 wipefs 命令来完成这一过程,但这个命令并不是每个操作系统中都有。

最后可执行 lsblk -f 确认文件系统的类型。

注 2: linux 内核在 4.1 之后支持了 xfs 文件系统,但是这个文件系统在 5.x 的内核中才比较稳定。使用 xfs 需要系统内安装有 xfsprogs

为分区创建文件系统

mkfs 是 util-linux 包的一部分,可以用来创建许多不同种类的文件系统。它只是一个包装工具,为创建不同的文件系统提供了统一的的接口。

mke2fs 是 e2fsprogs 包的一部分,可以用来创建 ext2/3/4 文件系统。创建 ext2/3/4 文件系统时,mkfs 会调用 mke2fs。

/usr/sbin/mkfs.<fs-type> 可以创建指定为 <fs-type> 格式的文件系统。比如 mkfs.ext4, mkfs.xfs 。但如果不加 <fs-type> 参数只执行 mkfs 则默认创建 ext2 格式的文件系统。同时,util-linux 的文档中提到并不推荐使用 mkfs 的格式,应该使用 mkfs.<fs-type> 的格式。

/usr/sbin/mke2fs 的常用参数有:

调整分区属性

ext 系列文件系统的卷标 (使用 e2fsprogs 包中的工具):

xfs 文件系统的卷标 (使用 xfsprogs 包中的工具):

/usr/sbin/tune2fs [OPTION] <device> 命令是 e2fsprogs 包的一部分,可以查看或调整 ext2/3/4 文件系统的某些属性:

注意: 块大小无法修改。

/usr/sbin/dumpe2fs -h <device-partition> 显示 ext 系列文件系统的属性信息。

/usr/sbin/blkid 查找文件系统:

文件系统检测与修复

因进程意外终止或系统崩溃等原因导致文件写入操作非正常中止,可能造成文件损坏。此时应检测并修复文件系统,建议离线进行。

xfs 文件系统 (使用 xfsprogs 包中的工具):

ext 系列文件系统的 (e2fsprogs 包中的) 专用工具 e2fsck 可用于检查 exit2/exit3/exit4 文件系统,命令格式 e2fsck [option] <device>:

/usr/sbin/fsck 和 mkfs 类似,它包装了各种文件系统检测工具,为用户提供了一个统一接口:

挂载设置

文件系统挂载到根目录上的某个目录之后,才能通过该目录访问文件系统,这个目录就是挂载点。挂载点必须:

mount [option] [-t vfstype] [-o options] <device> <dir> 命令可以被用于挂载文件系统到挂载点:

注: 可以将目录绑定至另一个目录上,作为临时访问入口 mount --bind <target-dir> <entrance-dir>

查看当前系统所有已经挂载的设备:

挂载光盘 / U 盘:

挂载本地的回环设备 (直接挂载 ISO 文件): mount -o loop <path-to-iso-file> <path-to-mount-point>

取消挂载

命令 umount {<device> | <dir>} 可以卸载设备。

注: 正在被进程访问的挂载点无法被取消挂载。

取消挂载失败:

  1. 找到哪个进程正在使用挂载点:
    • 显示哪个进程正在使用挂载点里的数据: lsof <path-to-mount-point>
    • 显示哪个用户的什么进程正在使用挂载点的数据: fuser -v <path-to-mount-point>
  2. 干掉所有使用挂载点的进程: fuser -km <path-to-mount-point>

开机自动挂载文件系统

/etc/fstab 文件中,每行 6 个字段定义了一个要开机挂载的文件系统及其相关属性:

  1. 要挂载的文件设备:
    1. 设备文件
    2. LABEL
    3. UUID
    4. 伪文件系统
  2. 挂载点:
    1. 文件夹路径
    2. swap 分区的挂载点为 swap
  3. 文件系统类型
  4. 挂载选项:
    1. defaults 表示使用默认挂载选项
    2. 如果要指明多个挂载选项,每个选项之间用逗号隔开。比如 defaults, acl, noatime, noexec
  5. 转储 (备份) 频率:
    1. 0 表示从不删除
    2. 1 每天备份一次
    3. 2 每隔一天备份一次
  6. 自检次序:
    1. 0 不自检
    2. 1 第一个自检 (通常根文件系统才用 1)
    3. 2 次级自检 (多个文件系统可以有相同的自检次序)
    4. 0-9 自检等级有 0 - 9 多个等级

/etc/fstab 文件中的自动挂载配置实例:

更改完成后,执行 mount -a 即可挂载 /etc/fstab 文件里指明的所有设备。