Skip to content

磁盘管理

数据被存储在磁盘上,所谓的磁盘管理就是 Linux 底层相关的操作,管理的是磁盘本身。

设备文件

在类 Unix 操作系统中,一切皆文件。而设备也不例外。设备文件(Device file)是是被驱动程序接口,他们被挂载到/dev目录下。他允许用户应用程序通过标准的 IO 接口来与设备进行交互。

设备类型

类 Unix 操作系统中有两种通用的设备文件:

  • 字符设备文件(Character special files): 提供对硬件的无缓冲(即上层没有磁盘文件系统,直接有字符设备文件提供)字节流(串行)访问,通常一次读取固定字节的数据。常见的字符设备有鼠标、键盘、串口设备(打印机等)以及控制台,字符设备文件标记是c
  • 块设备文件(Block special files): 提供对硬件的有缓存读取或写入,读取和写入的大小通常是任意的。块设备通常要求支持随机存取,最常见的就是硬盘,块设备文件标记是b

磁盘结构

所谓的磁盘通常指机械硬盘(目前常见的文件系统都是针对于他的,固态硬盘也是通过固件兼容机械硬盘的)。机械硬盘的内部结构如下:

磁盘结构

他由一个或多个磁性存储的能够高速旋转的盘片(platter)堆叠而成,每个盘片配备一个能够向盘片读取或写入磁性的磁头(magnetic head)。磁头被安装在摆臂执行器(swinging arm actuator)上来在盘片的任意位置移动。

数据被保存在盘片上,由于盘片是圆形的,为了方便管理他被划分为几个区域:

盘片划分

  • A: 磁道(Track)
  • B: 几何扇区(Genmetrical Sector)
  • C: 磁盘扇区(Disk Sector)
  • D: 簇(Cluster)

其中磁盘扇区(简称扇区)是对磁道的划分,每个扇区存储固定数量的数据,扇区也是数据存储的最小单元,传统的机械硬盘是 512 字节。这意味着文件是占据一个或多个扇区的,如果文件未填满整个扇区,会将为填充的扇区填充零,新文件从新扇区开始。这也就是为什么查看文件属性的时候,文件大小和磁盘大小不一样,磁盘大小一定是扇区的倍数,而文件大小则是 0 1 这些的实际数量。例如一个 100 字节的文件,文件大小就是 100 bytes,但是实际在磁盘中占用 512 bytes。

几何扇区是几何意义上的一个扇形区域,在该区域中的角速度是一样的。并且他们具有相同的扇区。这意味着内磁道的扇区要比外磁道的扇区范围更小(最初的磁盘是这样的,而随着技术的发展每个磁道的扇区不在一直了,不过对计算机来说还是被看作一致的区别被驱动屏蔽了)。由于这种特性外磁道的安全性会好一些,因此像 MBR 就是存储在磁盘的 0 开始的区域它位于最外层磁道。

簇(Cluster)又被叫做分配单位(allocation unit),他是操作系统的文件存储管理单元(我们所谓的分区就是创建簇的过程)。通常是要与扇区对齐(即扇区的整数倍),所谓的 4K 对齐说的就是簇与扇区对齐。

最初是没有物理扇区和逻辑扇区这些概念的,只有扇区这一个概念。不过随着块设备越来越大,512 bytes 也影响了读写性能。硬盘厂商往往会采用增大扇区大小的方法来提升性能,目前主流的是 4096 bytes。但是 4096 bytes 扇区会存在兼容性问题,因此硬盘内部的程序(固件)将 4096 拆分为 8 个逻辑分区(512 bytes)报告给操作系统。因此就就将他们命名为物理扇区和逻辑扇区

通过 fdisk -l 能够查看一个磁盘的这些基础信息:

Bash
yangguodong@debian:~$ sudo fdisk -l /dev/nvme0n1
# 容量(100xxx bytes) 扇区数量(195xxx sectors)
Disk /dev/nvme0n1: 931.51 GiB, 1000204886016 bytes, 1953525168 sectors
# 磁盘名称
Disk model: WDC WDS100T2B0C-00PXH0
# 分配单元
Units: sectors of 1 * 512 = 512 bytes
# 扇区大小(逻辑扇区/物理扇区)
Sector size (logical/physical): 512 bytes / 512 bytes
# I/O 大小(最小/最佳)
I/O size (minimum/optimal): 512 bytes / 512 bytes
# 分区类型
Disklabel type: gpt
# 分区表 UUID
Disk identifier: BE0363A0-EF98-41C8-A4DE-773EB1556038

