0%

20261010-xianxw-块设备存储链路实现异步 I/O 运行时实习总结

实习总结报告:为块设备存储链路实现异步 I/O 运行时——异步提交、单请求完成与背压机制的设计与实板验证

实习项目:StarryOS 块设备存储链路的异步化改造——为块设备运行时实现异步提交、单请求完成等待与背压机制,在星光 2(VisionFive 2,JH7110)平台 SD 卡上完成实测验证
工作仓库:rcore-os/tgoskits(上游开源仓库),本人仓库:https://github.com/xianxw/tgoskits


一、整体工作概述

1.1 本次改造具体做了什么

实习任务始于星光 2 平台的 SD 卡存储方向:原计划在完成 SD 卡驱动支持的基础上,直接对 SD 卡驱动做异步化改造。完成板卡引导、驱动对接并通过实践验证后,发现直接在驱动层做异步化收益有限——异步的价值在于请求提交与完成等待期间释放执行流,而这需要建立在统一管理请求准入、队列调度与完成路径的块设备运行时层之上,驱动层的单点改造无法获得这些机制。确认后,工作重心调整为块设备运行时的异步化改造,全部工作以 6 个经评审合并的上游 Pull Request 交付。

改造前,任务向块设备提交一次读写请求后,必须同步阻塞在原地等待硬件完成,I/O 期间整个任务无法让出 CPU。改造后,块设备运行时具备了完整的异步 I/O 能力,具体完成了以下五件事:

  1. 异步提交与完成等待:任务提交读写请求后立即返回并挂起让出 CPU,请求完成时由运行时唤醒等待它的任务;一个请求只唤醒等它的那个任务,不产生假唤醒、不丢唤醒;
  2. 异步准入与背压:提交队列满载时,任务挂起排队而非空转重试,队列腾出位置后自动恢复提交;
  3. 并发与取消安全:任务被调度器迁到其他 CPU 恢复后,请求仍提交到原队列;任务中途取消等待时,已进入硬件执行的请求不会被取消,DMA 缓冲由完成路径安全释放,杜绝”取消导致缓冲被过早回收”这类内存错误;
  4. 异步化的前置地基:先用两个 PR 治理运行时生命周期——Ready 资源唯一发布、设备与队列信息冻结、事务化更新与回滚、终止路径资源隔离——使异步提交建立在状态一致、并发安全的运行时之上;
  5. 成体系的验证:58 项宿主机确定性单元测试;星光 2 实板 212 项功能回归(AXTEST_SUITE_OK 零失败);riscv64、x86_64、aarch64、loongarch64 四架构 QEMU 全套;实板同步/异步对照基准——32 请求下时延 −27%、吞吐 +36%、上下文切换 −30%。

需要说明,这次改造的不是”SD 卡专用链路”,而是设备无关的块设备运行时:运行时与驱动之间是通用块设备接口,异步路径中没有任何 SD 或星光 2 专属代码。QEMU 测试环境的块设备正是 NVMe,异步读用例在四架构 QEMU 全套中于 NVMe 上真实执行并全部通过;星光 2 SD 卡是功能与性能实测的主要载体。

1.2 本工作在操作系统异步化中的位置

操作系统的异步化是一项分层工程。以一次文件读写从用户态到达 SD 卡的完整路径为参照,各层的异步化职责自下而上依次为:

1
2
3
4
5
6
用户态接口层        ← 尚未涉及(Linux 侧对应当 io_uring 类接口)
VFS / 系统调用层 ← 尚未异步化
文件系统层(ext4) ← 尚未异步化
块设备运行时层 ← ★ 本实习完成的一层(异步提交、完成等待、准入与背压)
驱动层(DW-MMC) ← 本实习完成引导与同步驱动对接
硬件(SD 卡) —— 控制器单在途,是物理约束

本实习完成了其中块设备运行时层的异步化,以及它下面的驱动与引导层的基础支撑;运行时之上的文件系统层、系统调用层目前仍以同步方式调用运行时(边界说明见第三节末尾)。

1.3 对后续完整操作系统异步化的帮助

虽然异步链路尚未贯通到用户态,但本工作为后续”整栈异步化”打下了四个方面的直接基础:

  1. 可复用的异步原语与语义:单请求完成等待、异步准入与背压、安全的取消语义、跨核提交语义。文件系统层将来接异步时,不需要重新设计这些机制,直接复用即可;
  2. 异步安全性的生命周期前提已经固化:唯一发布者、Ready 信息冻结、事务化更新与回滚、DMA 资源隔离——异步提交/等待若建立在状态可漂移的运行时上会产生难以排查的错误,这些保证现在已有确定性回归测试固化,对上层异步化同样成立;
  3. 测量方法与回归资产就位:同步/异步同负载的实板对照方法、逐操作延迟分位数与调度指标输出、212 项实板功能回归套件。异步链路每向上贯通一层(ext4 → VFS → 系统调用),都可以用同一套方法量化该层带来的收益,形成”改造一层、验证一层”的递进;
  4. 硬件收益形态的明确:实测证实单在途控制器上异步收益来自”任务不阻塞在完成等待 + 上下文切换减少”,而非并发带宽。这为上层异步化的投入方向(减少阻塞点而非追求队列深度)提供了依据。

