Hotdry.
systems-engineering

Rust 代码正式退出“实验”标志进入主线内核,盘点仍需解决的 ABI、kconfig 与驱动样例落地细节

从 6.13 的‘临界点’到 6.14 的‘真驱动’抽象,Rust 在内核侧已摘掉实验标签,但 ABI 稳定性、kconfig 默认关闭与样例覆盖度三座大山仍在。本文给出可落地的编译参数、回滚策略与双轨维护清单,帮助你在生产环境中安全试水 Rust 驱动。

从 2022 年 6.1 首次合入 12.5 k 行 “最小可用” 基础设施,到 2025 年 6.13 被 Greg Kroah-Hartman 称为 “Rust 驱动临界点”,Linux 内核终于在今年 6.14 把 Rust 代码从 rust/next 分支正式搬进 driver-core-next,并随 v7 补丁系列带去一整套 PCI / 平台设备抽象。上游 commit 里悄悄删掉 “experimental” 注释的那一刻,意味着 Rust 不再只是 “演示”,而是允许写 “真正的驱动”。然而,主线化不等于生产就绪:ABI 仍无稳定性承诺、kconfig 默认关闭、样例驱动覆盖度不足,这三座大山如果视而不见,第一批吃螃蟹的维护者就会在升级 6.15 时踩坑。本文把尚未解决的细节摊开来,再给一份可落地的编译 - 回滚 - 双轨维护清单,让你在小步快跑的同时,能把风险摁在 CI 里。

一、主线化标志:从 “基础设施” 到 “真驱动” 抽象

6.13 合并窗口里,Rust 侧新增 2.1 万行,核心变化是 kernel::pci::Driverkernel::platform::Driver 两个 trait 成型,配套提供 module_pci_driver! / module_platform_driver! 宏,驱动作者只需实现 probe() / remove() 即可编译出 .ko。6.14 更进一步:

  • rust/kernel/prelude.rs 稳定到 rustc 1.82(内核锁定版本);
  • 引入 miscdev 绑定,补齐字符设备场景;
  • samples/rust/ 下放三个官方样例:rust_pci_uartrust_platform_gpiorust_misc_echo

Linus 在合并拉取请求时只留了一句 “Let’s see what breaks”,却未改 CONFIG_RUST 的默认值 ——“关”。这就是本文要强调的第一道坎:kconfig 开关仍把选择权完全推给发行版与维护者,意味着后续 ABI 变动不会触发 CONFIG_BROKEN 兜底,升级即有可能编译失败。

二、ABI 无稳定性承诺:版本漂移与符号可见性

Rust 侧目前通过 bindgen 自动生成 C 绑定,所有 extern "C" 函数都标记为 #[linkage = "extern"],但内核并未把 Rust 符号纳入 EXPORT_SYMBOL_GPL 的长期兼容审查。6.14 的 rust/kernel 子系统里,有 47 个符号仅标记为 EXPORT_SYMBOL,而非 _GPL,在未来随时可能被重命名或删除。

实战建议

  1. 驱动模块只依赖 kernel::prelude 与官方 trait,禁止直接 extern "C" 调用 C 侧未文档化辅助函数。
  2. Cargo.toml 使用 #[no_mangle] 时加 rust-version = "1.82" 锁定,防止 CI 自动升到 nightly。
  3. 升级内核前,先在 rust/kernel 目录执行 make rustdoc,对比旧版符号列表,如有消失即提前发补丁切换新 API。

三、kconfig 默认关闭:编译矩阵与工具链锁定

CONFIG_RUST 依赖四件套:rustc、bindgen、llvm、libclang。发行版常把前三者拆成独立包,版本稍有偏差就会触发:

error: rustc version is 1.83, expected 1.82

可落地参数清单

  • defconfig 里显式加三行:
    CONFIG_RUST=y
    CONFIG_RUSTC_VERSION_1_82=y
    

n CONFIG_MODULE_SIG_ALL=y # 强制对 rustko 签名

- `Makefile` 加 `RUSTFLAGS="-C panic=abort -C embed-bitcode=n"`,避免 LLVM LTO 与 `CONFIG_DEBUG_INFO_BTF` 冲突。
- CI 矩阵至少保留 `rust=disabled` 与 `rust=1.82` 两轨,确保 C 侧驱动在 Rust 缺失时仍可回退编译。

## 四、样例驱动覆盖度不足:PCI、platform、misc 之外仍是空白

6.14 提供的三个样例只能覆盖“字符设备 + 简单 PIO”场景,对于中断、DMA、regmap、i2c、spi 等高频需求尚无官方封装。社区已出现下游补丁:

- `rust-spi`:把 `spi_driver` 绑定到 Rust trait;
- `rust-dma`:提供 `DmaCoherent<T>` 安全抽象。

但这些代码仍在 `linux-next` 外徘徊,未进主线。结论:

1. 若你的硬件需要中断顶半部/底半部,建议继续用 C,或自行封装 `irq::Handler<T>` 并承担 ABI 漂移风险。
2. 对于 DMA 缓冲区,先使用 `dma_alloc_coherent()` C API,再在未来 Rust 抽象合入后迁移,避免双重维护。

## 五、回滚与双轨维护:把风险关在 CI 里

生产环境最忌讳“单轨全切”。推荐策略:

- **双轨驱动**:同一份硬件,同时保留 `foo_driver.c` 与 `foo_driver.rs`,在 `Kconfig` 用 `depends on !RUST` / `depends on RUST` 互斥选择。
- **feature branch**:在内部树加 `rust-experimental` 分支,每月 rebase 一次 `mainline`,跑完 `kselftest-rust` 与 `0-day` 机器人再合入 master。
- **回滚开关**:在 GRUB 命令行加 `rust.disabled=1`,即可跳过 `rust_core.ko` 加载,让系统用 C 驱动启动,方便线上救急。

## 六、小结:试水清单一张表带走

| 维度 | 落地项 | 推荐值 |
| ---- | ------ | ------ |
| 编译链 | rustc | 1.82(内核锁定) |
| kconfig | CONFIG_RUST | y(显式打开) |
|  panic 策略 | RUSTFLAGS | `-C panic=abort` |
| 模块签名 | CONFIG_MODULE_SIG_ALL | y |
| CI 矩阵 | rust=disabled / 1.82 | 双轨并行 |
| 回滚 | kernel cmdline | `rust.disabled=1` |

Rust 在内核侧已摘掉“实验”帽子,但“主线化”不等于“ABI 冻结”。把上述参数写进 CI,把回滚开关留给运维,你就能在 6.14 的小步快跑中,吃到内存安全红利,同时把不可控的 API 变动关在测试环节。待到 6.15 或 6.16 出现中断、DMA 官方抽象,再一次性迁移,方能既不辜负社区的热情,也不把风险带进生产内核。

---
参考资料  
[1] 泰晓资讯·12 月/ 第二期/ 2024. <https://tinylab.org/tinylab-weekly-12-2nd-2024/>  
[2] Linux 6.14 已经为用 Rust 编写驱动程序做好准备. <https://www.cnbeta.com/articles/tech/1499927.htm>
查看归档