1.. SPDX-License-Identifier: GPL-2.0 2.. include:: ../disclaimer-zh_CN.rst 3 4:Original: Documentation/rust/general-information.rst 5 6:翻译: 7 8 司延腾 Yanteng Si <siyanteng@loongson.cn> 9 10 11基本信息 12======== 13 14本文档包含了在内核中使用Rust支持时需要了解的有用信息。 15 16``no_std`` 17---------- 18 19内核中的 Rust 支持只能链接 `core <https://doc.rust-lang.org/core/>`_, 20而不能链接 `std <https://doc.rust-lang.org/std/>`_。供内核使用的 crate 21必须使用 ``#![no_std]`` 属性选择这种行为。 22 23 24.. _rust_code_documentation_zh_cn: 25 26代码文档 27-------- 28 29Rust内核代码使用其内置的文档生成器 ``rustdoc`` 进行记录。 30 31生成的 HTML 文档包括集成搜索、链接项(如类型、函数、常量)、源代码等。 32它们可以在以下地址阅读: 33 34 https://rust.docs.kernel.org 35 36对于 linux-next,请参阅: 37 38 https://rust.docs.kernel.org/next/ 39 40每个主要版本也有对应的标签,例如: 41 42 https://rust.docs.kernel.org/6.10/ 43 44这些文档也可以很容易地在本地生成和阅读。这相当快(与编译代码本身的顺序相同),而且不需要特 45殊的工具或环境。这有一个额外的好处,那就是它们将根据所使用的特定内核配置进行定制。要生成它 46们,请使用 ``rustdoc`` 目标,并使用编译时使用的相同调用,例如:: 47 48 make LLVM=1 rustdoc 49 50要在你的网络浏览器中本地阅读该文档,请运行如:: 51 52 xdg-open Documentation/output/rust/rustdoc/kernel/index.html 53 54要了解如何编写文档,请看 coding-guidelines.rst 。 55 56 57额外的lints 58----------- 59 60虽然 ``rustc`` 是一个非常有用的编译器,但一些额外的lints和分析可以通过 ``clippy`` 61(一个Rust linter)来实现。要启用它,请将CLIPPY=1传递到用于编译的同一调用中,例如:: 62 63 make LLVM=1 CLIPPY=1 64 65请注意,Clippy可能会改变代码生成,因此在构建产品内核时不应该启用它。 66 67抽象和绑定 68---------- 69 70抽象是用Rust代码包装来自C端的内核功能。 71 72为了使用来自C端的函数和类型,需要创建绑定。绑定是Rust对那些来自C端的函数和类型的声明。 73 74例如,人们可以在Rust中写一个 ``Mutex`` 抽象,它从C端包装一个 ``Mutex结构体`` ,并 75通过绑定调用其函数。 76 77抽象并不能用于所有的内核内部API和概念,但随着时间的推移,我们打算扩大覆盖范围。“Leaf” 78模块(例如,驱动程序)不应该直接使用C语言的绑定。相反,子系统应该根据需要提供尽可能安 79全的抽象。 80 81.. code-block:: 82 83 rust/bindings/ 84 (rust/helpers/) 85 86 include/ -----+ <-+ 87 | | 88 drivers/ rust/kernel/ +----------+ <-+ | 89 fs/ | bindgen | | 90 .../ +-------------------+ +----------+ --+ | 91 | Abstractions | | | 92 +---------+ | +------+ +------+ | +----------+ | | 93 | my_foo | -----> | | foo | | bar | | -------> | Bindings | <-+ | 94 | driver | Safe | | sub- | | sub- | | Unsafe | | | 95 +---------+ | |system| |system| | | bindings | <-----+ 96 | | +------+ +------+ | | crate | | 97 | | kernel crate | +----------+ | 98 | +-------------------+ | 99 | | 100 +------------------# FORBIDDEN #--------------------------------+ 101 102主要思想是将所有与内核 C API 的直接交互封装到经过仔细审查和文档化的抽象 103中。这样,只要满足以下条件,这些抽象的用户就不能引入未定义行为 104(undefined behavior,UB): 105 106#. 抽象是正确的("可靠")。 107#. 任何 ``unsafe`` 块都遵守调用块内操作所需的安全契约。类似地,任何 108 ``unsafe impl`` 都遵守实现该特性所需的安全契约。 109 110绑定 111~~~~ 112 113通过从 ``include/`` 中将 C 头文件包含到 114``rust/bindings/bindings_helper.h``, ``bindgen`` 工具将为所包含的子系统 115自动生成绑定。构建后,请查看 ``rust/bindings/`` 目录中的 116``*_generated.rs`` 输出文件。 117 118对于 ``bindgen`` 不会自动生成的 C 头文件部分,例如 C ``inline`` 函数或 119非平凡宏,可以在 ``rust/helpers/`` 中添加一个小型包装函数,使其也可供 120Rust 端使用。 121 122抽象 123~~~~ 124 125抽象是绑定和内核内用户之间的层。它们位于 ``rust/kernel/`` 中,其作用是 126将对绑定的不安全访问封装到尽可能安全并暴露给用户的 API 中。抽象的用户 127包括用 Rust 编写的驱动程序或文件系统等。 128 129除了安全方面,这些抽象还应该易于使用,也就是说,把 C 接口转换为符合 130Rust 惯例的代码。基本示例包括将 C 的资源获取和释放转换为 Rust 的初始化 131和清理模式,或者将 C 整数错误码转换为 Rust 的 ``Result``。 132 133 134有条件的编译 135------------ 136 137Rust代码可以访问基于内核配置的条件性编译: 138 139.. code-block:: rust 140 141 #[cfg(CONFIG_X)] // Enabled (`y` or `m`) 142 #[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`) 143 #[cfg(CONFIG_X="m")] // Enabled as a module (`m`) 144 #[cfg(not(CONFIG_X))] // Disabled 145 146对于 Rust 的 ``cfg`` 不支持的其他条件,例如带有数值比较的表达式,可以 147定义一个新的 Kconfig 符号: 148 149.. code-block:: kconfig 150 151 config RUSTC_HAS_SPAN_FILE 152 def_bool RUSTC_VERSION >= 108800 153