计算、存储、网络构成了云计算的基本组件。Linux 中的 IO 栈主要分为 Filesystem 与 Block 两层,前者包括 VFS 与各种类型的文件系统(包括 Ext4、XFS 等),描述了数据的组织形式、提供管理数据的接口;而后者包括通用块层 (generic block layer) 与各种类型的块设备驱动(包括 SCSI、NVMe、Virtio 等),主要实现了数据在非易失性存储(HDD、SSD)中的存储。
本系列主要讨论 Block 层,如有涉及到代码内核版本为 4.19。献祭一张 IO 栈的架构图。
从文件系统到设备驱动, IO 栈的路径比较长,这一路径中的各个层级会采用不同的数据传输单元,理解这些数据传输单元对理解整个 IO 栈具有重要作用。本文就主要介绍 IO 栈中的各种数据单元。
sector
hardware disk controller 和 block device driver 都使用 sector 对块设备的地址空间进行寻址
sector 的概念最早源于 HDD 磁盘,后来的 SSD 设备也沿用这一概念,sector 的大小固定为 512 bytes
block
文件系统使用 block 对块设备的地址空间进行寻址,block 的大小是文件系统初始化的时候配置的,例如 mkfs.ext4 的时候可以配置 ext4 文件系统的 block size,ext4 中 block size 可以在 1K ~ 64K 范围内以 2 倍递增,因而一个 block 可以包含多个 sector
文件系统会使用内存对磁盘上的 block 进行缓存,这一部分用于缓存 block 的内存就称为 block buffer
block size 不能超过 page frame size,否则就无法使用 block buffer 特性
以下描述内存中的 block buffer 与磁盘上的 block 之间的映射关系
- 如果 page frame size == block size,那么一个 page frame 中只能容纳一个 block buffer,此时一个 page frame 只能缓存一个 block
- 如果 page frame size > block size,那么一个 page frame 中可以容纳多个 block buffer,一个 page frame 中缓存的多个 block 不一定连续
segment
hardware disk controller 和 block device driver 还有 segment 的概念
segment 的概念实际来自 DMA controller,DMA controller 可以实现一段内存物理地址区间与一段设备物理地址区间之间的数据拷贝,segment 就描述 DMA 数据传输过程中的一段连续的内存空间,也就是说 DMA controller 可以将内存中一个 segment 中的数据拷贝到设备,或将设备中的数据拷贝到 segment 中
disk controller 正是使用 DMA 来实现内存和磁盘之间的数据传输,老式的控制器只能支持 adjacent disk sectors 与 continuous physical memory 之间的 DMA 映射,而新式的磁盘控制器支持 scatter-gather DMA 特性,即支持 adjacent disk sectors 与多个 discontinuous physical memory 之间的 DMA 映射,此时将每一段 continuous physical memory 区间都称为一个 segment
segment 可以是一个 page,也可以是一个 page 的其中一部分,通常存储一个或多个相邻的 sector 的数据
一次 scatter-gather DMA transfer 实际上就包含一个或多个 segment