土法炼钢 · 系统与基础设施

【操作系统百科】Rust for Linux

文章导航

分类入口
os
标签入口
#rust#rust-for-linux#kernel-development#memory-safety#asahi

目录

开篇:内核为什么引入 Rust

Linux 内核约 70% 的安全 CVE 与内存破坏相关——该比例来自 Kernel Self Protection Project 等维护者多年统计与 CNA 分类讨论(具体百分比随年份波动,宜查当年 kernel.org 安全公告汇总,本文引用「内存安全类占主导」这一稳定趋势,不编造精确到小数点的 2026 年报)。

Rust 的 所有权 + 借用检查 在编译期消除:use-after-free、double-free、空指针解引用、数据竞争(在 safe Rust 内)。把 Rust 引入 30 年 C 代码库 的代价是:工具链、ABI、抽象层维护、社区技能分裂。

本文对照 KASLR 与缓解Rust 减漏洞类;KASLR/CFI/Shadow Stack 减利用成功率——正交。

flowchart LR
    C[历史 C 子系统] --> FFI[FFI 边界]
    FFI --> RUST[Rust 驱动 / 模块]
    RUST --> KC[kernel crate 抽象]
    KC --> BIND[bindgen 生成 C API]
    BIND --> C

一、合入主线时间线与能力边界

时间 里程碑 能力
2021 Miguel Ojeda RFC 提出 rust-for-linux 树
2022.12 Linux 6.1 CONFIG_RUST、最小 rust/、示例模块
6.4–6.6 持续扩展 kernel crate、syncalloc、更多驱动实验
6.7+ Asahi DRM 等 大型 Rust 驱动合入讨论/主线
2025–2026 发行版 Fedora 等提供可选 Rust 启用内核包

版本纪律:下文源码路径以 Linux 6.6+ Documentation/rust/ 为锚;读者若用 6.1 需对照 release notes 缺失组件。


二、rust/ 子系统架构

2.1 目录地图

路径 职责
rust/kernel/ kernel crate:模块、sync、error、device 抽象
rust/alloc/ 内核堆分配器绑定
rust/macros/ module!vtable 等过程宏
rust/bindings/ bindgen 生成的 C 结构体/函数
Documentation/rust/ 官方 Rust 内核指南

2.2 kernel crate 与模块入口

use kernel::prelude::*;

module! {
    type: MyDriver,
    name: "my_driver",
    authors: ["..."],
    description: "Example",
    license: "GPL",
}

struct MyDriver;

impl kernel::Module for MyDriver {
    fn init(_module: &'static ThisModule) -> Result<Self> {
        pr_info!("Rust driver loaded\n");
        Ok(MyDriver)
    }
}

对照 C module_init:Rust 用 Result 传播初始化错误,避免 C 式「返回负 errno」与资源泄漏交织。

2.3 pin_init 与自引用结构

内核大量结构 自引用(链表节点、含指针的 struct)。Rust 稳定前用 pin_init / PinnedDrop 模式在 构造期 固定地址,避免 move 后指针失效。

原则(A 级:Documentation/rust/general-information.html):

2.4 sync::Lock 与 C 锁原语映射

Rust 抽象 C 对应 用途
Mutex<T> mutex 睡眠锁
SpinLock<T> spinlock_t 原子上下文
CondVar wait_queue 组合 条件等待

Rust 锁在 编译期 标记 Send/Sync;错误持锁(跨 IRQ 睡眠)尽量在抽象层拒绝。

2.5 错误处理:ResultError