二、远程仓库与分支说明

本人远程仓库:https://github.com/xianxw/tgoskits (上游 rcore-os/tgoskits 的 fork,全部工作分支保存在此)。

分支 作用
fix/visionfive2-boot PR #1954:星光 2 引导修复(booti 镜像头、SD 根文件系统挂载)
fix/async PR #2135:块运行时 Ready/SMP 发布过程稳定化
fix/block-runtime-lifecycle PR #2256:块运行时生命周期线性化
fix/block-runtime-async-latest-20260909 PR #2349:异步块请求运行时(核心工作)
fix/block-runtime-async-test-20260918 PR #2451:实板同步/异步基准与验证
test/block-runtime-async-performance-20260922 PR #2515:功能回归固化与破坏性写入安全边界
archive/block-runtime-full-tests 完整性能测试的独立归档分支

归档分支单独说明:按照评审确立的原则,性能测量应当与内核功能回归分离,不应放在生产内核的测试路径里。该分支保存的是分离之前构建在内核测试中的完整性能测试版本,含 5 个块设备性能基准(多块写读对照、混合读写对照、单块读同步/异步对照、I/O 等待与计算重叠、请求尺寸扫描)及配套的延迟汇总、速率输出、CPU 占用统计机制。它仅作历史保存与参考:将来设计独立入口的请求级基准时,负载构造与测量方法可从该分支取材,但不应直接合回内核测试。第四节所述的完整性能测试即来自该分支的实板运行。


三、具体工作一览

全部工作按”先打地基、再实现异步、后固化验证”的顺序分五个阶段推进,以 6 个经评审合并的上游 PR 交付:

阶段 PR 工作内容 交付与验证
一:板卡引导与 SD 存储支持 #1954 修复 RISC-V 镜像头错位(booti 报 Bad magic)与 MMC 时钟供给断裂(时钟提供者未对接驱动探测) 星光 2 实现”SD 卡引导 + 根文件系统挂载”的可重复实板环境
二:块运行时生命周期治理 #2135、#2256 Ready 资源唯一发布;设备与队列信息冻结;生命周期门控状态统一;更新事务化(安装—提交—回滚);终止时资源隔离而非强行释放 红-绿确定性回归:rdif-block 28 项、ax-fs-ng 81 项单元 + 3 项集成、nvme-driver 16 项宿主机测试及生命周期交错回归
三:异步块请求运行时(核心工作) #2349 异步提交与单请求完成等待(不丢醒、不假唤醒);异步准入与背压;跨核提交语义;唤醒/回调/析构移出运行时锁外;取消与 DMA 所有权解耦 58 项宿主机确定性单元测试 + StarryOS 异步读 axtest;同步 API 行为不变,同步/异步双路径共存
四:实板基准与验证 #2451 新增同步对照路径,同一负载(32 个单块请求)下同步/异步实板对照测量 时延 −27%、吞吐 +36%、上下文切换 −30%;axtest 198/198
五:功能回归固化与破坏性写入安全边界 #2515 内核测试收敛为 6 项纯功能回归(清单见 5.1 节);破坏性写入保护区模型(已识别分区、分区表元数据、整盘文件系统)与”先恢复、后报告”恢复流程硬化;性能测量移出内核测试路径 scratch 资格策略 13 项 + 声明解析 3 项宿主机测试;axtest 212/212,写入区域逐字节恢复校验

当前边界需要说明:异步链路止步于块设备运行时层,文件系统层与系统调用层仍以同步方式调用运行时;文件系统接入只需将现有同步调用点替换为异步提交与完成等待,运行时侧原语已全部交付并有测试固化。


四、完整性能测试结果

除正文引用的 32 请求对照基准(时延 −27%、吞吐 +36%、上下文切换 −30%)外,完整性能测试在归档分支上于星光 2 实板运行,包括单块读同步/异步对照与并发深度扫描、多块写读对照、混合读写对照、I/O 等待与计算重叠、请求尺寸扫描共 5 项基准,以及逐操作延迟分位数、每秒速率与 CPU 占用统计和全部运行日志。主要结论有三:异步收益随并发深度单调上升(并发 8 时相对同步 +23.9%);全部运行期间控制器单在途(peak_inflight_global=1),收益来自任务侧重叠而非硬件并发;请求合并(多块)是最大的性能杠杆(吞吐提升约 3.9 倍)。

完整测试数据与运行日志收录在实习日志中,不在本报告完整展开,详见:实习日志·总结报告


五、功能正确性验证

功能正确性验证贯穿全部阶段,按层级与时间线完整记录如下。

5.1 内核功能回归用例(星光 2 实板执行,6 项)

