从去年九月,Linux 内核维护者 Greg 表示愿意接受用 Rust 开发 Linux 驱动,到今年七月,Linus Torvalds 回应称可以默认启用 Rust 支持,Linux 开发者并非只是说说而已。
在八月底举办的 2020 Linux Plumbers 大会上,关于 Linux 内核上游对 Rust 的开放程度成为了最热门的讨论话题。Rust 语言团队的联合负责人 Thomas 和 Gaynor,以及 Linux 内核开发者 Josh Triplett 等人参与了这场讨论,并向大家展示了截至目前的一些研究成果、想法,还有遇到的问题。
他们强调,并不打算将已有的内核改写成 Rust,而只专注于可以用 Rust 编写的新代码。具体来讲,与会者集中讨论了 Linux 内核对 Rust 的支持可能涉及到的三个方面:内核中现有的 API、架构支持,和 ABI 与内核的兼容性问题。
绑定到现有的 C API
目前来看,Rust 能够生成可以链接到内核的代码还不够。它还需要一种方法来访问 Linux 内核中使用的大量 API,这些 API 目前都在 C 头文件中定义。
Linux 内核开发者指出,Rust 与 C 具有良好的互操作性;此外,bindgen 工具能够解析 C 头文件以生成适当的 Rust 声明,因此 Rust 不需要从 C 复制重复的定义,这也提供了一种跨语言类型检查的措施。
从表面上看,这些特性使 Rust 具备了与现有 C API 集成的良好条件,但实际上实施起来还存在一些挑战。例如,Linux 大量使用了预处理器宏和内联函数,bindgen 和 Rust 的外函数接口不容易支持它们。
有关 API 绑定的第二个问题是:需要手动封装多少 C API 才能呈现惯用的 Rust 接口?
Thomas 和 Gaynor 展示了一个 linux-kernel-module-rust 项目,可在其中看到内核模式的 Rust 代码示例。在这个项目中,指向用户空间的指针被封装到 UserSlicePtr 类型中。这样的封装生成的代码对现有 Rust 开发者而言更加熟悉,并使 Rust 的类型系统和借用检查器提供最大程度的安全性。但是,必须针对每个 API 进行设计和开发,用 C 和 Rust 编写的模块也会创建不同的 API。这无疑加重了工作的繁琐度。
John Baublitz 也给出了一个演示模块,它更直接地绑定了内核的用户访问功能,绑定多由 bindgen 自动生成。然而,Rust 开发者对这些代码可能会不太习惯,并且这种方式可能需要放弃 Rust 的许多安全保证。
最后,会议达成了共识:对于某些最常见和关键的 API,编写 Rust 封装器是有意义的,但是手动封装每个内核 API 不可行。Thomas 还提到谷歌正致力于自动生成 C++ 代码的惯用绑定,并考虑内核是否可以做类似的事情。
架构支持
对架构的支持是讨论的另一个重点。与会者表示,在 Rust 中实现 Linux 驱动是可以接受的,但无论如何不能把它放在更晦涩难懂的架构上。
在这方面,现阶段唯一成熟的 Rust 实现是 rustc 编译器,该编译器通过 LLVM 发出代码。Linux 内核支持多种架构,其中一些没有可用的 LLVM 后端,另一些存在 LLVM 后端,却尚不受 rustc 支持。
Triplett 认为,先将 Rust 添加到 Linux 内核中,反过来会有助于增加对更多架构的 Rust 支持。就像 Rust 软件被引入 Debian 后,吸引了更多不同架构的爱好者协助改进 Rust 支持一样,他寄希望于为 Linux 内核添加 Rust 支持也获得类似的效果。
ABI 与内核的兼容性
Gaynor 问到了有关 ABI 兼容性的建议。当前 Rust 是通过 LLVM 编译的,而 Linux 内核通常使用 GCC 构建,因此将 Rust 代码链接到内核可能意味着混合 GCC 和 LLVM 发出的代码。
参与讨论者担心 LLVM 与 GCC 可能会有 ABI 兼容的问题,于是提出一个设想,即 Linux 内核社区是否可以将 Rust 支持仅限于使用 Clang 构建的内核,以确保兼容性。
Linux 内核维护者 Greg 指出,当前的内核规则是,仅当内核中的所有目标文件使用相同的编译器并使用相同的标志构建时,才能保证兼容性。不过,他仍然对将 LLVM 构建的 Rust 对象链接到 GCC 构建的内核表示满意,因为只要配置适当,并通过测试即可。他认为不需要任何预先的限制,直到真正有实际问题产生。
另一位内核开发者 Triplett 也强调,GCC 和 Rust 之间的调用是常规且普遍的,不必担心兼容性。因此目前看来,二者的兼容性问题目前不会成为将 Rust 引入 Linux 内核的阻碍。
这场会议上的讨论大致到此,暂时没有后续消息。随着越来越多的人对此抱有期待和热情,正如 LWN.net 所说,或许待一个具体的 Rust 内核驱动用例出现时,所有的争议和决策都将变得更加清晰。