pub fn probe(dev: &Device) -> Result<Pin<KBox<Self>>> {
    let reg = dev.iomap_region(0, None)?;
    // ...
    Ok(Pin::from(kbox!(Self { reg }))
}

? 运算符映射到内核 errno;与 C PTR_ERR 模式对照,减少遗漏检查。


三、与 C 的互操作规则

3.1 #[no_mangle] extern "C" 导出

Rust 回调 C 所需:

#[no_mangle]
pub extern "C" fn rust_helper_do_work(ptr: *mut c_void) -> c_int {
    // safety: 调用约定与 C 侧文档一致
    0
}

3.2 Opaque 类型

C 结构体对 Rust 常为 opaque:仅传递指针,不解引用布局——避免 Rust 与 C 头文件布局漂移。

3.3 bindgenbuild.rs

内核构建集成 bindgen 从 C 头生成 Rust 绑定;C API 变更 必须同步更新绑定与 kernel crate 安全封装——这是 维护负担 核心。

3.4 FFI 边界安全契约

官方要求:unsafe 集中在薄封装层;驱动业务逻辑尽量 safe。违反时 clippy 与 review 聚焦 unsafe 块。


四、案例路径:从示例到 Asahi GPU

4.1 官方示例模块

6.1 起 samples/rust/ 提供最小字符设备、Rust 版 printk 等——适合验证工具链:

make LLVM=1 rustavailable
make M=samples/rust examples

4.2 块层与网络 Rust 实验

邮件列表与 -next 树常见:Rust 块驱动、phy 驱动实验——合入节奏因子系统维护者态度而异。

4.3 Asahi Linux GPU 驱动(里程碑意义)

Apple Silicon GPU 驱动大量使用 Rust 管理:

意义:非玩具——代码规模与状态空间接近生产 DRM 驱动,证明 Rust 可承载真实硬件复杂性。


五、内存安全:C vs Rust 对照表

缺陷类 C 典型表现 Rust safe 代码
UAF 崩溃/利用 编译拒绝
double free 崩溃 编译拒绝
缓冲区溢出 崩溃/利用 边界检查或编译拒绝
数据竞争 KCSAN 运行时抓 Send/Sync 拒绝
空指针 崩溃 Option
整数溢出 未定义行为 checked_* / debug panic

边界unsafe 块内仍可出现上述 bug;FFI 调用 C 仍继承 C 风险。


六、与编译期缓解(CFI、KASAN)的关系

机制 作用阶段 与 Rust 关系
KASAN/KFENCE 运行时检测 C 内存错误 Rust 减少触发,但不替代
CFI 限制间接调用目标 C 代码仍需要;Rust vtable 亦受架构影响
KASLR 布局随机化 与语言无关
Rust borrow 编译期 源头削减 漏洞类

对照 完整性seccomp:Rust 不替代 LSM/沙箱。


七、工具链、ABI 与编译时间

7.1 rustc 版本锁定

内核指定 精确 rustc 版本(见 scripts/min-tool-version.shDocumentation/rust/quick-start.rst)。发行版打包 Rust 内核模块必须用 相同版本 编译——Rust 无稳定 ABI

7.2 架构支持

并非所有 ARCH=CONFIG_RUST=y;嵌入式架构可能长期缺席。部署前查目标架构 Kconfig。

7.3 编译时间

全内核 LLVM=1 + Rust 增量显著增加链接时间——CI 与开发者笔记本是实际摩擦点。

7.4 调试

gdb 对 Rust 符号支持逐年改善,但仍不如 C 成熟;printk + tracing 仍是主力。


八、局限与未解决问题

话题 状态(2026)
内核 async/await 实验性讨论,非生产默认
no_std 约束 无标准库;仅 core + kernel crate
大型 C 子系统重写 不现实;增量替换
形式化验证 Rust 类型 + 个别项目;非全线
社区分裂风险 Linus:不强制 C 维护者学 Rust

8.1 为何不全量重写


九、eBPF 中的 Rust(Aya)— 相关但不同层

// Aya:用户态加载 + 内核 eBPF 程序可用 Rust 编写
#[kprobe]
pub fn try_kprobe(ctx: ProbeContext) -> u32 {
    match try_kprobe(ctx) {
        Ok(ret) => ret,
        Err(_) => 0,
    }
}

AyaBPF 程序 用 Rust——经过 verifier,与 rust-for-linux 内核模块 不同路径。对照 eBPF 核心


十、其他语言实验(对照)

项目 语言 状态
Rust for Linux Rust 合入主线
Redox OS Rust 独立 OS
Hubris Rust Oxide 嵌入式
seL4 C + 证明 微内核形式化
C++ 内核模块 少数驱动 非主线趋势

十一、对应用开发者的影响

短期(2026):几乎无——你仍跑同样 syscall、同样 /proc。收益在 长期 内核攻击面下降。

中期:若使用 out-of-tree 驱动自定义模块,可评估 Rust 分支减少内存类 bug。

跟踪源:LWN.net、rust-for-linux 邮件列表、Documentation/rust/


十二、源码阅读路径(建议顺序)

  1. Documentation/rust/quick-start.rst
  2. samples/rust/minimal.rs
  3. rust/kernel/lib.rs — 模块与错误
  4. rust/kernel/sync/ — 锁抽象
  5. Asahi 或 DRM Rust 驱动(按当前主线文件名)

十三、小结

参考文献

工具


上一篇Unikernel 下一篇机密计算

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。

2026-07-10 · os / architecture

【操作系统百科】OS 的下一个十年

综合 Windows/RTOS/Unikernel/Rust/机密计算/CXL 等前沿篇章,从 Rust 内核、机密计算、可拆分内存、io_uring 统一 I/O、eBPF 可编程内核五条趋势出发,按现在/三年/十年框架说明应用开发者应调整的假设与可执行建议。

2026-07-05 · os

【操作系统百科】实时 OS 巡礼

硬实时与软实时的可调度性边界、VxWorks/QNX/Zephyr 机制对照、Linux PREEMPT_RT 与主线合入、DO-178C/ISO 26262 认证语境,以及选型决策树。

2026-07-06 · os

【操作系统百科】Unikernel

Unikernel 在云上为什么没成主流?MirageOS、IncludeOS、Unikraft、OSv 的设计取舍——库操作系统、启动时间、工具链、调试困难、POSIX 兼容。

2026-07-09 · os / architecture

【操作系统百科】可拆分 OS

CXL 内存池化如何动摇 OS 对本地 DRAM 的假设?从资源解耦、CXL.mem 语义、LegoOS/PhantomOS/Twilight 学术原型,到 Linux CXL 驱动、dax、HMM 与 memory tiering,说明 disaggregated OS 的工程边界与 NUMA 演进。


By .