块层与 I/O 路径
这页讲的是:文件系统最后并不是直接“把字节塞进磁盘”,中间还有块层来组织真正的 I/O 路径。学这页的重点,是理解上层文件请求如何被整理成设备能处理的读写请求。
这块是什么
块层是文件系统与实际块设备之间的重要中间层。它负责把上层产生的 I/O 需求整理、排队、合并、下发给真正设备,让“读一个文件”最终能变成设备控制器和驱动真正能执行的动作。它像交通调度层,把零散请求整理成设备世界能理解的流量。
可以把块层理解成“磁盘交通指挥”:上层不断提出请求,它负责把这些请求排成更可执行的路线和队列。
它负责什么
组织 I/O 请求
- 把上层读写意图整理成设备请求
- 维护请求队列
- 减少乱序和低效访问
- 让设备面对更可执行的工作单元
衔接文件系统和设备
- 承接来自文件系统或页缓存路径的 I/O 需求
- 交给块设备驱动和控制器处理
- 屏蔽部分底层差异
- 让上层不必直接操心设备细枝末节
平衡吞吐与延迟
- 请求合并
- 排队调度
- 完成通知
- 在“快”和“稳”之间找合适路径
为什么文件 I/O 到设备 I/O 之间需要中间层
| 上层看到的 | 底层真正关心的 | 块层的作用 |
|---|
| 读一个文件 | 设备要面对的是哪些块、什么顺序、何时提交。 | 把文件语义转成设备级工作单元。 |
| 很多小读写请求 | 设备通常更希望看到更合理、可合并的访问模式。 | 减少零碎和低效请求直接砸向设备。 |
| 缓存命中或脏页写回 | 底层最终还是要处理真实 I/O 完成。 | 承接写回和读取需求,把它们组织成统一路径。 |
| 不同设备特性 | 不同介质和控制器处理能力差异很大。 | 让上层不用直接绑定到某类设备细节。 |
关键概念
| 概念 | 现在怎么理解 |
|---|
| 块设备 | 按块读写数据的设备视角,是很多存储介质被组织进系统的方式。 |
| 请求队列 | 设备读写请求在下发前需要有序组织的地方。 |
| I/O 合并 | 把多个零散请求尽量整理得更高效,减少设备处理负担。 |
| 写回 | 先在缓存里改、之后再真正落盘的那部分路径。 |
| 完成通知 | 设备处理完请求后,需要把结果和状态反馈回系统。 |
为什么重要
- 它让文件系统和真实设备之间有了可管理的桥梁。
- 很多存储性能问题,不只是文件系统问题,也常是 I/O 路径组织问题。
- 它帮助你理解“为什么读写请求不是立即直接打到设备上”。
- 如果不懂块层,很难真正把上层文件访问和底层设备读写连成一条线。
常见误解
- 误解一:文件系统直接操作磁盘。实际上中间通常还有块层和设备驱动路径。
- 误解二:块层只是性能优化。实际上它还是设备请求组织和完成路径的核心中间层。
- 误解三:只有磁盘很慢时才需要关心它。实际上很多缓存、写回、队列行为都离不开它。
它不负责什么
- 它不定义文件语义,那是 VFS 和具体文件系统的职责。
- 它不直接替代驱动,最终仍要把请求交给设备驱动和控制器。
- 它不等于页缓存,但会大量承接由页缓存与写回产生的 I/O 需求。
和其他模块的关系
| 相关模块 | 关系 |
|---|
| VFS / 文件系统 | 上层文件请求最终要有一部分沿着块层继续往下走。 |
| 内存管理 | 页缓存、回收、写回都会把很多存储行为推到块层路径上。 |
| 驱动 | 块层组织好的请求最终仍由具体驱动与控制器去执行。 |
| 中断与定时器 | 很多 I/O 完成和后续处理会通过事件触发和异步路径推进。 |
你现在最该先建立的 I/O 画面
| 时刻 | 块层在做什么 | 别误会成什么 |
|---|
| 上层刚发来请求 | 先把文件或页缓存路径给出的意图转成块设备世界能理解的工作单元。 | 别以为这时已经是设备在真正读写了。 |
| 很多请求同时涌来 | 块层要决定如何排队、合并、推进,避免设备被零碎访问淹没。 | 别把性能问题只归咎给“磁盘本身太慢”。 |
| 设备开始处理 | 组织好的请求被继续交给驱动和控制器落到真实介质。 | 别把块层和具体驱动看成一回事。 |
| 请求完成返回 | 完成状态要一路反馈回来,让上层知道哪些 I/O 已经真正结束。 | 别把“发出请求”和“数据已经安全完成”混在一起。 |
读完这页后,你应该能回答
- 为什么文件 I/O 到设备 I/O 之间需要块层?
- 为什么“读文件”不等于“立刻直接读磁盘某块”?
- 块层为什么既关性能,也关路径组织和系统秩序?
后面适合继续问:请求队列到底在组织什么?写回路径为什么经常带来性能抖动?块层和具体控制器驱动怎样分工?