Umgebung einrichten. Naked Binary oder Executable ohne main ()
Der erste Schritt beim Schreiben Ihres eigenen Betriebssystems besteht darin, eine Binärdatei zu erstellen, die nicht von Standardbibliotheken abhängt. Dies ermöglicht das Ausführen von Code ohne Betriebssystem - wir schreiben unser eigenes.
Der ursprüngliche Blog wird auf GitHub entwickelt . Hinterlassen Sie Ihre Kommentare dem Original auf der Seite "Probleme" des obigen Repositorys und der Übersetzung - in PM, Kommentaren oder hier . Der in diesem Artikel geschriebene Code ist in enthalten post-01.
Einführung
Um unser eigenes Betriebssystem zu schreiben, benötigen wir Code, der nicht von Bibliotheken oder Funktionen eines anderen Betriebssystems abhängt. Dies bedeutet, dass wir keine Threads, Dateien, Heapspeicher, Netzwerke, Terminalausgaben usw. verwenden können. Dies kann jedoch überwunden werden, indem Sie Ihr eigenes Betriebssystem und Ihre eigenen Treiber schreiben.
Wir können den größten Teil der Rust-Standardbibliothek nicht verwenden , aber es gibt auch viele Funktionen, die wir verwenden können . Zum Beispiel Iteratoren , Abschlüsse , Mustervergleich , Option und Ergebnis , Zeichenfolgenformatierung und natürlich das Konzept des Eigentums . Auf diese Weise können Sie Ihren Kernel in einem übergeordneten Stil schreiben, ohne sich um undefiniertes Verhalten oder Speichersicherheit sorgen zu müssen .
In diesem Artikel wird erläutert, wie Sie eine eigenständige ausführbare Datei erstellen und warum Sie sie benötigen. Wenn Sie nur ein Beispiel möchten, können Sie zum Abschnitt Schlussfolgerung scrollen.
Deaktivieren der Standardbibliothek
, , , .. : 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
. . , , . -, .