環境のセットアップ。ネイキッドバイナリ、またはメインなしで実行可能()
独自のOSを作成する最初のステップは、標準ライブラリに依存しないバイナリを作成することです。これにより、OSなしでコードを実行できるようになります。独自のOSを作成しています。
元のブログはGitHubで開発されています。上記のリポジトリの[問題]ページの元のページと、PM、コメント、またはここの翻訳にコメントを残してください。この記事で書かれたコードはに含まれてい post-01ます。
前書き
独自のOSを作成するには、ライブラリや別のオペレーティングシステムの機能に依存しないコードが必要です。これは、スレッド、ファイル、ヒープメモリ、ネットワーキング、端末出力などを使用できないことを意味します。しかし、これは独自のOSとドライバーを作成することで克服できます。
私たちは、ほとんどの使用することはできません錆標準ライブラリを、私たちがいることを多くの機能もありますすることができます使用しますが。たとえば、イテレータ、クロージャ、パターンマッチング、オプションと結果、文字列の書式設定、そしてもちろん所有権の概念。これにより、未定義の動作やメモリの安全性を気にすることなく、カーネルを高レベルのスタイルで作成できます。
この記事では、スタンドアロンの実行可能ファイルを作成する方法と、それが必要な理由について説明します。例が必要な場合は、[結論]セクションまでスクロールできます。
標準ライブラリを無効にする
, , , .. : libc, . , , . no_std.
Cargo. :
cargo new os-in-rust --bin --edition 2018
os-in-rust ( ), . --bin , , , . --edition 2018 , Rust 2018. Cargo :
os-in-rust
├── Cargo.toml
└── src
└── main.rs
Cargo.toml : , , . src/main.rs , , . cargo build, target/debug.
no_std
. no_std:
// main.rs
#![no_std]
fn main() {
println!("Hello, world!");
}
, :
error: cannot find macro `println!` in this scope
--> src/main.rs:4:5
|
4 | println!("Hello, world!");
| ^^^^^^^
, println — Rust, . , . , , . :(
:
// main.rs
#![no_std]
fn main() {}
> cargo build
error: `#[panic_handler]` function required, but not found
error: language item required, but not found: `eh_personality`
panic!()
panic_handler , , ( panic!()). , no_std :
// main.rs
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
PanicInfo , , () . , — ! (never). , .
eh_personality
eh_personality — " ", , . , Copy — , , . , #[lang = "copy"], .
, , , , ! , .
eh_personality , "" . Rust , . , , (libunwind Linux Windows), .
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
abort dev ( cargo build), release (cargo build --release). eh_personality.
. :
> cargo build
error: requires `start` lang_item
start
, main . . , (Java, C#, JavaScript...) (, Go). main .
Rust , crt0, . , , . Rust , start, Rust , main().
, crt0, . crt0.
, , #![no_main].
#![no_std]
#![no_main]
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
main(), . _start:
#[no_magnle]
pub extern "C" fn _start() -> ! {
loop {}
}
#[no_mangle], , _start, , , _ZN3blog_os4_start7hb173fedf945531caE. , .
extern "C", , , Rust ( , , , ). , .
, , , !, , . , , , ( ).
, cargo build, .
— , , , . , , .
, , , . 2 : , .
""
Rust . Windows x86-64, Rust .exe x86-64. .
Rust ( ) target triples. , rustc --version --verbose:
rustc 1.47.0-nightly (576d27c5a 2020-08-12)
binary: rustc
commit-hash: 576d27c5a6c80cd39ef57d7398831d8e177573cc
commit-date: 2020-08-12
host: x86_64-unknown-linux-gnu
release: 1.47.0-nightly
LLVM version: 10.0
(Linux x86-64). , — host. , :
-
x86-64, - : Linux,
- ABI: GNU
, Rust , - ( , Linux) (libc, libunwind ). , .
thumbv7em-none-eabihf, ARM. , , (none). , Rustup:
rustup target add thumbv7em-none-eabihf
:
cargo build --target thumbv7em-none-eabihf
--target, - . , , .
, . thumbv7em-none-eabihf x86-64. ( ), . , m1rko, ( ).
, :
src/main.rs:
#![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points
use core::panic::PanicInfo;
#[no_mangle] // don't mangle the name of this function
pub extern "C" fn _start() -> ! {
// this function is the entry point, since the linker looks for a function
// named `_start` by default
loop {}
}
/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
Cargo.toml:
[package]
name = "crate_name"
version = "0.1.0"
authors = ["Author Name <author@example.com>"]
# the profile used for `cargo build`
[profile.dev]
panic = "abort" # disable stack unwinding on panic
# the profile used for `cargo build --release`
[profile.release]
panic = "abort" # disable stack unwinding on panic
— :
cargo build --target thumbv7em-none-eabihf
. . , , . -, .