https://github.com/rust-for-linux
https://rust-for-linux.github.io/docs/kernel/
https://rust-for-linux.github.io/docs/alloc/index.html
https://rust-for-linux.github.io/docs/core/index.html
// SPDX-License-Identifier: GPL-2.0
//! this is document
use kernel::prelude::*;
module! {
type: RustSample,
name: "rust_sample",
authors: ["Rust for Linux Contributors"],
description: "Minimal in-tree Rust sample driver",
license: "GPL",
}
struct RustSample;
impl kernel::Module for RustSample {
fn init(_module: &'static ThisModule) -> Result<Self> {
pr_info!("rust_sample: init\n");
Ok(RustSample)
}
}
impl Drop for RustSample {
fn drop(&mut self) {
pr_info!("rust_sample: exit\n");
}
}
prelude 모듈을 사용한다prelude 모듈은 커널 모듈 개발에 필요한 핵심 traits, type, macro들을 제공한다module! 매크로에서는 커널 모듈에 대한 정보를 한곳에서 정의한다make M=drivers/rust_sample rust-analyzer
# Build a Rust kernel module
obj-$(CONFIG_RUST_SAMPLE) += sample.o
config RUST_SAMPLE
tristate "Rust Sample Kernel Module"
depends on RUST
default n
help
Example Rust kernel module
obj-$(CONFIG_RUST_HELLO) += rust_sample/
source "drivers/rust_sample/Kconfig"
이후 make menuconfig를 하면, Device Drivers / Rust Hello Kernel Module를 M으로 체크한다
마지막으로 아래 명령어로 빌드할 수 있다
make M=drivers/rust_sample modules
#[pin_data(PinnedDrop)]
struct RustSample {
#[pin]
dev: MiscDeviceRegistration<SampleDevice>,
}
struct SampleDevice;
#[vtable]
impl MiscDevice for SampleDevice {
type Ptr = ();
fn open(_file: &File, _misc: &MiscDeviceRegistration<Self>) -> Result<Self::Ptr> {
pr_info!("rust_sample: device opened\n");
Ok(())
}
}
impl kernel::InPlaceModule for RustSample {
fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
pr_info!("rust_sample: init\n");
try_pin_init!(Self {
dev <- MiscDeviceRegistration::register(MiscDeviceOptions {
name: c_str!("rust-sample"),
}),
})
}
}
#[pinned_drop]
impl PinnedDrop for RustSample {
fn drop(self: Pin<&mut Self>) {
pr_info!("rust_sample: exit\n");
}
}
// SPDX-License-Identifier: GPL-2.0
//! 최소 구조만 갖춘 Rust 모듈 예제.
use core::ffi::c_void;
use kernel::{
bindings,
c_str,
fs::{File, Kiocb},
iov::IovIterDest,
miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
prelude::*,
};
module! {
type: RustSample,
name: "rust_sample",
authors: ["Rust for Linux Contributors"],
description: "Minimal Rust sample driver",
license: "GPL",
}
#[pin_data(PinnedDrop)]
struct RustSample {
#[pin]
dev: MiscDeviceRegistration<SampleDevice>,
}
struct SampleDevice;
#[vtable]
impl MiscDevice for SampleDevice {
type Ptr = ();
fn open(_file: &File, _misc: &MiscDeviceRegistration<Self>) -> Result<Self::Ptr> {
pr_info!("rust_sample: device opened\n");
Ok(())
}
fn read_iter(_kiocb: Kiocb<'_, Self::Ptr>, dest: &mut IovIterDest<'_>) -> Result<usize> {
const CHUNK: usize = 256;
let mut buf = [0u8; CHUNK];
let mut total = 0usize;
while !dest.is_empty() {
let len = buf.len().min(dest.len());
fill_random(&mut buf[..len]);
let written = dest.copy_to_iter(&buf[..len]);
total += written;
if written != len {
break;
}
}
Ok(total)
}
}
impl kernel::InPlaceModule for RustSample {
fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
pr_info!("rust_sample: init\n");
try_pin_init!(Self {
dev <- MiscDeviceRegistration::register(MiscDeviceOptions {
name: c_str!("rust-sample"),
}),
})
}
}
#[pinned_drop]
impl PinnedDrop for RustSample {
fn drop(self: Pin<&mut Self>) {
pr_info!("rust_sample: exit\n");
}
}
fn fill_random(slice: &mut [u8]) {
if slice.is_empty() {
return;
}
unsafe {
bindings::get_random_bytes(
slice.as_mut_ptr().cast::<c_void>(),
slice.len(),
);
}
}