このページの目次

カーネルモジュールと no_std

std は OS(スレッド、ファイル、ヒープ割り当て)に依存しており、ボートメタルやカーネルモジュールにはそれらが存在しません。#![no_std] は std を除去し、OS に依存しない core crate のみを残しますが、alloc(ヒープ割り当て)と panic_handler(パニック時の処理)は自分で提供する必要があります。Rust-for-Linux は、no_std とカーネルが提供する alloc 実装を用いて、Linux カーネル内で Rust コードを実行します。

std の除去: no_std 環境

std は OS に依存しています——スレッド、ファイル IO、ネットワーク、ヒープ割り当ては、すべて OS の存在を前提としています。ボートメタル(bare metal)、組み込みシステム、カーネルモジュールにはそれらが存在しません。#![no_std] は std を除去し、OS に依存しない core crate のみを残します:

#![no_std]
#![no_main]

extern crate alloc;                  // オプション: ヒープ割り当てが必要ない場合にのみ導入

use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}                          // 出力不可、unwind 不可
}

core には以下が含まれます:Option, Result, Iterator, Clone, Copy, 基本マクロ(format_args! は含まれますが、format! を使用するには write_str の実装を自分で提供する必要があります)、アトミック操作。alloc crate は GlobalAlloc が実装されている場合に利用可能になり、Box, Vec, String, Rc, Arc, HashMap を提供します。

Rust-for-Linux (Linux カーネル)

Linux 6.1 以降では Rust 製カーネルモジュールがサポートされています。主要な抽象化:

use kernel::prelude::*;

kernel::module! {
    type: MyModule,
    name: "my_module",
    license: "GPL",
}

struct MyModule;
impl kernel::Module for MyModule {
    fn init(_module: &'static ThisModule) -> Result<Self> { Ok(MyModule) }
}

// ファイル操作の実装
struct MyFile;
#[vtable]
impl kernel::file::Operations for MyFile {
    fn read(&self, _data: ()) -> Result<Vec<u8>> {
        Ok(b"Hello from Rust kernel module!\n".to_vec())
    }
}

#[vtable] マクロは、C 互換の関数ポインタテーブルを生成するコードを trait に生成します——これにより、カーネルの C コードにおける file_operations 構造体と連携します。カーネル内の Rust はユーザー空間よりも多くの制約があります:

  • 独自のアロケータ:カーネルでは #[global_allocator] を使用できません。カーネルのアロケータ(kmalloc/kfree)を使用する必要があります——kernel::alloc を介してアクセスします
  • 独自の同期プリミティブ:kernel::sync::Mutex はカーネルのミューテックス(struct mutex)の Rust によるラッパーであり、std::sync::Mutex ではありません
  • 独自のエラー型:kernel::error::Error は Linux の errno にマッピングされます
  • Panic = BUG():カーネルでは unwind できません——panic_handlerBUG() を呼び出します(スタックの出力 + カーネルの停止)

参考

  • Rust-for-Linux: rust-for-linux.com
  • Embedded Rust Book: docs.rust-embedded.org
  • Phil Opp's blog: os.phil-opp.com

Keywords: no_std, core, alloc, panic_handler, kernel module, Rust-for-Linux, embedded, BUG