🔥Linux Storage Stack 终极详细解读(精简但超透彻)
下面按照存储 I/O 从应用 → 内核 → VFS → Page Cache → Block Layer → 设备 → 物理硬件的顺序讲。
Linux Storage Stack Diagram
① 应用层(Userspace)
应用通过系统调用进入内核:
| 调用 | 作用 |
|---|---|
| read/write | 最典型的 I/O |
| pread/pwrite | 带偏移 |
| open/close | 打开文件句柄 |
| fsync/fdatasync | 刷写到磁盘 |
| mmap | 将文件映射到虚拟内存 |
| O_DIRECT | 绕过 page cache |
⭐ 核心概念
- 默认 I/O都走 page cache(缓存读写)。
O_DIRECT直接下发 BIO,没有缓存,也无合并能力,需要对齐。mmap读写数据也等价于读写 page cache。
② VFS 层(Virtual File System)
VFS 是所有文件系统的统一接口。
它不干活,只做路由 + 抽象。
⭐ VFS 只负责:
- inode 抽象
- dentries
- 通用的 read/write/open 接口,转发到具体文件系统
⭐ 支持的文件系统类型(图中四类)
| 类别 | 示例 | 特点 |
|---|---|---|
| Block-based FS | ext2/ext3/ext4、xfs、btrfs、f2fs | 工作在 block device 上 |
| Network FS | NFS、SMB、CephFS | 底层不是块设备,是网络 |
| Pseudo FS | procfs、sysfs、tmpfs、devtmpfs | 内核自身结构或内存 |
| Stackable FS | overlayfs、unionfs、ecryptfs | 叠加构造新文件系统 |
| FUSE | s3fs、sshfs | 文件系统逻辑在用户态处理 |
③ Page Cache(页面缓存)
Linux I/O 的核心加速层。
⭐ 作用
- 读缓存:命中返回内存,不命中才下发 I/O
- 写缓存:write() 直接写 RAM → 变成 dirty page → 后台 flush 线程刷到磁盘
- 合并小 I/O:多个小写合并成大块 sequential 写,提高性能
⭐ 调优关注点
vm.dirty_ratio、vm.dirty_background_ratio、写回速率、readahead
④ Direct I/O(绕过 page cache)
VFS 会直接构造 BIO 给 block layer。
特点:
- 不缓存
- 不合并
- 要求对齐
- 性能依赖硬件与 block 层调度
数据库通常搭配 O_DIRECT。
⑤ BIO(block I/O)结构
BIO 是 Linux 存储栈的原子 I/O 单元。
BIO 含有:
- sector(扇区号)
- vec(页列表)
- 操作类型(读/写)
- 回调函数
BIO 由 FS 或 Direct I/O 产生 → block layer 接收。
⑥ Block Layer(块层)
核心调度中心。
分为两套模式:
⑥-1:传统单队列(I/O Scheduler)
图中黄色模块:noop、cfq、deadline
| 调度器 | 适用场景 |
|---|---|
| noop | SSD、RAID、有自己调度逻辑的设备 |
| deadline | 数据库场景、低延迟写入 |
| cfq(已废弃) | 桌面系统 |
功能:
合并 I/O、排序、延迟控制、限速。
⑥-2:blk-mq 多队列(现代内核)
blk-mq:每 CPU / 每硬件队列一个队列,彻底并行化。
NVMe = 取代传统队列 → 每个核独立 IO 队列
virtio-blk、scsi-mq 也使用 blk-mq
优点:
- 并发高
- 锁竞争低
- 最适合 SSD / NVMe / 高 IOPS 场景
现代系统默认使用 blk-mq。
⑦ Device Mapper(可选叠加层)
图中央蓝色方框。
device-mapper(dm)是 Linux 强大的虚拟块层。
常见模块:
| 模块 | 作用 |
|---|---|
| LVM (dm-linear) | 逻辑卷 |
| dm-multipath | 多路径(SAN) |
| dm-crypt (LUKS) | 加密 |
| dm-cache | SSD/NVMe 作缓存 |
| dm-raid / mdraid | RAID |
| bcache | 大容量 HDD + SSD 缓存 |
可以“任意组合叠加”。
例如:
文件系统 → dm-crypt → dm-cache → RAID → NVMe每层都会增加一点延迟与复杂度。
⑧ 块设备驱动(Block Drivers)
图中的蓝色设备节点:
| 设备 | 含义 |
|---|---|
| /dev/sdX | SCSI / SATA 磁盘 |
| /dev/nvmeXnY | NVMe |
| /dev/vdX | virtio |
| /dev/loopX | 文件映射成块设备 |
| /dev/nbdX | 网络块设备 |
| /dev/rbdX | Ceph RBD |
| /dev/mdX | mdadm RAID |
| /dev/dm-X | device-mapper 生成的设备 |
驱动负责:
- 构造命令
- 与 HBA/NVMe 控制器交互
- 完成中断处理
⑨ SCSI 中层 + 传输类(左下灰色区域)
SCSI 是一个“协议栈”,后端可以是:
- 遥远的 SAN(FC)
- TCP(iSCSI)
- SAS
- SATA(通过 libata)
- USB Mass Storage
SCSI 层负责:
把块请求转换为 SCSI Command(READ/WRITE、INQUIRY)
发送到 transport class:
- scsi_transport_fc(光纤)
- scsi_transport_sas
- scsi_transport_iscsi
SCSI 全局架构使得不同存储介质都可以统一呈现为/dev/sdX。
⑩ 底层物理设备
最底部橙色区域:
- SATA 硬盘
- SAS 硬盘
- SSD(SATA/SAS/NVMe)
- NVMe(PCIe)
- SD 卡
- UFS(手机)
- 服务器 RAID 卡(LSI、Adaptec、MegaRAID)
- 虚拟存储(VMware、KVM、Xen)
IO 最终落到硬盘/闪存控制器。
⑪ Target(LIO) —— 反向路径(左上角)
Linux 内核可以把自己的块设备“导出去”给别人用:
- iSCSI Target
- USB Gadget(做成 U 盘)
- Fibre Channel Target
- NVMe-oF Target
target_core_mod是核心组件。
常见用途:
- 构建软件 SAN
- 本地盘共享给其它节点
🔥 全流程串起来(最核心的一张图)
下面是一次普通 write() 的真实路径:
APP → VFS → Page Cache(写脏页) →(稍后)flush/writeback → BIO → Block Layer(调度/多队列) → DM(可选:LVM/crypt/raid/cache) → 驱动(SAS/NVMe/virtio/…) → 硬件(SSD/HDD/NVMe)如果是 O_DIRECT:
APP → VFS → BIO(跳过 page cache) → Block Layer → DM → 驱动 → 设备如果是网络文件系统(NFS/Ceph):
APP → VFS → Network FS client → 网络栈 → 服务器最终总结(最简洁版)
下面是这张图的一句话 per block 概括:
| 模块 | 一句话说明 |
|---|---|
| 应用 | 发起 read/write |
| VFS | 统一文件接口 |
| FS | ext4/xfs/btrfs/nfs… 解析元数据并生成 I/O |
| Page Cache | 读写缓存,加速90% I/O |
| Direct I/O | 绕过缓存,直接生成 BIO |
| BIO | 基础块 I/O 单元 |
| Block Layer | 调度、合并、多队列并行 |
| I/O Scheduler | 对 HDD 友好;现代 NVMe 依赖 blk-mq |
| blk-mq | 高并发 NVMe / virtio 的核心 |
| Device Mapper | LVM、加密、RAID、多路径、缓存 |
| Block Drivers | NVMe/SCSI/SATA/virtio 等 |
| SCSI Layer | 协议中间层(iSCSI/FC/SAS) |
| Transport | 具体总线:SAS/SATA/FC/iSCSI |
| 物理设备 | 最终的 SSD/HDD/NVMe |
| LIO | 把本地盘导出给别人 |
想要我继续深化哪一部分?
你可以告诉我你想进一步深入哪个模块:
- Page Cache 写回机制?
- blk-mq 多队列内部流程?
- NVMe 队列深度和 IOPS 调优?
- LVM/dm-crypt 性能影响?
- RAID vs dm-raid vs mdadm 的区别?
- 数据库(MySQL/Oracle)最佳 I/O 路径?
- 如何根据 iostat / blktrace 分析瓶颈?