本文使用 archlinux 进行操作
配置环境
安装 base-devel包组 软件组,这个组包含了 make包 等我们需要的软件包。参考 Arch 默认内核的 PKGBUILD,同时可能需要安装以下软件包:xmlto包、kmod包、inetutils包、 mkinitcpio包、 bc包、libelf包、git包、cpio包、perl包、tar包、xz包。
安装 llvm 工具链:clang lld lldb llvm libc++
安装 rustup: rustup
安装 qemu: qemu-full
编译 linux for rust
源码与 rust 环境
# 下载源码
git clone https://github.com/Rust-for-Linux/linux -b rust-dev
cd linux
# 配置环境
rustup override set $(scripts/min-tool-version.sh rustc)
rustup component add rust-src
cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen-cli
# 验证环境
make LLVM=1 rustavailable
如果 make LLVM=1 rustavailable 提示 Rust is available! 就ok了。
内核设置
# 创建默认配置
make ARCH=x86_64 LLVM=1 O=build defconfig
# 你也可以使用 zcat /proc/config.gz > 。./build/.config 把你当前的内核配置写入.config
make ARCH=x86_64 LLVM=1 O=build nconfig
#General setup
# ---> [*] Rust support
# ^ 按空格开启 即 [*]
make menuconfig
: 老的 ncurses 界面,被nconfig
取代make nconfig
: 新的命令行 ncurses 界面make xconfig
: 用户友好的图形界面,需要安装 packagekit-qt5包。建议没有经验的用户使用此方法。make gconfig
: 和 xconfig 类似的图形界面,使用 gtk.
制作 rust hello world 模块
源码
vim samples/rust/rust_helloworld.rs
填入以下内容
// SPDX-License-Identifier: GPL-2.0
//! Rust minimal sample.
use kernel::prelude::*;
module! {
type: RustHelloWorld,
name: "rust_helloworld",
author: "whocare",
description: "hello world module in rust",
license: "GPL",
}
struct RustHelloWorld {}
impl kernel::Module for RustHelloWorld {
fn init(_module: &'static ThisModule) -> Result<Self> {
pr_info!("Hello World from Rust module");
Ok(RustHelloWorld {})
}
}
配置
vim samples/rust/Kconfig
添加以下内容
要在 if SAMPLES_RUST 和 endif # SAMPLES_RUST 之间添加
config SAMPLE_RUST_HELLOWORLD
tristate "Print Helloworld in Rust"
help
This option builds the Rust HelloWorld module sample.
To compile this as a module, choose M here:
the module will be called rust_helloworld.
If unsure, say N.
vim samples/rust/Makefile
添加以下内容
obj-$(CONFIG_SAMPLE_RUST_HELLOWORLD) += rust_helloworld.o
修改 .config 开启 rust hello world
make ARCH=x86_64 LLVM=1 O=build nconfig
Kernel hacking
—> Sample Kernel code
—> Rust samples
—> Print Helloworld in Rust (NEW)
# 检查
cat build/.config | grep SAMPLE_RUST_HELLOWORLD
cat build/.config | grep SAMPLES_RUST
# CONFIG_SAMPLE_RUST_HELLOWORLD=m
# CONFIG_SAMPLES_RUST=y
构建内核
# 构建内核
cd build
make ARCH=x86_64 LLVM=1 -j12
# Kernel: arch/x86/boot/bzImage is ready (#3)
构建 initramfs.img
sudo make ARCH=x86_64 LLVM=1 modules_install
# 也可以 HOOKS=(base systemd autodetect modconf block filesystems keyboard fsck)
echo "HOOKS=(base udev resume autodetect modconf block filesystems keyboard fsck)" > ./mkinitcpio.conf
sudo mkinitcpio -k $(pwd)/arch/x86_64/boot/bzImage -c ./mkinitcpio.conf -g ./initramfs.img
sudo chmod ugo+r ./initramfs.img
内核和 initramfs 已经完成,但我们需要一个硬盘来运行一切
创建 raw 并安装 archlinux
dd if=/dev/zero of=rawhd bs=1M count=4096
# 格式化硬盘
mkfs.ext4 ./rawhd
# 挂载硬盘
sudo mount rawhd /mnt
sudo pacman -S arch-install-scripts
# 安装 archlinux
sudo pacstrap /mnt base base-devel vim
# 复制我们编写的 rust_helloworld
sudo cp samples/rust/rust_helloworld.ko /mnt/
genfstab -U /mnt
$ genfstab -U /mnt
# /dev/loop0
UUID=920290b2-8f5e-4222-96b5-ae911205eef7 / ext4 rw,relatime 0 1/swapfile none swap defaults 0 0
# 把环境切换到新系统的/mnt 下
sudo arch-chroot /mnt
echo "UUID=920290b2-8f5e-4222-96b5-ae911205eef7 / ext4 rw,relatime 0 1" > /etc/fstab
# 设置 root 密码
passwd root
exit
sudo umount rawhd
启动 arch linux for rust 操作系统
qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -initrd initramfs.img -m 1G -drive file=rawhd -nographic -append "root=/dev/sda console=ttyS0"
如果出现 ERROR: Root device mounted successfully, but /sbin/init does not exist.
把 -append “root=/dev/sda console=ttyS0” 改为 -append “root=/dev/sda init=/lib/systemd/systemd console=ttyS0”
运行 rust_helloworld 模块
dmesg -C
# 运行模块
insmod /rust_helloworld.ko
dmesg
# [ 65.603974] rust_helloworld: Hello World from Rust module
# 卸载模块
rmmod rust_helloworld
最后
现在你应该知道Linux 本身并不是一个操作系统。它只是一个内核。操作系统的一部分。整个操作系统由内核、附带的 initramfs、根文件系统和社区组成。