# 分区 实际上就是簇
# 设备  开始扇区   结束扇区   扇区大小   容量大小  类型
Device             Start        End    Sectors   Size Type
/dev/nvme0n1p1      2048    1050623    1048576   512M EFI System
/dev/nvme0n1p2   1050624  781715455  780664832 372.3G Linux filesystem
/dev/nvme0n1p3 781715456  791480319    9764864   4.7G Linux swap
/dev/nvme0n1p4 791480320 1953523711 1162043392 554.1G Linux filesystem

磁盘类型

磁盘设备文件开头指定了内核中使用的驱动程序子系统(driver subsytem)来操作块设备。

SCSI

这些设备由内核的 SCSI 驱动程序子系统来处理,设备的名称以 sd 开头,后面接一个小写字母。以发现的顺序来命名为 a-z。通过 SCSI 驱动的存储设备支持 SCSI 命令(SCSI、SAS、UASP)、ATA(PATA、SATA)等命令,也是最常见的块设备处理方式。

机械影硬盘或者接口是 SATA 的固态就是这个

NVMe

通过 NVMe(NVM Express) 连接的存储设备。他的设备名称以 nvme 开头,他后面跟数字来作为发现的顺序,之后接 n 在之后就是以 1 开头的序列表示控制器上的设备开始。

Bash
# 第一个发现的控制器(controller) 0 上的第一个设备(device) 1
/dev/nvme0n1

M2 接口的 NVMe 固态就是这个

MMC

SD 卡,MMC/eMMC 等存储设备,他们由内核的 MMC 启动程序子系统处理,这些设备以 mmcblk 开头,之后以数值序列作为发现时间。

注意如果 SD 卡是使用 USB 读卡器接入,这由 SCSI 处理

磁盘分区命名

分区(Partition)设备比较特殊,他们是将单一块设备通过系统分区分割为多个设备:

Bash
# /dev/sda 设备的第一个分区
/dev/sda1

# 通过 p3 来表示第三个分区
/dev/nume2n4p3

列出所有块设备

由 util-linux 提供的lsblk命令来列出所有的块设备:

Bash
lsblk [option] [block device...]

option:
-a/--all: 禁用所有内置过滤器,列出所有块设备
-f/--fs: 输出有关文件系统的信息

$ lsblk lsblk --fs
NAME   FSTYPE FSVER LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1 ext4   1.0         92f11550-cf06-4598-bb9f-6952bd9c7d37  157.9G    14% /
├─sda2
└─sda5 swap   1           e927c546-9f78-4961-854e-679d7fe7f0f2                [SWAP]

块设备使用情况

df命令用于查看磁盘的整体使用情况:

Bash
# `--human/-h` : 人类易读的形式
# `--inode/-i` : 列出inode使用信息

df -hi

文件系统                 Inodes 已用I 可用I 已用I% 挂载点
udev                        16M   588   16M     1% /dev
tmpfs                       16M   958   16M     1% /run
/dev/nvme1n1p2             1.8M  265K  1.5M    15% /
tmpfs                       16M     1   16M     1% /dev/shm
tmpfs                       16M     5   16M     1% /run/lock
/dev/nvme1n1p4              57M  161K   57M     1% /home
/dev/nvme1n1p1                0     0     0      - /boot/efi
tmpfs                      3.2M    86  3.2M     1% /run/user/1000
//192.168.1.200/导出数据      0     0     0      - /home/yangguodong/share/导出数据
//192.168.1.200/rocksfs       0     0     0      - /home/yangguodong/share/rocksfs

如果只是想要查看一个文件、文件夹的磁盘占用,可以使用du来实现:

Bash
# 查看当前文件夹的磁盘占用
du .
47578424        .

du 的结果于 ls 不一样。前者是磁盘占用,后者是文件的实际大小

磁盘管理

磁盘管理主要包括几个方面:

参考