Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RustでOS開発はじめの一歩
Search
nasa
December 19, 2023
Technology
7.6k
8
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RustでOS開発はじめの一歩
https://uniquevision.connpass.com/event/303687/
nasa
December 19, 2023
More Decks by nasa
See All by nasa
難解な自己紹介プログラムを書く
nasa_desu
1
400
鉄は熱いうちに打て - Kaigi Effect LT大会
nasa_desu
2
610
リンカを変えてgo buildを 速く出来るか
nasa_desu
2
4k
ログから学ぶgo build
nasa_desu
4
1.6k
goのメモリアロケーターの話
nasa_desu
1
830
GoとRust - 並行処理編
nasa_desu
5
4.2k
Other Decks in Technology
See All in Technology
LanceDB入門
mocobeta
7
460
PLATEAU で バーチャル花火大会
tatsuya1970
0
150
生成 AI の基礎 〜 サンプル実装で学ぶ基本原理
enakai00
7
4.4k
ハーレムエンジニアリング
kazuma777777
0
150
サイバー捜査員研修(前半)
nomizone
1
2k
猫付きpingコマンドを自作
uyuki234
0
230
【CEDEC2026】グラフィックスエンジニアのためのニューラルシェーディング入門
cygames
PRO
0
140
関東Kaggler会発表資料
takoi
1
220
MIRU 2026 チュートリアル
keisuke198619
0
910
AIコーディングの次。コードレビューと理解負荷を解消して組織の開発生産性を高める
moongift
PRO
2
2.5k
メルカリのグローバルアプリで挑んだ AlloyDB 運用と課題解決の実践記
hatappi
0
250
Sets in Go
ramalho
1
370
Featured
See All Featured
Fireside Chat
paigeccino
42
4k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
410
The untapped power of vector embeddings
frankvandijk
2
1.8k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
66
57k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
460
GraphQLとの向き合い方2022年版
quramy
50
15k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
490
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
380
Navigating Team Friction
lara
192
16k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
A Soul's Torment
seathinner
6
3.4k
Transcript
RustでOS開発はじめの一歩 UV Study: Rust LT会 Dec. 19 2023 - nasa
発表のモチベ • 最近RustでOSを書いている • これまでCLIツールやライブラリをRustで実装してきた • OSだと普段書いているコードが普通には動作しない • どんな違いがあるのか話したい
動作環境 • platform: QEMU riscv64 • build target: riscv64gc-unknown-none-elf #
.cargo/config.toml [build] target = "riscv64gc-unknown-none-elf" [target.riscv64gc-unknown-none-elf] runner = """ qemu-system-riscv64 \ -machine virt \ -bios default \ --no-reboot \ -nographic \ -serial mon:stdio \ -kernel """
ベアメタル環境 • OSによりプログラムがホスティングされない • 自分の書いたプログラムを動かし始めるまでの環境がない • time, io, fsなどOSの上に構成されている標準機能が使えない •
メモリアロケーターも無いのでVec, String等が使えない
ベアメタル環境
main関数を動かす
main関数を動かす QEMU riscvのdefault biosは0x80200000を実行する
main関数を動かす プログラムを0x8020_0000に配置し呼出す
main関数を動かす リンカースクリプトで任意の アドレスにプログラムを配置する .entryシンボルを8020_0000に配置 OUTPUT_ARCH( "riscv" ) ENTRY( _entry )
SECTIONS { . = 0x80200000; .text : { *(.entry) *(.text .text.*) } .rodata : { *(.rdata .rodata .rodata.*) } .data : { *(.data .data.*) } .bss : { *(.bss bss.*) } }
main関数を動かす main.rsで.entryを定義 これで関数_entryが呼ばれる // src/main.rs #![no_std] #![no_main] #[no_mangle] #[link_section =
".entry"] pub fn _entry() { main(); } #[inline] fn main() { loop {} } #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { loop {} }
関数呼び出しをサポートしたい
関数呼び出し みんな大好き関数呼び出し。 というかプログラムを書く上でほぼ必須 • 関数呼び出しが出来ない。。 • inlineオプションを付けると呼び出せる fn a() {
b() } fn b() { c() } pub fn _entry() { main(); } #[inline] fn main() { loop {} }
関数呼び出し • 関数呼び出しが出来ない。。 • inlineオプションを付けると呼び出せる • (正確には関数を呼ぶとローカル変数の値がおかしくなる) なぜこれらが起きるのか
関数呼び出し • 関数呼び出し時にスタック領域が確保される • しかしSPの初期値は0 • SPを初期化する必要があった
関数呼び出し // src/main.rs static INIT_SP: [u8; 4096 * 1024] =
[0; 4096 * 1024]; static STACK_SIZE: usize = 4096 * 1024; // 4MB pub unsafe fn _entry() { // NOTE: スタックポインタの初期値を設定する // NOTE: スタックは下位に伸びていくのでINIT_SP + STACK_SIZEを設定 しSTACK_SIZE分の領域を確保 asm!("la sp, INIT_SP", "ld a0, STACK_SIZE", "add sp, sp, a0",); main(); } SPを初期化 誰からも変更されないように配列を定義し末尾アドレスを利用
動的メモリ確保したい
動的メモリ確保 StringやVec,Boxが普通に使いたくなる これらはallocクレートに定義されている (stdが存在する場合はstdの一部)
動的メモリ確保 allocを使うにはメモリアロケーターを実装する必要がある (heaplessクレートを利用するとアロケーターの実装無しでString, Vec等が使 える)
メモリアロケーターの実装 global_allocatorディレクティブで登録出来る GlobalAllocトレイトを実装している必要がある #[global_allocator] static mut ALLOCATOR: BumpAllocator = BumpAllocator::new();
pub struct BumpAllocator { arena: RefCell<[u8; ARENA_SIZE]>, next: Cell<usize>, } unsafe impl GlobalAlloc for BumpAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 {} unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} }
メモリアロケーターの実装 bump allocatorを採用 heapの始点から終点まで順次割り当 てていくだけ フラグメンテーションを一切考慮してい ない 実装が超簡単なので採用
まとめ
まとめ • 普段Rustを書く時に色んなものに乗っかっている事が分かった • OSの機能以外にブート、メモリアロケーター、スタックポインタを気にする 必要があった 「俺の戦いはこれからだ!!」
自己紹介 HN: nasa (Asan Kondo) nasaが欲しい • github: k-nasa •
x(twitter): nasa_desu お仕事: MLOpsっぽいこと、DSの生産性改善
(余談) 遭遇したバグたち • 一度出力した文字が出力できない 「Hel?o W?r?d.」が出力される ◦ 原因: SP初期化していないから •
カーネル起動時に有効化していないタイマ割り込みが発生して死ぬ ◦ 原因1: エラーコードがズレてた。。本当は`address misaligned` ◦ 原因2: アライメントを考慮していなかった • プロセス切り替え時にSPが意図通り切り替わらない ◦ 原因: 調査中。涙
ご清聴ありがとうございました!