通用資訊¶
本文件包含在使用核心中的 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):
抽象是正確的(“sound”)。
任何
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