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
第13回Kernel/VM勉強会発表資料
Search
orumin
July 22, 2017
Programming
1
1.5k
第13回Kernel/VM勉強会発表資料
2017/07/22 に行なわれた Kernel/VM 勉強会の発表資料です。
orumin
July 22, 2017
Tweet
Share
More Decks by orumin
See All by orumin
ヴィンテージマシンと付き合う - kernel/vm online 5
orumin
0
1k
むかしの RISC、むかしの Unix
orumin
7
3.3k
Fundamental of architecture to implementing OS on AArch64
orumin
3
4.7k
Kernel/VM Kansai #9
orumin
0
880
Kernel/VM #14 発表資料
orumin
1
530
Unikernels report
orumin
2
430
第12回カーネル/VM探検隊
orumin
0
330
第11回 Kernel/VM探検隊 発表資料
orumin
1
520
KernelVM night! LT
orumin
0
410
Other Decks in Programming
See All in Programming
イベント駆動で成長して委員会
happymana
1
340
ヤプリ新卒SREの オンボーディング
masaki12
0
130
最新TCAキャッチアップ
0si43
0
190
Jakarta EE meets AI
ivargrimstad
0
240
[Do iOS '24] Ship your app on a Friday...and enjoy your weekend!
polpielladev
0
110
NSOutlineView何もわからん:( 前編 / I Don't Understand About NSOutlineView :( Pt. 1
usagimaru
0
340
3rd party scriptでもReactを使いたい! Preact + Reactのハイブリッド開発
righttouch
PRO
1
610
CSC509 Lecture 11
javiergs
PRO
0
180
Jakarta EE meets AI
ivargrimstad
0
620
ふかぼれ!CSSセレクターモジュール / Fukabore! CSS Selectors Module
petamoriken
0
150
Amazon Qを使ってIaCを触ろう!
maruto
0
410
Functional Event Sourcing using Sekiban
tomohisa
0
100
Featured
See All Featured
5 minutes of I Can Smell Your CMS
philhawksworth
202
19k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
44
2.2k
RailsConf 2023
tenderlove
29
900
Writing Fast Ruby
sferik
627
61k
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
Building Applications with DynamoDB
mza
90
6.1k
Statistics for Hackers
jakevdp
796
220k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
31
2.7k
Testing 201, or: Great Expectations
jmmastey
38
7.1k
BBQ
matthewcrist
85
9.3k
How to Think Like a Performance Engineer
csswizardry
20
1.1k
Transcript
C 以外でのベアメタルプログラミング XXX Jul 22th, 2017 1 / 27
自己(事故)紹介 orumin Twitter ID: @kotatsu_mi 最近自宅のサーバの電源と PT3 が雷に撃たれました。 雷サージ対策は忘れずにやろうね! アンテナ線にも電話線にもサージプロテクタは存在する
2 / 27
緒言 ベアメタルプログラミング いわゆる freestanding 環境 libc 他が存在しない みなさんよくやってますよね? よくつかわれるのは C
や C++ どうして C をつかうのか 3 / 27
ベアメタルプログラミングと C メリット 生ポインタで特定のアドレスへの I/O 操作といったことが簡単にでき る,また,この分野で枯れており,ノウハウも豊富 デメリット 型システムが貧弱,最近のクールな言語機能が使えない 4
/ 27
C 以外でベアメタルプログラミング 複数の代替手段 D 言語,C♯,Rust … (いますぐ採用するとかなくても)今後のために C 以外でやるノウハウも得てお かないとそのうち死ぬので
Rust 既にかなりの規模のそれなりにちゃんと動く OS が作られている(Redox)実績 C♯ も 2011 年ぐらいから Cosmos という OS があったりする C♯ でのベアメタルプログラミングも調べて話そうとすると話者の力量不足でどっち つかずの内容になるので割愛しました そのうちやるかも? 5 / 27
Rust OCaml と C++ の血を感じる言語 ML 系の強力な型システム 所有権など,独特だが C++ を既に知ってる人間がわりと違和感なく使える強力な
機能 nightly コンパイラで freestanding をサポート stable 入りはまだですかー! 様々な機能や設計が C++ のカウンターっぽい c.f.) 過去の KernelVM での @omasanori さんの発表 https://speakerdeck.com/omasanori/rustru-men-yi-qian-fa-biao-ban 6 / 27
Rust(nightly)のインストールとテスト $ curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain=nightly
-y $ . ~/.cargo/env $ cargo new --bin hello-rust 7 / 27
Rust のテスト 右のようなディレクトリツリーが出来あがる 作成されるファイルは下例 実行は cargo run cargo は gem
みたいなもの。ビルドツールか つパッケージマネージャ。 Rust のパッケージは https://crates.io に ある hello-rust Cargo.toml src/ main.rs [package] name = ”hello-rust” version = ”0.1.0” authors = [”orumin <
[email protected]
>”] [dependencies] fn main() { println!(”Hello, world!”); } 8 / 27
Rust でベアメタルをするにはどうすれば良いか UEFI apps を例に step-by-step で紹介します! Linux の人は手元で試してみてください TL;DR
https://github.com/orumin/rust-uefi-sample.git を clone して make run rust-uefi-sample/ Makefile Cargo.toml x86_64-unknown-efi.json src/ lib.rs 9 / 27
Cargo.toml [package] name = ”uefi-sample” version = ”0.1.0” authors =
[”orumin <
[email protected]
>”] [dependencies] uefi = { git = ”https://github.com/orumin/rust-uefi” } rlibc = ”1.0” [lib] crate-type = [”staticlib”] [profile.dev] panic = ”abort” [profile.release] panic = ”abort” 10 / 27
Cargo.toml パッケージ名や依存パッケージを記述 [lib] セクションをつくり,src/lib.rs を記述するとライブラリとして作られる 今回はオブジェクトファイルだけ作成して手動でリンクしたかった 依存パッケージは名前だけ書いておくと crates.io からもってくる path
= に続けてパスを記述すると他のディレクトリのプロジェクトを依存に指定 git = に続けて Git repo を記述すると自動で clone とビルドしてくれます 11 / 27
target json Cargo は json で custom ターゲットを作れる { ”arch”:
”x86_64”, ”os”: ”efi”, ”llvm-target”: ”x86_64-efi-none-gnu”, ”target-endian”: ”little”, ”target-pointer-width”: ”64”, ”function-sections”: false, ”no-compiler-rt”: true, ”data-layout”: ”e-m:e-i64:64-f80:128-n8:16:32:64-S128”, ”linker”: ”x86_64-efi-pe”, ”linker-flavor”: ”ld”, ”pre-link-args”: [ ”subsystem”, ”10” ] } 12 / 27
target json 今回は UEFI 向けに PE バイナリを作りたいので target の json
を記述 arm-none-eabi などでも記述 ただの x86_64 の ELF なら要らないかも? 13 / 27
ソースコード #![no_std] #![feature(asm)] #![feature(intrinsics)] #![feature(lang_items)] extern crate uefi; extern crate
rlibc; use core::mem; #[allow(unreachable_code)] #[no_mangle] pub extern ”win64” fn efi_main(hdl: uefi::Handle, sys: uefi::SystemTable) -> uefi::Status { uefi::initialize_lib(&hdl, &sys); let bs = uefi::get_system_table().boot_services(); let rs = uefi::get_system_table().runtime_services(); 14 / 27
ソースコード uefi::get_system_table().console().write(”Hello, World!\n\rvendor: ”); uefi::get_system_table().console().write_raw(uefi::get_system_table().vendor()); uefi::get_system_table().console().write(”\n\r”); loop { } uefi::Status::Success
} #[no_mangle] pub fn abort() -> ! { loop {} } #[no_mangle] pub fn breakpoint() -> ! { loop {} } #[no_mangle] pub extern ”C” fn _Unwind_Resume() -> ! { loop {} } #[lang = ”eh_personality”] #[no_mangle] pub extern fn rust_eh_personality() {} 15 / 27
ソースコード #[lang = ”panic_fmt”] #[no_mangle] pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
_file: &’static str, _line: u32) -> ! { loop {} } 16 / 27
ソースコード解説 #![no_std] 標準ライブラリをリンクしなくなる 標準ライブラリのうち,アーキテクチャ非依存な便利機能は core ライブラリを use すれば使えるものもある 17 /
27
no_std でフォーマット出力 e.g.) use core::fmt::Write; impl Write for Writer {
fn write_str(&mut self, s: &str) -> core::fmt::Result { 引数でうけた文字列 s について出力を自分で実装; Ok(()) // 失敗なら Err(foo) でエラーの値返す } } これだけで,write!() マクロの実装が得られる let mut w = Writer {}; write!(w, ”foo {}”, bar).unwrap(); 18 / 27
#![feature(lang_items)] eh_personality とか panic_fmt とか eh_personality GCC の personality 関数の代わりのシンボル
LLVM で言語の例外ハンドリングに使う unwind panic_fmt Rust で panic!() を使うときのシンボル デバッグ文字列出力とか作っておくと良い 19 / 27
extern extern “C” などとすると C 互換の ABI になる #[no_mangle] 付けると名前マングルをしない
既存のライブラリを置き換える何かを作るのにもべんりかも UEFI は x86_64 だと Microsoft’s 64-bit call convention を使う extern “win64” で対応 20 / 27
ではビルドをしてみましょう $ cargo install xargo $ xargo build --target x86_64-unknown-efi
Xargo を導入 cargo build の際に core ライブラリなどをターゲットのアーキでビルドしてく れる 素の cargo だとヘンなアーキテクチャ使うのに core をそこに合わせてビルドしな いといけない 21 / 27
binutils とリンク 今回は UEFI ターゲットの PE バイナリを作りたいので普通の binutils だとダメ $
curl -O https://orum.in/distfiles/x86_64-efi-pe-binutils.tar.xz $ mkdir -p $PWD/toolchain $ tar xf x86_64-efi-pe-binutils.tar.xz -C $PWD/toolchain $ export PATH=$PATH:$PWD/toolchain/usr/bin/ $ pushd $ cd target/x86_64-unknown-efi/debug $ ar x *.a $ popd $ x86_64-efi-pe-ld --gc-sections --oformat pei-x86-64 \ --subsystem 10 -pie -e efi_main \ -o bootx64.efi \ target/x86_64-unknown-efi/debug/*.o 22 / 27
実行 $ dd if=/dev/zero of=fat.img bs=1k count=1440 $ mformat -i
fat.img -f 1440 :: $ mmd -i fat.img ::/EFI $ mmd -i fat.img ::/EFI/BOOT $ mcopy -i fat.img bootx64.efi ::/EFI/BOOT $ curl -O https://orum.in/distfiles/ovmf.fd $ qemu-system-x86_64 -enable-kvm -net none -m 1024 \ -bios ovmf.fd -usb -usbdevice disk::fat.img 23 / 27
これだと見えづらいので…… https: //github.com/orumin/rust-uefi-sample/blob/master/src/lib.rs Graphic Output Protocol の取得,設定 BLT 24 /
27
conclusion Rust 便利 C 以外でもベアメタルしたい! 25 / 27
こぼれ話1 質問:@nullpo_head さん「自作 OS 勉強会だと Box が使えなくて辛いとかあっ たけどどうやってるの? 」 回答:
「まだそこらへんがっつりやるステージに入れてないが,そもそも Box と かは自前実装する方法があるので問題がないと思う。 」 https://rust-lang-ja.github.io/the-rust-programming-language-ja/ 1.6/book/custom-allocators.html 実は上記の通り公式ドキュメントがある ベアメタル以外でも使えるのでゲームエンジンとかやる人にも良いのではないか 26 / 27
こぼれ話2 Rust のコンパイラ機能 #[start] 特定のシンボルの前(たとえば pub fn app_main() とかの前の行)に付けておく と,エントリポイントにしてくれる
#[link_section = “.test_section”] この行のところが ELF の.test_section になる。便利。 27 / 27