通用資訊

本文件包含在使用核心中的 Rust 支援時需要了解的有用資訊。

no_std

核心中的 Rust 支援只能連結 core,不能連結 std。要在核心中使用的 crate 必須使用 #![no_std] 屬性選擇此行為。

程式碼文件

Rust 核心程式碼使用 rustdoc(其內建文件生成器)進行文件化。

生成的 HTML 文件包括整合的搜尋、連結的專案(例如型別、函式、常量)、原始碼等。它們可以在以下網址閱讀:

對於 linux-next,請參閱

還有每個主要版本的標籤,例如

這些文件也可以輕鬆地生成並在本地閱讀。這非常快(與編譯程式碼本身相同的數量級),並且不需要特殊的工具或環境。這還有一個額外的好處,它們將根據使用的特定核心配置進行定製。要生成它們,請使用與編譯相同的呼叫使用的 rustdoc 目標,例如

make LLVM=1 rustdoc

要在 Web 瀏覽器中在本地閱讀文件,請執行例如

xdg-open Documentation/output/rust/rustdoc/kernel/index.html

要了解如何編寫文件,請參閱 編碼準則

額外的 lints

雖然 rustc 是一個非常有用的編譯器,但一些額外的 lints 和分析可以透過 clippy(Rust linter)獲得。要啟用它,請將 CLIPPY=1 傳遞給用於編譯的相同呼叫,例如

make LLVM=1 CLIPPY=1

請注意,Clippy 可能會更改程式碼生成,因此在構建生產核心時不應啟用它。

抽象 vs. 繫結

抽象是從 C 端包裝核心功能的 Rust 程式碼。

為了使用 C 端的函式和型別,需要建立繫結。繫結是 C 端那些函式和型別的 Rust 宣告。

例如,可以在 Rust 中編寫一個 Mutex 抽象,它包裝 C 端的 struct mutex,並透過繫結呼叫其函式。

並非所有核心內部 API 和概念都提供抽象,但預計隨著時間的推移,覆蓋範圍會擴大。“葉”模組(例如驅動程式)不應直接使用 C 繫結。相反,子系統應根據需要提供儘可能安全的抽象。

                                                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 #--------------------------------+

主要思想是將與核心 C API 的所有直接互動封裝到經過仔細審查和記錄的抽象中。然後,只要滿足以下條件,這些抽象的使用者就不會引入未定義的行為 (UB):

  1. 抽象是正確的(“sound”)。

  2. 任何 unsafe 塊都遵循呼叫塊內操作所必需的安全約定。類似地,任何 unsafe impl 都遵循實現 trait 所必需的安全約定。

繫結

透過將 include/ 中的 C 標頭檔案包含到 rust/bindings/bindings_helper.h 中,bindgen 工具將自動生成包含的子系統的繫結。構建後,在 rust/bindings/ 目錄中檢視 *_generated.rs 輸出檔案。

對於 bindgen 未自動生成的 C 標頭檔案的部分,例如 C inline 函式或非平凡的宏,可以向 rust/helpers/ 新增一個小的包裝函式,使其也可用於 Rust 端。

抽象

抽象是繫結和核心使用者的層。它們位於 rust/kernel/ 中,它們的作用是將對繫結的不安全訪問封裝到儘可能安全的 API 中,並將該 API 公開給其使用者。抽象的使用者包括用 Rust 編寫的驅動程式或檔案系統等。

除了安全性方面,抽象還應該是“符合人體工程學的”,因為它們將 C 介面轉換為“慣用”的 Rust 程式碼。基本的例子是將 C 資源獲取和釋放轉換為 Rust 建構函式和解構函式,或者將 C 整數錯誤程式碼轉換為 Rust 的 Result

條件編譯

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

對於 Rust 的 cfg 不支援的其他謂詞,例如具有數值比較的表示式,可以定義一個新的 Kconfig 符號

config RUSTC_VERSION_MIN_107900
        def_bool y if RUSTC_VERSION >= 107900