요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
General Information
===================
This document contains useful information to know when working with
the Rust support in the kernel.
``no_std``
----------
The Rust support in the kernel can link only `core <https://doc.rust-lang.org/core/>`_,
but not `std <https://doc.rust-lang.org/std/>`_. Crates for use in the
kernel must opt into this behavior using the ``#![no_std]`` attribute.
.. _rust_code_documentation:
Code documentation
------------------
Rust kernel code is documented using ``rustdoc``, its built-in documentation
generator.
The generated HTML docs include integrated search, linked items (e.g. types,
functions, constants), source code, etc. They may be read at:
https://rust.docs.kernel.org
For linux-next, please see:
https://rust.docs.kernel.org/next/
There are also tags for each main release, e.g.:
https://rust.docs.kernel.org/6.10/
The docs can also be easily generated and read locally. This is quite fast
(same order as compiling the code itself) and no special tools or environment
are needed. This has the added advantage that they will be tailored to
the particular kernel configuration used. To generate them, use the ``rustdoc``
target with the same invocation used for compilation, e.g.::
make LLVM=1 rustdoc
To read the docs locally in your web browser, run e.g.::
xdg-open Documentation/output/rust/rustdoc/kernel/index.html
To learn about how to write the documentation, please see coding-guidelines.rst.
Extra lints
-----------
While ``rustc`` is a very helpful compiler, some extra lints and analyses are
available via ``clippy``, a Rust linter. To enable it, pass ``CLIPPY=1`` to
the same invocation used for compilation, e.g.::
make LLVM=1 CLIPPY=1
Please note that Clippy may change code generation, thus it should not be
enabled while building a production kernel.
Abstractions vs. bindings
-------------------------
Abstractions are Rust code wrapping kernel functionality from the C side.
In order to use functions and types from the C side, bindings are created.
Bindings are the declarations for Rust of those functions and types from
the C side.
For instance, one may write a ``Mutex`` abstraction in Rust which wraps
a ``struct mutex`` from the C side and calls its functions through the bindings.
Abstractions are not available for all the kernel internal APIs and concepts,
but it is intended that coverage is expanded as time goes on. "Leaf" modules
(e.g. drivers) should not use the C bindings directly. Instead, subsystems
should provide as-safe-as-possible abstractions as needed.
.. code-block::
rust/bindings/
(rust/helpers/)
include/ -----+ <-+
| |
drivers/ rust/kernel/ +----------+ <-+ |
fs/ | bindgen | |
.../ +-------------------+ +----------+ --+ |
| Abstractions | | |
+---------+ | +------+ +------+ | +----------+ | |
| my_foo | -----> | | foo | | bar | | -------> | Bindings | <-+ |
| driver | Safe | | sub- | | sub- | | Unsafe | | |
+---------+ | |system| |system| | | bindings | <-----+
| | +------+ +------+ | | crate | |
| | kernel crate | +----------+ |
| +-------------------+ |
| |
+------------------# FORBIDDEN #--------------------------------+
The main idea is to encapsulate all direct interaction with the kernel's C APIs
into carefully reviewed and documented abstractions. Then users of these
abstractions cannot introduce undefined behavior (UB) as long as:
#. The abstractions are correct ("sound").
#. Any ``unsafe`` blocks respect the safety contract necessary to call the
operations inside the block. Similarly, any ``unsafe impl``\ s respect the
safety contract necessary to implement the trait.
Bindings
~~~~~~~~
By including a C header from ``include/`` into
``rust/bindings/bindings_helper.h``, the ``bindgen`` tool will auto-generate the
bindings for the included subsystem. After building, see the ``*_generated.rs``
output files in the ``rust/bindings/`` directory.
For parts of the C header that ``bindgen`` does not auto generate, e.g. C
``inline`` functions or non-trivial macros, it is acceptable to add a small
wrapper function to ``rust/helpers/`` to make it available for the Rust side as
well.
Abstractions
~~~~~~~~~~~~
Abstractions are the layer between the bindings and the in-kernel users. They
are located in ``rust/kernel/`` and their role is to encapsulate the unsafe
access to the bindings into an as-safe-as-possible API that they expose to their
users. Users of the abstractions include things like drivers or file systems
written in Rust.
Besides the safety aspect, the abstractions are supposed to be "ergonomic", in
the sense that they turn the C interfaces into "idiomatic" Rust code. Basic
examples are to turn the C resource acquisition and release into Rust
constructors and destructors or C integer error codes into Rust's ``Result``\ s.
Conditional compilation
-----------------------
Rust code has access to conditional compilation based on the kernel
configuration:
.. code-block:: rust
#[cfg(CONFIG_X)] // Enabled (`y` or `m`)
#[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`)
#[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
#[cfg(not(CONFIG_X))] // Disabled
For other predicates that Rust's ``cfg`` does not support, e.g. expressions with
numerical comparisons, one may define a new Kconfig symbol:
.. code-block:: kconfig
config RUSTC_VERSION_MIN_107900
def_bool y if RUSTC_VERSION >= 107900
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
no_std, rustdoc와 Clippy
1-66커널 Rust 지원을 사용할 때 알아야 할 기본 정보다. 커널은 Rust `core` crate에는 링크할 수 있지만 userspace 기능을 담은 `std`에는 링크할 수 없다. 커널용 crate는 `#![no_std]` 속성으로 이 동작을 명시해야 한다.
Rust 커널 코드는 내장 문서 생성기 `rustdoc`으로 문서화한다. 생성된 HTML에는 통합 검색, 타입·함수·상수 링크와 소스 코드가 포함된다. 현재 문서는 `https://rust.docs.kernel.org`, linux-next는 `/next/`, 각 주 릴리스는 `/6.10/` 같은 tag 경로에서 읽을 수 있다.
로컬 문서는 현재 커널 설정에 맞춰 빠르게 만들 수 있다. 커널 컴파일과 같은 옵션으로 `make LLVM=1 rustdoc`를 실행하고 `Documentation/output/rust/rustdoc/kernel/index.html`을 연다. 작성 규칙은 `coding-guidelines.rst`를 따른다.
추가 lint와 분석에는 Clippy를 사용한다. 평소 컴파일 명령에 `CLIPPY=1`을 더해 `make LLVM=1 CLIPPY=1`로 실행한다. Clippy가 코드 생성을 바꿀 수 있으므로 production kernel을 빌드할 때는 켜지 않는다.
빌드, 문서와 추가 검사를 서로 다른 목적으로 사용합니다.
.. SPDX-License-Identifier: GPL-2.0
General Information
===================
This document contains useful information to know when working with
the Rust support in the kernel.
``no_std``
----------
The Rust support in the kernel can link only `core <https://doc.rust-lang.org/core/>`_,
but not `std <https://doc.rust-lang.org/std/>`_. Crates for use in the
kernel must opt into this behavior using the ``#![no_std]`` attribute.
.. _rust_code_documentation:
Code documentation
------------------
Rust kernel code is documented using ``rustdoc``, its built-in documentation
generator.
The generated HTML docs include integrated search, linked items (e.g. types,
functions, constants), source code, etc. They may be read at:
https://rust.docs.kernel.org
For linux-next, please see:
https://rust.docs.kernel.org/next/
There are also tags for each main release, e.g.:
https://rust.docs.kernel.org/6.10/
The docs can also be easily generated and read locally. This is quite fast
(same order as compiling the code itself) and no special tools or environment
are needed. This has the added advantage that they will be tailored to
the particular kernel configuration used. To generate them, use the ``rustdoc``
target with the same invocation used for compilation, e.g.::
make LLVM=1 rustdoc
To read the docs locally in your web browser, run e.g.::
xdg-open Documentation/output/rust/rustdoc/kernel/index.html
To learn about how to write the documentation, please see coding-guidelines.rst.
Extra lints
-----------
While ``rustc`` is a very helpful compiler, some extra lints and analyses are
available via ``clippy``, a Rust linter. To enable it, pass ``CLIPPY=1`` to
the same invocation used for compilation, e.g.::
make LLVM=1 CLIPPY=1
Please note that Clippy may change code generation, thus it should not be
enabled while building a production kernel.
안전 추상화와 C binding의 경계
67-113추상화는 C 쪽 커널 기능을 감싸는 Rust 코드이고, binding은 C 함수와 타입을 Rust에서 부를 수 있게 만든 선언이다. 예를 들어 Rust의 `Mutex` 추상화는 C의 `struct mutex`를 보관하고 binding을 통해 C 함수를 호출한다.
아직 모든 내부 API와 개념에 추상화가 있는 것은 아니지만 범위를 계속 넓히는 것이 목표다. Driver 같은 leaf module은 C binding을 직접 사용하지 않아야 한다. 대신 subsystem이 필요한 기능을 가능한 한 안전한 추상화로 제공한다.
핵심은 C API와의 직접 상호작용을 꼼꼼히 검토하고 문서화한 추상화 안에 가두는 것이다. 추상화 자체가 sound하고, 모든 `unsafe` 블록과 `unsafe impl`이 각각 호출과 trait 구현에 필요한 safety contract를 지키면 그 사용자는 undefined behavior를 새로 만들 수 없다.
원문의 ASCII 그림을 계층과 허용 방향이 드러나는 구조로 다시 표현했습니다.
Leaf module에서 C binding으로 가는 직접 경로는 금지됩니다.
Abstractions vs. bindings
-------------------------
Abstractions are Rust code wrapping kernel functionality from the C side.
In order to use functions and types from the C side, bindings are created.
Bindings are the declarations for Rust of those functions and types from
the C side.
For instance, one may write a ``Mutex`` abstraction in Rust which wraps
a ``struct mutex`` from the C side and calls its functions through the bindings.
Abstractions are not available for all the kernel internal APIs and concepts,
but it is intended that coverage is expanded as time goes on. "Leaf" modules
(e.g. drivers) should not use the C bindings directly. Instead, subsystems
should provide as-safe-as-possible abstractions as needed.
.. code-block::
rust/bindings/
(rust/helpers/)
include/ -----+ <-+
| |
drivers/ rust/kernel/ +----------+ <-+ |
fs/ | bindgen | |
.../ +-------------------+ +----------+ --+ |
| Abstractions | | |
+---------+ | +------+ +------+ | +----------+ | |
| my_foo | -----> | | foo | | bar | | -------> | Bindings | <-+ |
| driver | Safe | | sub- | | sub- | | Unsafe | | |
+---------+ | |system| |system| | | bindings | <-----+
| | +------+ +------+ | | crate | |
| | kernel crate | +----------+ |
| +-------------------+ |
| |
+------------------# FORBIDDEN #--------------------------------+
The main idea is to encapsulate all direct interaction with the kernel's C APIs
into carefully reviewed and documented abstractions. Then users of these
abstractions cannot introduce undefined behavior (UB) as long as:
#. The abstractions are correct ("sound").
#. Any ``unsafe`` blocks respect the safety contract necessary to call the
operations inside the block. Similarly, any ``unsafe impl``\ s respect the
safety contract necessary to implement the trait.
Binding 생성과 helper wrapper
114-126`include/`의 C header를 `rust/bindings/bindings_helper.h`에 포함하면 `bindgen`이 해당 subsystem의 Rust binding을 자동 생성한다. 빌드 뒤 결과는 `rust/bindings/` 디렉터리의 `*_generated.rs` 파일에서 확인할 수 있다.
C `inline` 함수나 단순하지 않은 macro처럼 `bindgen`이 자동 생성하지 못하는 부분은 `rust/helpers/`에 작은 wrapper 함수를 추가해 Rust 쪽에 제공할 수 있다.
자동 생성 범위와 수동 wrapper 범위를 분리합니다.
Bindings
~~~~~~~~
By including a C header from ``include/`` into
``rust/bindings/bindings_helper.h``, the ``bindgen`` tool will auto-generate the
bindings for the included subsystem. After building, see the ``*_generated.rs``
output files in the ``rust/bindings/`` directory.
For parts of the C header that ``bindgen`` does not auto generate, e.g. C
``inline`` functions or non-trivial macros, it is acceptable to add a small
wrapper function to ``rust/helpers/`` to make it available for the Rust side as
well.
관용적이고 안전한 Rust API
127-141추상화는 binding과 커널 내부 사용자 사이의 계층이며 `rust/kernel/`에 둔다. Unsafe binding 접근을 감싸 가능한 한 안전한 API로 노출하고, Rust로 작성한 driver와 file system 등이 이를 사용한다.
안전성뿐 아니라 사용성도 목표다. C 인터페이스를 관용적인 Rust 코드로 바꾸며, C의 자원 획득과 해제를 Rust constructor와 destructor, 즉 RAII 수명으로 표현하고 C 정수 오류 코드를 Rust `Result`로 바꾸는 것이 기본 예다.
C의 명시적 규약을 Rust 타입과 수명 규칙으로 옮깁니다.
Abstractions
~~~~~~~~~~~~
Abstractions are the layer between the bindings and the in-kernel users. They
are located in ``rust/kernel/`` and their role is to encapsulate the unsafe
access to the bindings into an as-safe-as-possible API that they expose to their
users. Users of the abstractions include things like drivers or file systems
written in Rust.
Besides the safety aspect, the abstractions are supposed to be "ergonomic", in
the sense that they turn the C interfaces into "idiomatic" Rust code. Basic
examples are to turn the C resource acquisition and release into Rust
constructors and destructors or C integer error codes into Rust's ``Result``\ s.
커널 설정에 따른 조건부 컴파일
142-161Rust 코드는 커널 설정을 `cfg` 조건으로 사용할 수 있다. `#[cfg(CONFIG_X)]`는 built-in `y` 또는 module `m`이면 활성화되고, `#[cfg(CONFIG_X="y")]`와 `#[cfg(CONFIG_X="m")]`는 각각 두 상태를 구분한다. `#[cfg(not(CONFIG_X))]`는 설정이 꺼졌을 때 선택된다.
숫자 비교처럼 Rust `cfg`가 직접 지원하지 않는 조건은 Kconfig symbol을 새로 정의해 boolean으로 바꾼다. 예를 들어 `RUSTC_VERSION >= 107900` 조건을 `RUSTC_VERSION_MIN_107900`의 `def_bool`로 만들고 Rust에서는 그 symbol을 조건으로 사용한다.
Kconfig의 y, m, 비활성 상태를 Rust cfg로 정확히 구분합니다.
Conditional compilation
-----------------------
Rust code has access to conditional compilation based on the kernel
configuration:
.. code-block:: rust
#[cfg(CONFIG_X)] // Enabled (`y` or `m`)
#[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`)
#[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
#[cfg(not(CONFIG_X))] // Disabled
For other predicates that Rust's ``cfg`` does not support, e.g. expressions with
numerical comparisons, one may define a new Kconfig symbol:
.. code-block:: kconfig
config RUSTC_VERSION_MIN_107900
def_bool y if RUSTC_VERSION >= 107900
요약·해설
general-information.rst:1-161no_std와 개발 도구, C binding과 안전 추상화의 경계, Kconfig 조건부 컴파일을 설명합니다.