Linux Kernel Rust 代码梳理
分析日期:2026-01-16
分析范围:Linux kernel 中的 Rust 代码
一、整体架构
rust/ # Rust 核心代码
├── kernel/ # 内核 API 封装(~90个模块)
├── bindings/ # C 绑定
├── uapi/ # UAPI 绑定
├── macros/ # 过程宏(module!, vtable, fmt! 等)
├── pin-init/ # 固定初始化(#[pin_data], pin_init!)
├── zerocopy/ # 零拷贝库
└── ffi.rs # FFI 类型定义
samples/rust/ # 示例代码(~18个)
tools/testing/selftests/rust/ # 自测代码
二、核心模块详解
2.1 kernel crate (rust/kernel/lib.rs)
入口文件,定义了 90+ 个子系统模块:
| 模块 | 功能 |
|---|---|
alloc |
内存分配器(Box, Vec, KBox, KVec) |
sync |
同步原语(Mutex, SpinLock, Arc, CondVar) |
device |
设备模型(Device<Ctx> 泛型类型状态) |
driver |
驱动框架(Driver trait, Registration) |
module |
模块系统(Module, InPlaceModule trait) |
error |
错误处理(Error, Result, 错误码) |
types |
类型系统(Opaque, ForeignOwnable, ScopeGuard) |
pci/usb/i2c |
总线子系统抽象 |
mm/fs/net |
内存/文件系统/网络 |
2.2 内存分配 (kernel/alloc.rs)
rust
// 核心分配器 trait
pub unsafe trait Allocator {
const MIN_ALIGN: usize;
fn alloc(layout: Layout, flags: Flags, nid: NumaNode) -> Result<NonNull<[u8]>, AllocError>;
fn realloc(...) -> Result<NonNull<[u8]>, AllocError>;
fn free(ptr: NonNull<u8>, layout: Layout);
}
// 分配标志
pub mod flags {
pub const GFP_KERNEL: Flags = ...; // 内核上下文
pub const GFP_ATOMIC: Flags = ...; // 原子上下文
pub const __GFP_ZERO: Flags = ...; // 零初始化
}
// 智能指针
pub use kbox::Box; // 等同内核 kmalloc
pub use kvec::Vec; // 动态数组
2.3 同步原语 (kernel/sync.rs)
rust
// 通用锁结构
pub struct Lock<T: ?Sized, B: Backend> {
#[pin] state: Opaque<B::State>,
#[pin] data: UnsafeCell<T>,
}
// 使用示例
pub use lock::mutex::{new_mutex, Mutex, MutexGuard};
pub use lock::spinlock::{new_spinlock, SpinLock};
// 原子引用计数
pub use arc::Arc; // 线程安全引用计数
pub use aref::ARef; // 内核对象引用计数
2.4 设备模型 (kernel/device.rs)
类型状态模式 - 使用泛型参数表示设备上下文:
rust
pub struct Device<Ctx: DeviceContext = Normal>(Opaque<bindings::device>, PhantomData<Ctx>);
// 设备上下文层次结构
// CoreInternal → Core → Bound → Normal
impl Device {
// 安全转换
pub unsafe fn as_bound(&self) -> &Device<Bound>;
pub fn name(&self) -> &CStr;
pub fn fwnode(&self) -> Option<&property::FwNode>;
}
// 设备打印宏
dev_info!(dev, "message: {}\n", value);
dev_err!(dev, "error occurred\n");
2.5 驱动框架 (kernel/driver.rs)
rust
// 驱动注册
pub struct Registration<T: RegistrationOps> {
#[pin] reg: Opaque<T::DriverType>,
}
// 模块驱动宏
module_pci_driver! {
type: SampleDriver,
name: "rust_driver_pci",
license: "GPL v2",
}
2.6 错误处理 (kernel/error.rs)
rust
pub struct Error(NonZeroI32); // 封装内核 errno
pub type Result<T = (), E = Error> = core::result::Result<T, E>;
// 错误码常量
pub mod code {
pub const EINVAL: Error = ...;
pub const ENOMEM: Error = ...;
// 130+ 个标准错误码
}
// C API 转换
pub fn to_result(err: c_int) -> Result; // 负数 → Err
pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T>; // 错误指针转换
2.7 类型系统 (kernel/types.rs)
rust
// 不透明类型 - 封装 C 结构体
pub struct Opaque<T> {
value: UnsafeCell<MaybeUninit<T>>,
_pin: PhantomPinned,
}
// 外部所有权传递
pub unsafe trait ForeignOwnable {
fn into_foreign(self) -> *mut c_void;
unsafe fn from_foreign(ptr: *mut c_void) -> Self;
}
// 作用域守卫
pub struct ScopeGuard<T, F: FnOnce(T)>;
2.8 过程宏 (macros/lib.rs)
| 宏 | 功能 |
|---|---|
module! |
声明内核模块 |
#[vtable] |
Vtable 特质 |
#[export] |
导出函数给 C |
fmt! |
内核格式化 |
concat_idents! |
连接标识符 |
paste! |
粘贴标识符 |
#[kunit_tests] |
KUnit 测试 |
三、总线子系统
3.1 PCI 总线 (kernel/pci.rs)
rust
/// PCI 设备 ID
#[repr(transparent)]
pub struct DeviceId(bindings::pci_device_id);
impl DeviceId {
/// 等价于 C 的 PCI_DEVICE 宏
pub const fn from_id(vendor: Vendor, device: u32) -> Self;
}
/// PCI 设备
#[repr(transparent)]
pub struct Device<Ctx: device::DeviceContext = device::Normal>(
Opaque<bindings::pci_device>, PhantomData<Ctx>,
);
/// PCI 驱动 trait
pub trait Driver {
type IdInfo: 'static;
type Data<'bound>: Send + 'bound;
const ID_TABLE: IdTable<Self::IdInfo>;
fn probe<'bound>(
dev: &'bound Device<device::Core<'_>>,
id_info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
}
3.2 USB 总线 (kernel/usb.rs)
rust
/// USB 驱动适配器
pub struct Adapter<T: Driver>(T);
/// USB 设备 ID
#[repr(transparent)]
pub struct DeviceId(bindings::usb_device_id);
impl DeviceId {
/// 等价于 C 的 USB_DEVICE 宏
pub const fn from_id(vendor: u16, product: u16) -> Self;
}
/// USB 接口(类型状态模式)
#[repr(transparent)]
pub struct Interface<Ctx: device::DeviceContext = device::Normal>(
Opaque<bindings::usb_interface>, PhantomData<Ctx>,
);
/// USB 驱动 trait
pub trait Driver {
type IdInfo: 'static;
type Data<'bound>: Send + 'bound;
const ID_TABLE: IdTable<Self::IdInfo>;
fn probe<'bound>(
interface: &'bound Interface<device::Core<'_>>,
id: &DeviceId,
id_info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
fn disconnect<'bound>(
interface: &'bound Interface<device::Core<'_>>,
data: Pin<&Self::Data<'bound>>,
);
}
3.3 I2C 总线 (kernel/i2c.rs)
rust
/// I2C 设备 ID
#[repr(transparent)]
pub struct DeviceId(bindings::i2c_device_id);
impl DeviceId {
pub const fn new(id: &'static CStr) -> Self;
}
/// I2C 客户端设备
#[repr(transparent)]
pub struct I2cClient<Ctx: device::DeviceContext = device::Normal>(
Opaque<bindings::i2c_client>, PhantomData<Ctx>,
);
/// I2C 驱动 trait
pub trait Driver {
type IdInfo: 'static;
type Data<'bound>: Send + 'bound;
const I2C_ID_TABLE: Option<IdTable<Self::IdInfo>> = None;
const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None;
fn probe<'bound>(
dev: &'bound I2cClient<device::Core<'_>>,
id_info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
}
3.4 Platform 总线 (kernel/platform.rs)
rust
/// 平台设备
#[repr(transparent)]
pub struct Device<Ctx: device::DeviceContext = device::Normal>(
Opaque<bindings::platform_device>, PhantomData<Ctx>,
);
impl<Ctx: device::DeviceContext> Device<Ctx> {
/// 按索引获取资源
pub fn resource_by_index(&self, index: u32) -> Option<&Resource>;
/// 按索引获取 IRQ
pub fn irq_by_index(&self, index: u32) -> Result<IrqRequest<'_>>;
}
/// 平台驱动 trait
pub trait Driver {
type IdInfo: 'static;
type Data<'bound>: Send + 'bound;
const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None;
fn probe<'bound>(
dev: &'bound Device<device::Core<'_>>,
id_info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
}
3.5 总线子系统对比
| 总线 | 核心文件 | Driver Trait | 设备类型 | 注册宏 |
|---|---|---|---|---|
| PCI | kernel/pci.rs |
pci::Driver |
pci::Device<Ctx> |
module_pci_driver! |
| USB | kernel/usb.rs |
usb::Driver |
usb::Interface<Ctx> |
module_usb_driver! |
| I2C | kernel/i2c.rs |
i2c::Driver |
i2c::I2cClient<Ctx> |
module_i2c_driver! |
| Platform | kernel/platform.rs |
platform::Driver |
platform::Device<Ctx> |
module_platform_driver! |
| MDIO | kernel/net/phy.rs |
phy::Driver |
phy::Device |
module_phy_driver! |
四、网络子系统
文件位置 :rust/kernel/net/(mod.rs、netlink.rs、phy/)
4.1 核心结构
rust
// Netlink 消息包装
pub struct NetlinkSkBuff { skb: NonNull<bindings::sk_buff> }
pub struct GenlMsg { skb: NetlinkSkBuff, hdr: NonNull<c_void> }
// Generic Netlink 族
#[repr(transparent)]
pub struct Family { inner: Opaque<bindings::genl_family> }
// PHY 设备抽象
#[repr(transparent)]
pub struct Device(Opaque<bindings::phy_device>);
// PHY 驱动 vtable
#[repr(transparent)]
pub struct DriverVTable(Opaque<bindings::phy_driver>);
4.2 Driver Trait(PHY 子系统)
rust
#[vtable]
pub trait Driver {
const FLAGS: u32 = 0;
const NAME: &'static CStr;
const PHY_DEVICE_ID: DeviceId = DeviceId::new_with_custom_mask(0, 0);
fn soft_reset(_dev: &mut Device) -> Result { build_error!(VTABLE_DEFAULT_ERROR) }
fn probe(_dev: &mut Device) -> Result { build_error!(VTABLE_DEFAULT_ERROR) }
fn config_aneg(_dev: &mut Device) -> Result { build_error!(VTABLE_DEFAULT_ERROR) }
fn read_status(_dev: &mut Device) -> Result<u16> { build_error!(VTABLE_DEFAULT_ERROR) }
}
4.3 Netlink 使用示例
rust
// 定义 Netlink 族
static BINDER_NL_FAMILY: Family = Family::const_new(
kernel::module::this_module::<crate::LocalModule>(),
c"binder_family",
BINDER_FAMILY_VERSION,
&BINDER_NL_FAMILY_MCGRPS,
);
// 发送多播消息
impl Report {
pub fn new(size: usize, portid: u32, seq: u32, flags: alloc::Flags) -> Result<Self> {
let skb = NetlinkSkBuff::new(size, flags)?;
let skb = skb.genlmsg_put(portid, seq, &BINDER_NL_FAMILY, BINDER_CMD_REPORT)?;
Ok(Self { skb })
}
pub fn multicast(self, portid: u32, flags: alloc::Flags) -> Result {
self.skb.multicast(&BINDER_NL_FAMILY, portid, 0, flags)
}
}
4.4 网络子系统架构
rust/kernel/net/
├── mod.rs # 网络模块主入口
├── netlink.rs # Generic Netlink 支持
└── phy/
├── mod.rs # PHY 设备抽象
└── reg.rs # PHY 寄存器接口(C22/C45)
五、文件系统
文件位置 :rust/kernel/fs/、rust/kernel/debugfs.rs、rust/kernel/configfs.rs
5.1 核心结构
rust
// 文件对象封装
#[repr(transparent)]
pub struct File { inner: Opaque<bindings::file> }
// 非线程安全版本
#[repr(transparent)]
pub struct LocalFile { inner: Opaque<bindings::file> }
// 内核 IO 回调
pub struct Kiocb<'a, T> { inner: NonNull<bindings::kiocb>, _phantom: PhantomData<&'a T> }
// DebugFS 目录/文件条目
pub(crate) struct Entry<'a> { entry: *mut bindings::dentry, _parent: Option<Arc<Entry<'static>>> }
5.2 文件操作特征体系
rust
// Writer 特征 - 文本输出
pub trait Writer {
fn write(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
}
// BinaryWriter 特征 - 二进制输出
pub trait BinaryWriter {
fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: &mut file::Offset) -> Result<usize>;
}
// Reader 特征 - 文本输入
pub trait Reader {
fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result;
}
5.3 DebugFS 文件操作实现
rust
// 只读文件实现
impl<T: Writer + Sync> ReadFile<T> for T {
const FILE_OPS: FileOps<T> = {
let operations = bindings::file_operations {
read: Some(bindings::seq_read),
llseek: Some(bindings::seq_lseek),
release: Some(bindings::single_release),
open: Some(writer_open::<Self>),
..pin_init::zeroed()
};
unsafe { FileOps::new(operations, 0o400) }
};
}
// 读写文件实现
impl<T: Writer + Reader + Sync> ReadWriteFile<T> for T {
const FILE_OPS: FileOps<T> = {
let operations = bindings::file_operations {
open: Some(writer_open::<T>),
read: Some(bindings::seq_read),
write: Some(write::<T>),
llseek: Some(bindings::seq_lseek),
release: Some(bindings::single_release),
..pin_init::zeroed()
};
unsafe { FileOps::new(operations, 0o600) }
};
}
5.4 文件系统示例(DebugFS)
rust
#[pin_data]
struct RustDebugFs {
pdev: ARef<platform::Device>,
_debugfs: Dir,
#[pin]
counter: File<Atomic<usize>>,
#[pin]
inner: File<Mutex<Inner>>,
}
impl RustDebugFs {
fn new<'a, 'b>(pdev: &'a platform::Device<Core<'b>>) -> impl PinInit<Self, Error> + use<'a, 'b> {
let debugfs = Dir::new(c"sample_debugfs");
try_pin_init! {
Self {
counter <- debugfs.read_write_file(c"counter", Atomic::<usize>::new(0)),
inner <- debugfs.read_write_file(c"pair", new_mutex!(Inner { x: 3, y: 10 })),
_debugfs: debugfs,
pdev: pdev.into(),
}
}
}
}
六、内存管理
文件位置 :rust/kernel/mm.rs、rust/kernel/page.rs、rust/kernel/alloc.rs、rust/kernel/alloc/allocator.rs
6.1 页抽象
rust
// 页常量
pub const PAGE_SHIFT: usize = bindings::PAGE_SHIFT as usize;
pub const PAGE_SIZE: usize = bindings::PAGE_SIZE;
pub const PAGE_MASK: usize = !(PAGE_SIZE - 1);
// 拥有页所有权的指针
pub struct Page { page: NonNull<bindings::page> }
// 非拥有借用版本
pub struct BorrowedPage<'a>(ManuallyDrop<Page>, PhantomData<&'a Page>);
impl Page {
pub fn alloc_page(flags: Flags) -> Result<Self, AllocError> {
let page = unsafe { bindings::alloc_pages(flags.as_raw(), 0) };
let page = NonNull::new(page).ok_or(AllocError)?;
Ok(Self { page })
}
}
impl Drop for Page {
fn drop(&mut self) {
unsafe { bindings::__free_pages(self.page.as_ptr(), 0) };
}
}
6.2 分配器 Trait
rust
pub unsafe trait Allocator {
const MIN_ALIGN: usize;
fn alloc(layout: Layout, flags: Flags, nid: NumaNode) -> Result<NonNull<[u8]>, AllocError> {
unsafe { Self::realloc(None, layout, Layout::new::<()>(), flags, nid) }
}
unsafe fn realloc(...) -> Result<NonNull<[u8]>, AllocError>;
unsafe fn free(ptr: NonNull<u8>, layout: Layout) {
let _ = unsafe { Self::realloc(Some(ptr), Layout::new::<()>(), layout, Flags(0), NumaNode::NO_NODE) };
}
}
6.3 三种分配器实现
rust
// 连续内核分配器
pub struct Kmalloc;
// 虚拟连续内核分配器
pub struct Vmalloc;
// kvmalloc(先试 kmalloc,失败回退到 vmalloc)
pub struct KVmalloc;
unsafe impl Allocator for Kmalloc {
const MIN_ALIGN: usize = ARCH_KMALLOC_MINALIGN;
unsafe fn realloc(...) -> Result<NonNull<[u8]>, AllocError> {
let layout = Kmalloc::aligned_layout(layout);
unsafe { ReallocFunc::KREALLOC.call(ptr, layout, old_layout, flags, nid) }
}
}
6.4 虚拟内存区域(VMA)
rust
// VMA 包装器
#[repr(transparent)]
pub struct VmaRef { vma: Opaque<bindings::vm_area_struct> }
impl VmaRef {
pub fn start(&self) -> usize { unsafe { (*self.as_ptr()).__bindgen_anon_1.__bindgen_anon_1.vm_start } }
pub fn end(&self) -> usize { unsafe { (*self.as_ptr()).__bindgen_anon_1.__bindgen_anon_1.vm_end } }
pub fn flags(&self) -> vm_flags_t { unsafe { (*self.as_ptr()).__bindgen_anon_2.vm_flags } }
}
// 地址空间包装
pub struct MmWithUser { mm: Mm }
impl MmWithUser {
pub fn mmap_read_lock(&self) -> MmapReadGuard<'_> {
unsafe { bindings::mmap_read_lock(self.as_raw()) };
MmapReadGuard { mm: self, _nts: NotThreadSafe }
}
}
6.5 内存管理组件概览
| 组件 | 文件 | 核心类型 | 功能 |
|---|---|---|---|
| 页抽象 | page.rs |
Page, BorrowedPage |
页分配/释放、映射/解映射 |
| 分配器 | alloc/allocator.rs |
Kmalloc, Vmalloc, KVmalloc |
内存分配/重分配/释放 |
| VMA | mm/virt.rs |
VmaRef, VmaNew |
虚拟内存区域管理 |
| 地址空间 | mm.rs |
Mm, MmWithUser |
进程地址空间管理 |
| IOMMU | iommu/pgtable.rs |
IoPageTable |
IOMMU 页表管理 |
七、进程管理
文件位置 :rust/kernel/task.rs、rust/kernel/cred.rs、rust/kernel/pid_namespace.rs、rust/kernel/workqueue.rs
7.1 任务(Task)抽象
rust
// 包装内核的 struct task_struct
#[repr(transparent)]
pub struct Task(pub(crate) Opaque<bindings::task_struct>);
// 表示当前任务
pub struct CurrentTask(Task, NotThreadSafe);
impl Task {
pub fn pid(&self) -> Pid { unsafe { *ptr::addr_of!((*self.as_ptr()).pid) } }
pub fn tgid(&self) -> Pid { unsafe { *ptr::addr_of!((*self.as_ptr()).tgid) } }
pub fn uid(&self) -> Kuid { Kuid::from_raw(unsafe { bindings::task_uid(self.as_ptr()) }) }
pub fn signal_pending(&self) -> bool { unsafe { bindings::signal_pending(self.as_ptr()) != 0 } }
pub fn wake_up(&self) { unsafe { bindings::wake_up_process(self.as_ptr()) }; }
}
// 当前任务宏
#[macro_export]
macro_rules! current {
() => { unsafe { &*$crate::task::Task::current() } };
}
7.2 进程凭证
rust
// 包装内核的 struct cred
#[repr(transparent)]
pub struct Credential(Opaque<bindings::cred>);
impl Credential {
pub fn euid(&self) -> Kuid { Kuid::from_raw(unsafe { (*self.0.get()).euid }) }
pub fn get_secid(&self) -> u32 {
let mut secid = 0;
unsafe { bindings::security_cred_getsecid(self.0.get(), &mut secid) };
secid
}
}
7.3 同步原语
rust
// 条件变量(等待队列)
#[pin_data]
pub struct CondVar {
#[pin]
pub(crate) wait_queue_head: Opaque<bindings::wait_queue_head>,
#[pin]
_pin: PhantomPinned,
}
impl CondVar {
pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) {
self.wait_internal(TASK_UNINTERRUPTIBLE, guard, MAX_SCHEDULE_TIMEOUT);
}
pub fn wait_interruptible<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) -> bool {
self.wait_internal(TASK_INTERRUPTIBLE, guard, MAX_SCHEDULE_TIMEOUT);
crate::current!().signal_pending()
}
pub fn notify_one(&self) { self.notify(1); }
pub fn notify_all(&self) { self.notify(0); }
}
// 完成同步
#[pin_data]
pub struct Completion { #[pin] inner: Opaque<bindings::completion> }
impl Completion {
pub fn complete_all(&self) { unsafe { bindings::complete_all(self.as_raw()) }; }
pub fn wait_for_completion(&self) { unsafe { bindings::wait_for_completion(self.as_raw()) }; }
}
7.4 工作队列
rust
// 工作队列包装
pub struct Queue(Opaque<bindings::workqueue_struct>);
impl Queue {
pub fn enqueue<W, const ID: u64>(&self, w: W) -> W::EnqueueOutput
where
W: RawWorkItem<ID> + Send + 'static,
{
// 入队工作项
}
pub fn system() -> &'static Queue {
unsafe { Queue::from_raw(bindings::system_wq) }
}
}
7.5 进程管理组件概览
| 组件 | 文件 | 核心类型 | 功能 |
|---|---|---|---|
| 任务 | task.rs |
Task, CurrentTask |
进程/线程抽象 |
| 凭证 | cred.rs |
Credential |
进程权限管理 |
| PID 命名空间 | pid_namespace.rs |
PidNamespace |
PID 隔离 |
| 工作队列 | workqueue.rs |
Queue |
异步任务执行 |
| 条件变量 | sync/condvar.rs |
CondVar |
等待/通知机制 |
八、示例代码分析
8.1 最小模块 (samples/rust/rust_minimal.rs)
rust
module! {
type: RustMinimal,
name: "rust_minimal",
authors: ["Rust for Linux Contributors"],
description: "Rust minimal sample",
license: "GPL",
params: {
test_parameter: i64 { default: 1, description: "..." },
},
}
struct RustMinimal {
numbers: KVec<i32>,
}
impl kernel::Module for RustMinimal {
fn init(_module: &'static ThisModule) -> Result<Self> {
let mut numbers = KVec::new();
numbers.push(72, GFP_KERNEL)?;
numbers.push(108, GFP_KERNEL)?;
numbers.push(200, GFP_KERNEL)?;
Ok(Self { numbers })
}
}
impl Drop for RustMinimal {
fn drop(&mut self) {
pr_info!("My numbers are {:?}\n", self.numbers);
}
}
8.2 PCI 驱动示例 (samples/rust/rust_driver_pci.rs)
rust
impl pci::Driver for SampleDriver {
type IdInfo = TestIndex;
type Data<'bound> = SampleDriverData<'bound>;
fn probe<'bound>(
pdev: &'bound pci::Device<Core<'_>>,
info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> {
pdev.enable_device_mem()?;
pdev.set_master();
let bar = pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_driver_pci")?;
Ok(SampleDriverData { pdev, bar, index: *info.unwrap() })
}
}
8.3 USB 驱动示例 (samples/rust/rust_driver_usb.rs)
rust
struct SampleDriver {
_intf: ARef<usb::Interface>,
}
kernel::usb_device_table!(
USB_TABLE,
<SampleDriver as usb::Driver>::IdInfo,
[(usb::DeviceId::from_id(0x1234, 0x5678), ()),]
);
impl usb::Driver for SampleDriver {
type IdInfo = ();
type Data<'bound> = Self;
const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE;
fn probe<'bound>(
intf: &'bound usb::Interface<Core<'_>>,
_id: &usb::DeviceId,
_info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self, Error> + 'bound {
let dev: &device::Device<Core<'_>> = intf.as_ref();
dev_info!(dev, "Rust USB driver sample probed\n");
Ok(Self { _intf: intf.into() })
}
fn disconnect<'bound>(intf: &'bound usb::Interface<Core<'_>>, _data: Pin<&Self>) {
let dev: &device::Device<Core<'_>> = intf.as_ref();
dev_info!(dev, "Rust USB driver sample disconnected\n");
}
}
kernel::module_usb_driver! {
type: SampleDriver,
name: "rust_driver_usb",
authors: ["Daniel Almeida"],
description: "Rust USB driver sample",
license: "GPL v2",
}
关键要点:
- 使用
usb_device_table!宏声明设备 ID 表 - 实现
usb::Drivertrait 的probe和disconnect方法 - 通过
intf.into()获取接口的引用计数 (ARef) - 使用
module_usb_driver!宏声明模块
九、关键设计模式详解
9.1 类型状态模式 (Type-level State Machine)
9.1.1 核心思想
类型状态模式使用 Rust 的泛型参数来编码设备的上下文状态,在编译期保证 API 的正确使用。
rust
// rust/kernel/device.rs:167
pub struct Device<Ctx: DeviceContext = Normal>(
Opaque<bindings::device>,
PhantomData<Ctx>
);
9.1.2 上下文层次结构
┌─────────────────┐
│ CoreInternal │ ──► Core (总线内部回调)
└────────┬────────┘
│
▼
┌─────────────────┐
│ Core │ ──► Bound (驱动 probe 回调)
└────────┬────────┘
│
▼
┌─────────────────┐
│ Bound │ ──► Normal (已绑定驱动的设备)
└────────┬────────┘
│
▼
┌─────────────────┐
│ Normal │ (默认:普通设备)
└─────────────────┘
关键实现 (rust/kernel/device.rs:628-701):
rust
// 实现 Deref 层次结构,自动转换上下文类型
macro_rules! impl_device_context_deref {
(unsafe { $device:ident }) => {
// CoreInternal → Core
::kernel::__impl_device_context_deref!(unsafe {
$device,
<'a> $crate::device::CoreInternal<'a> => $crate::device::Core<'a>
});
// Core → Bound
::kernel::__impl_device_context_deref!(unsafe {
$device,
<'a> $crate::device::Core<'a> => $crate::device::Bound
});
// Bound → Normal
::kernel::__impl_device_context_deref!(unsafe {
$device,
$crate::device::Bound => $crate::device::Normal
});
};
}
9.1.3 上下文类型定义
rust
// rust/kernel/device.rs:498-554
/// Normal: 默认上下文,无额外约束
pub struct Normal;
/// Core<'a>: 总线回调中的设备,生命周期绑定到回调作用域
pub struct Core<'a>(PhantomData<fn(&'a ()) -> &'a ()>);
/// CoreInternal<'a>: 内部总线抽象使用
pub struct CoreInternal<'a>(PhantomData<fn(&'a ()) -> &'a ()>);
/// Bound: 设备已绑定到驱动,保证驱动私有数据存在
pub struct Bound;
/// BoundInternal: 内部使用的绑定上下文
pub struct BoundInternal;
9.1.4 实际应用示例
rust
// PCI 驱动 probe 回调:接收 Device<Core<'_>>,只能在此作用域使用
fn probe<'bound>(
dev: &'bound pci::Device<device::Core<'_>>, // 只能在此作用域使用
id_info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
// 可以调用 Core 上下文的方法
dev.enable_device_mem()?;
dev.set_master();
// 通过 Deref 自动转换为 Bound/Normal
let normal_dev: &device::Device<device::Normal> = dev.as_ref();
}
类型状态的好处:
- 编译期保证 :某些 API 只能在特定上下文中调用(如
drvdata_borrow需要InternalBoundContext) - 生命周期安全 :
Core<'a>确保设备引用不会逃逸回调作用域 - 零运行时开销:泛型在编译期擦除,无额外成本
9.2 RAII 模式 (Resource Acquisition Is Initialization)
9.2.1 核心思想
RAII 通过 Drop trait 确保资源在离开作用域时自动释放,避免资源泄漏。
9.2.2 锁守卫实现(rust/kernel/sync/lock.rs:299-305)
rust
/// 锁守卫:离开作用域时自动解锁
pub struct Guard<'a, T: ?Sized, B: Backend> {
pub(crate) lock: &'a Lock<T, B>,
pub(crate) state: B::GuardState,
_not_send: NotThreadSafe, // !Send
}
impl<'a, T: ?Sized, B: Backend> Drop for Guard<'_, T, B> {
#[inline]
fn drop(&mut self) {
// SAFETY: 调用者拥有锁,可以安全解锁
unsafe { B::unlock(self.lock.state.get(), &self.state) };
}
}
使用方式:
rust
let mutex: Mutex<i32> = new_mutex!(42);
{
let guard = mutex.lock(); // 获取锁
*guard += 1; // 访问数据(通过 Deref)
// guard 离开作用域时自动解锁
}
9.2.3 作用域守卫(rust/kernel/types.rs:229-276)
rust
/// 运行清理函数当被 drop 时
pub struct ScopeGuard<T, F: FnOnce(T)>(Option<(T, F)>);
impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> {
fn drop(&mut self) {
// 执行清理函数
if let Some((data, cleanup)) = self.0.take() {
cleanup(data)
}
}
}
// 使用示例:自动释放资源
fn example() {
let _log = ScopeGuard::new(|| pr_info!("函数退出\n"));
// 无论正常返回还是提前返回,清理函数都会执行
if condition { return; }
// ...
}
9.2.4 驱动注册(rust/kernel/driver.rs:250-257)
rust
/// 驱动注册:drop 时自动注销
#[pin_data(PinnedDrop)]
pub struct Registration<T: RegistrationOps> {
#[pin]
reg: Opaque<T::DriverType>,
}
#[pinned_drop]
impl<T: RegistrationOps> PinnedDrop for Registration<T> {
fn drop(self: Pin<&mut Self>) {
// SAFETY: self 存在意味着之前已成功注册
unsafe { T::unregister(&self.reg) };
}
}
9.2.5 页释放(rust/kernel/page.rs:533-537)
rust
impl Drop for Page {
fn drop(&mut self) {
// 自动释放页
unsafe { bindings::__free_pages(self.page.as_ptr(), 0) };
}
}
RAII 的好处:
- 异常安全 :即使 panic,
Drop也会执行 - 无泄漏:所有路径都保证释放
- 可组合:守卫可以返回、嵌套、传递
9.3 Vtable 模式 (Virtual Table)
9.3.1 核心思想
使用 #[vtable] 宏将 Rust trait 映射到 C 的函数指针表(vtable),实现面向对象风格的回调。
9.3.2 宏实现(rust/macros/vtable.rs:24-72)
rust
/// 处理 trait 定义:添加 HAS_* 常量和 OwnerModule 类型
fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> {
let mut gen_items = Vec::new();
// 添加 USE_VTABLE_ATTR 标记
gen_items.push(parse_quote! {
const USE_VTABLE_ATTR: ();
});
// 添加 OwnerModule 关联类型(如果不存在)
if !item.items.iter().any(|i| matches!(i, TraitItem::Type(t) if t.ident == "OwnerModule")) {
gen_items.push(parse_quote! {
type OwnerModule: ::kernel::ModuleMetadata;
});
}
// 为每个方法生成 HAS_* 常量
for item in &item.items {
if let TraitItem::Fn(fn_item) = item {
let name = &fn_item.sig.ident;
let gen_const_name = Ident::new(
&format!("HAS_{}", name.to_string().to_uppercase()),
name.span(),
);
gen_items.push(parse_quote! {
#[doc = "Indicates if the method is overridden"]
const #gen_const_name: bool = false; // 默认未重写
});
}
}
item.items.extend(gen_items);
Ok(item)
}
9.3.3 使用示例
定义 vtable trait:
rust
#[vtable]
pub trait Operations: Send + Sync + Sized {
fn foo(&self) -> Result<()> {
build_error!(VTABLE_DEFAULT_ERROR) // 默认实现永远不会被调用
}
fn bar(&self) -> Result<()> {
build_error!(VTABLE_DEFAULT_ERROR)
}
}
实现 vtable trait:
rust
#[vtable]
impl Operations for Foo {
fn foo(&self) -> Result<()> {
// 实现 foo
}
// bar 使用默认实现(HAS_BAR = false)
}
// 宏自动生成:
// const HAS_FOO: bool = true; // 已重写
// const HAS_BAR: bool = false; // 未重写
// type OwnerModule = LocalModule; // 自动插入
9.3.4 实际应用:PHY 驱动(rust/kernel/net/phy/mod.rs)
rust
#[vtable]
pub trait Driver {
const FLAGS: u32 = 0;
const NAME: &'static CStr;
fn soft_reset(_dev: &mut Device) -> Result {
build_error!(VTABLE_DEFAULT_ERROR)
}
fn probe(_dev: &mut Device) -> Result {
build_error!(VTABLE_DEFAULT_ERROR)
}
fn config_aneg(_dev: &mut Device) -> Result {
build_error!(VTABLE_DEFAULT_ERROR)
}
}
C 侧调用流程:
C 函数指针 ──► Rust 桩函数 ──► 检查 HAS_* 常量 ──► 调用实现的方法
│
▼
如果 false,跳过调用
Vtable 的好处:
- 可选方法 :使用
NULL指针表示未重写的方法 - 类型安全:Rust 编译器检查签名
- 自动生成:宏自动生成 HAS_* 常量和 OwnerModule
9.4 Opaque 模式 (Opaque Types)
9.4.1 核心思想
Opaque<T> 封装不透明的 C 类型,允许 Rust 安全地持有可能未初始化的 C 结构体。
9.4.2 实现(rust/kernel/types.rs:331-419)
rust
#[repr(transparent)]
pub struct Opaque<T> {
value: UnsafeCell<MaybeUninit<T>>, // 允许未初始化内存
_pin: PhantomPinned, // !Unpin,保证固定
}
关键特性:
- 允许未初始化 :使用
MaybeUninit<T>允许任意位模式 - 可变性灵活 :
&Opaque<T>允许可变访问(绕过 Rust 常规规则) - 不强制唯一性 :多个
&mut Opaque<T>可指向同一值 - 线程不安全 :默认
!Sync,需要外部同步
9.4.3 核心方法
rust
impl<T> Opaque<T> {
/// 创建已初始化的值
pub const fn new(value: T) -> Self {
Self {
value: UnsafeCell::new(MaybeUninit::new(value)),
_pin: PhantomPinned,
}
}
/// 创建未初始化的值
pub const fn uninit() -> Self {
Self {
value: UnsafeCell::new(MaybeUninit::uninit()),
_pin: PhantomPinned,
}
}
/// 创建零初始化的值
pub const fn zeroed() -> Self { ... }
/// FFI 初始化:安全地写入未初始化内存
pub fn ffi_init(init_func: impl FnOnce(*mut T)) -> impl PinInit<Self> {
unsafe {
pin_init::pin_init_from_closure::<_, ::core::convert::Infallible>(move |slot| {
init_func(Self::cast_into(slot));
Ok(())
})
}
}
/// 获取原始指针(unsafe 访问)
pub const fn get(&self) -> *mut T {
UnsafeCell::get(&self.value).cast::<T>()
}
}
9.4.4 实际应用
设备结构体:
rust
// rust/kernel/device.rs:167
pub struct Device<Ctx: DeviceContext = Normal>(
Opaque<bindings::device>, // 封装 C struct device
PhantomData<Ctx>,
);
// rust/kernel/pci.rs:340
pub struct Device<Ctx: device::DeviceContext = device::Normal>(
Opaque<bindings::pci_dev>, // 封装 C struct pci_dev
PhantomData<Ctx>,
);
锁状态:
rust
// rust/kernel/sync/lock.rs:106
pub struct Lock<T: ?Sized, B: Backend> {
#[pin]
state: Opaque<B::State>, // 封装锁的底层状态(如 mutex、spinlock)
#[pin]
_pin: PhantomPinned,
#[pin]
data: UnsafeCell<T>,
}
使用模式:
rust
impl Device {
fn read_field(&self) -> u32 {
// SAFETY: 保证 self 有效且字段已初始化
unsafe { (*self.0.get()).some_field }
}
}
Opaque 的好处:
- 零成本抽象:无额外运行时开销
- 安全封装:访问需要 unsafe,明确责任边界
- 固定初始化 :与
pin_init!宏配合安全初始化 - 灵活可变性:绕过 Rust 常规规则以适应 C 代码
9.5 四种模式的关系图
┌─────────────────────────────────────────────────────────────────┐
│ 类型状态模式 │
│ Device<Ctx> 泛型约束 │
│ ▼ │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Opaque<T> │◄──── │ RAII Guard │ │
│ │ 封装 C 类型 │ │ 自动释放 │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ Vtable 模式 │ │
│ │ #[vtable] trait → C 回调 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
协同工作示例:
1. 设备使用 Opaque 封装 C struct device
2. 设备使用泛型参数表示类型状态(Device<Ctx>)
3. 驱动注册使用 RAII 自动注销
4. 驱动 trait 使用 vtable 映射到 C 回调
十、构建系统
Makefile 配置
makefile
obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o
obj-$(CONFIG_RUST) += kernel.o bindings.o
obj-$(CONFIG_RUST) += macros.o pin_init.o zerocopy.o
Kconfig 配置
kconfig
config SAMPLE_RUST_MINIMAL
tristate "Minimal"
depends on RUST
十一、文件路径索引
| 文件 | 说明 |
|---|---|
rust/kernel/lib.rs |
kernel crate 入口(312行) |
rust/kernel/alloc.rs |
内存分配(273行) |
rust/kernel/module.rs |
模块系统(80行) |
rust/kernel/error.rs |
错误处理(663行) |
rust/kernel/types.rs |
类型系统(453行) |
rust/kernel/device.rs |
设备模型(952行) |
rust/kernel/driver.rs |
驱动框架(326行) |
rust/kernel/sync.rs |
同步原语(171行) |
rust/kernel/sync/lock.rs |
通用锁(324行) |
rust/macros/lib.rs |
过程宏(539行) |
rust/kernel/usb.rs |
USB 子系统(485行) |
rust/kernel/i2c.rs |
I2C 总线(596行) |
rust/kernel/platform.rs |
Platform 总线 |
rust/kernel/of.rs |
设备树抽象 |
rust/kernel/acpi.rs |
ACPI 抽象 |
rust/kernel/device_id.rs |
设备 ID 匹配 |
rust/kernel/net/mod.rs |
网络模块入口 |
rust/kernel/net/netlink.rs |
Netlink 封装 |
rust/kernel/net/phy/mod.rs |
PHY 设备抽象 |
rust/kernel/net/phy/reg.rs |
PHY 寄存器接口 |
rust/kernel/fs/file.rs |
文件对象封装 |
rust/kernel/debugfs.rs |
DebugFS 抽象 |
rust/kernel/configfs.rs |
ConfigFS 抽象 |
rust/kernel/mm.rs |
内存管理 |
rust/kernel/page.rs |
页抽象 |
rust/kernel/task.rs |
任务抽象 |
rust/kernel/cred.rs |
进程凭证 |
rust/kernel/workqueue.rs |
工作队列 |
samples/rust/rust_minimal.rs |
最小示例(56行) |
samples/rust/rust_driver_pci.rs |
PCI 驱动示例(194行) |
samples/rust/rust_driver_usb.rs |
USB 驱动示例(54行) |
samples/rust/rust_driver_i2c.rs |
I2C 驱动示例 |
samples/rust/rust_driver_platform.rs |
Platform 驱动示例 |
samples/rust/rust_debugfs.rs |
DebugFS 示例 |
samples/rust/rust_configfs.rs |
ConfigFS 示例 |
十二、学习计划与方法
12.1 学习路径图
阶段一:基础准备(2-3周)
├── 1. Rust 语言基础
│ ├── 所有权与生命周期
│ ├── Trait 系统
│ ├── 泛型与关联类型
│ └── 宏系统(声明宏、过程宏)
│
├── 2. Linux 内核基础
│ ├── 内核模块开发
│ ├── 设备模型(device、driver、bus)
│ ├── 内存管理(kmalloc、vmalloc、页分配)
│ └── 同步原语(spinlock、mutex、RCU)
│
└── 3. 工具链准备
├── rustc、rustup、cargo
├── bindgen(C 绑定生成)
└── 内核构建系统(Kconfig、Makefile)
阶段二:核心框架(2-3周)
├── 1. Rust 内核核心库
│ ├── kernel/lib.rs - 模块入口
│ ├── kernel/alloc.rs - 内存分配
│ ├── kernel/sync.rs - 同步原语
│ ├── kernel/types.rs - 类型系统
│ └── kernel/error.rs - 错误处理
│
├── 2. 设备模型
│ ├── kernel/device.rs - 设备抽象
│ ├── kernel/driver.rs - 驱动框架
│ └── kernel/device_id.rs - 设备 ID 匹配
│
└── 3. 宏系统
├── macros/lib.rs - 过程宏
└── pin-init/ - 固定初始化
阶段三:子系统实践(4-6周)
├── 1. 字符设备
│ ├── kernel/miscdevice.rs
│ └── samples/rust/rust_misc_device.rs
│
├── 2. 总线驱动
│ ├── PCI 驱动(samples/rust/rust_driver_pci.rs)
│ ├── USB 驱动(samples/rust/rust_driver_usb.rs)
│ ├── I2C 驱动(samples/rust/rust_driver_i2c.rs)
│ └── Platform 驱动(samples/rust/rust_driver_platform.rs)
│
├── 3. 文件系统
│ ├── debugfs(samples/rust/rust_debugfs.rs)
│ └── configfs(samples/rust/rust_configfs.rs)
│
└── 4. 网络
└── net/phy/ - PHY 设备驱动
阶段四:高级主题(持续)
├── 1. 安全保证
│ ├── unsafe 代码审计
│ ├── 内存安全模式
│ └── 并发安全验证
│
├── 2. 性能优化
│ ├── 零成本抽象
│ ├── 内联优化
│ └── 基准测试
│
└── 3. 贡献社区
├── 阅读邮件列表
├── 提交补丁
└── 参与代码审查
12.2 推荐学习资源
| 资源 | 类型 | 说明 |
|---|---|---|
| Rust 官方文档 | 文档 | Rust 语言基础 |
| Linux Kernel Rust 文档 | 文档 | 内核 Rust 官方文档 |
| kernel/README.rst | 文档 | 内核 Rust 快速入门 |
| Rust for Linux 仓库 | 代码 | 上游开发仓库 |
| LWN.net Rust 文章 | 文章 | 内核 Rust 进展报道 |
| Linux Kernel Mailing List | 邮件列表 | 社区讨论 |
12.3 学习方法要点
1. 代码阅读顺序:
rust/kernel/lib.rs → 了解模块结构
↓
rust/kernel/alloc.rs → 理解内存分配
↓
rust/kernel/sync.rs → 理解同步原语
↓
rust/kernel/device.rs → 理解设备模型
↓
rust/kernel/driver.rs → 理解驱动框架
↓
samples/rust/*.rs → 学习示例代码
2. 关键设计模式:
- 类型状态模式 :使用泛型参数表示设备上下文(
Device<Ctx>) - RAII 模式 :通过
Droptrait 自动释放资源 - Vtable 模式 :使用
#[vtable]宏实现 trait 到 C 回调的映射 - Opaque 模式 :使用
Opaque<T>封装不透明 C 类型
3. 调试技巧:
rust
// 使用 pr_info!/pr_debug! 输出
pr_info!("value: {}\n", value);
// 使用 dev_info!/dev_dbg! 输出设备信息
dev_info!(dev, "message: {}\n", value);
// 使用断言
build_assert!(condition, "error message");
4. 常见陷阱:
- 不要忘记
#[pin]属性用于固定字段 - 注意
unsafe块的安全不变式 - 正确处理引用计数(
AlwaysRefCounted) - 注意 Pinned 初始化(
PinInittrait)
12.4 学习检查清单
- 理解 Rust 所有权系统
- 理解内核模块生命周期
- 掌握内存分配(
GFP_KERNELvsGFP_ATOMIC) - 掌握同步原语(
Mutex、SpinLock、CondVar) - 理解设备上下文类型状态
- 能够编写简单的字符设备驱动
- 能够编写平台驱动
- 理解设备 ID 匹配机制
- 掌握
#[vtable]宏使用 - 理解固定初始化(
pin_init!) - 能够阅读和调试 Rust 内核代码
- 了解如何向社区贡献代码
十三、总结
Linux kernel 中的 Rust 代码结构清晰,主要包含:
- 核心库 :
kernel、bindings、uapi、ffi等提供内核 API - 工具库 :
pin-init、zerocopy、macros等提供基础设施 - 示例代码 :
samples/rust/包含各种驱动示例 - 构建系统:完整的 Makefile、Kconfig 和脚本支持
Rust 在 Linux kernel 中的使用正在积极发展,提供了安全、高效的内核编程体验。
附录:实践项目建议
初级项目(1-2周)
- 修改
samples/rust/rust_minimal.rs添加新功能 - 编写一个简单的 miscdevice 驱动
- 创建 debugfs 接口展示内核信息
中级项目(2-4周)
- 编写一个完整的平台驱动
- 实现一个 I2C 设备驱动
- 为现有 C 驱动添加 Rust 封装
高级项目(1-3月)
- 实现新的总线子系统 Rust 抽象
- 为网络子系统添加 Rust 支持
- 重构内核同步原语的 Rust 接口