用例 验证内容
block_runtime_registration_and_read_consistency 设备注册就绪(容量与逻辑块大小非零);同一 LBA 的同步读与异步读结果逐字节一致;提交/完成/失败计数闭环
block_runtime_async_double_read 同一任务内并发提交两个异步读;两个请求独立完成、独立唤醒;DMA 缓冲与所有权相互独立(改写其一不影响另一)
block_runtime_single_block_contiguous_read_write 8 次单块同步写 + 逐块异步读回,按确定性 pattern 逐字节校验,测试后区域恢复并校验
block_runtime_multi_block_contiguous_read_write 真正的多块请求(8 块)走异步写 + 异步读完成路径,完整缓冲内容与块边界校验
block_runtime_multi_descriptor_contiguous_read_write 16 块(8 KiB)请求跨两个 IDMAC 描述符链式传输(星光 2 DMA 分配 4 KiB 对齐、单描述符上限 4 KiB),覆盖真实链式传输
block_runtime_async_mixed_read_write 偶数块异步写新 pattern、奇数块异步读原始数据,完成顺序无关,每个请求独立判定

每个破坏性用例在测试前后对 scratch 区域做原始字节保存与逐字节恢复校验,保证 SD 卡可复用、不留残留。

5.2 安全门与跳过语义

无 scratch 环境(普通 QEMU)下写用例自动跳过(输出 BLOCK_WRITE_TESTS_SKIPPED)并以成功状态退出,读用例正常执行——保证跨环境 CI 全绿不因环境差异假失败,也不因缺少设备而假通过;安全门本身的资格策略由 13 项宿主机单元测试固化(见 5.5 节)。

5.3 实板运行记录(全部 AXTEST_SUITE_OK、零失败)

阶段 运行内容 结果
PR #2451 基准 + 功能套件 198/198
PR #2515 功能版 纯功能回归(性能移出后) 205/205
归档分支完整版 完整性能测试套件 + 功能回归 210/210
PR #2515 最终版 功能回归 + 安全边界重构 212/212

5.4 QEMU 跨架构全套

riscv64、x86_64、aarch64、loongarch64 四个架构的 StarryOS 套件均全绿执行(写用例自跳过、读用例真实执行)。值得注意的是,QEMU 环境的块设备是 NVMe 而非 SD 卡,因此这套验证同时证明了异步读路径在第二种块设备上的正确性,与 1.1 节”改造面向所有块设备”的定位互为印证。

5.5 宿主机确定性单元测试

PR 测试资产
#2135 rdif-block 28 项;ax-fs-ng 81 项单元 + 3 项集成;nvme-driver 16 项(发布者唯一、信息冻结、DMA 一致性、通道稳定性)
#2256 生命周期交错回归(provisional 提升、安装事务回滚、终止清理)接入 axbuild 测试发现链路
#2349 58 项完成/等待者/准入/通道背压/取消/teardown/DMA 生命周期成体系异步行为测试
#2515 scratch 资格策略 13 项(最小长度、设备边界、root/其他分区/元数据/整盘保护、未知设备拒绝、协议绑定)+ 声明解析 3 项 + 卷扫描元数据断言

所有并发与生命周期修复均采用红-绿验证:先证明同一测试在旧实现上稳定失败,再验证修复后通过;每个 PR 合并前全量通过 cargo xtask clippy(按影响面)与 cargo xtask test,并经 QEMU 全套与实板复验。


六、总结

工作总结

实习以星光 2 的 SD 存储链路为验证载体,完成了块设备运行时的异步化改造:任务提交块 I/O 后不再阻塞等待,而是挂起让出执行流、完成后被精确唤醒,并配套异步准入背压、跨核提交与安全取消语义;此前先以两个 PR 完成运行时生命周期治理,作为异步安全性的地基。全部工作以 6 个经评审合并的上游 PR 交付;异步路径在实板对照中取得吞吐 +36%、时延 −27% 的实证数据;同时建立了覆盖宿主机确定性单元测试、QEMU 四架构全套(NVMe 设备上真实执行)与实板 axtest(212 项)的分层验证体系。


附录:Pull Request 索引

PR 标题 链接
#1954 fix(visionfive2): restore booti and SD rootfs boot https://github.com/rcore-os/tgoskits/pull/1954
#2135 fix(ax-fs-ng): stabilize block runtime lifecycle publication https://github.com/rcore-os/tgoskits/pull/2135
#2256 fix(ax-fs-ng): linearize block runtime lifecycle https://github.com/rcore-os/tgoskits/pull/2256
#2349 feat(ax-fs-ng): add async block request runtime https://github.com/rcore-os/tgoskits/pull/2349
#2451 test(starry): add block runtime async benchmark https://github.com/rcore-os/tgoskits/pull/2451
#2515 test(starry): extend async block runtime performance coverage https://github.com/rcore-os/tgoskits/pull/2515

本人仓库:https://github.com/xianxw/tgoskits (分支说明见第二节)


实习日志:https://github.com/xianxw/StarryOS/wiki

演示视频:https://drive.google.com/file/d/1CK_Iy4NacZsds-AHafIXxjFaCdVCUqMH/view?usp=drive_link