Configurando o ambiente. Binário nu ou executável sem main ()
O primeiro passo para escrever seu próprio sistema operacional é criar um binário que não depende de bibliotecas padrão, o que torna possível executar o código sem um sistema operacional - estamos escrevendo o nosso próprio.
O blog original está sendo desenvolvido no GitHub . Deixe seus comentários no original na página de Issues do repositório acima e na tradução - em PM, comentários ou aqui . O código escrito neste artigo está contido em post-01.
Introdução
Para escrever nosso próprio sistema operacional, precisamos de um código que não dependa de bibliotecas ou funções de outro sistema operacional. Isso significa que não podemos usar threads, arquivos, memória heap, rede, saída de terminal e assim por diante. Mas isso pode ser superado escrevendo seu próprio sistema operacional e drivers.
Nós não podemos usar a maior parte da biblioteca padrão Rust , mas também há muitas funções que pode usar. Por exemplo , iteradores , encerramentos , correspondência de padrões , Opção e Resultado , formatação de strings e, claro, o conceito de propriedade . Isso permitirá que você escreva seu kernel em um estilo de alto nível sem se preocupar com comportamento indefinido ou segurança de memória .
Este artigo explica como criar um arquivo executável autônomo e por que você precisa dele. Se você deseja apenas um exemplo, pode rolar até a seção Conclusão.
Desativando a biblioteca padrão
, , , .. : 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
. . , , . -, .