从 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::Driver 与 kernel::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_uart、rust_platform_gpio、rust_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,在未来随时可能被重命名或删除。
实战建议:
- 驱动模块只依赖
kernel::prelude与官方 trait,禁止直接extern "C"调用 C 侧未文档化辅助函数。 - 在
Cargo.toml使用#[no_mangle]时加rust-version = "1.82"锁定,防止 CI 自动升到 nightly。 - 升级内核前,先在
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>