用Rust编写OS。设置环境。“裸”铁的二进制

设置环境。裸二进制文件,或不带main()的可执行文件



编写自己的操作系统的第一步是创建一个不依赖于标准库的二进制文件,这使得在没有操作系统的情况下运行代码成为可能-我们正在编写自己的操作系统。



原始博客正在GitHub上开发将您的评论保留在上面存储库的“问题”页面上的原始文档中,以及翻译成PM的注释或此处本文中编写的代码包含在中 post-01



介绍



为了编写我们自己的OS,我们需要不依赖于另一个操作系统的库或功能的代码。这意味着我们不能使用线程,文件,堆内存,网络,终端输出等。但这可以通过编写自己的OS和驱动程序来克服。



我们不能使用大多数Rust标准库,但是也可以使用许多功能例如,迭代器闭包模式匹配选项结果字符串格式,当然还有所有权概念这将使您能够以高级样式编写内核,而不必担心未定义的行为内存安全性



本文介绍了如何创建独立的可执行文件以及为什么需要它。如果只需要一个示例,则可以滚动到结论部分。



禁用标准库



默认情况下,编译后的代码是使用标准库构建的,操作系统需要该库来实现文件,网络等功能。它还取决于C:标准库libc,该更多地使用了OS功能。而且由于我们正在编写一个替换常规OS的程序,因此这不适合我们。您需要使用禁用库no_std



首先,让我们使用Cargo创建一个项目。这是使用命令行完成的:



cargo new os-in-rust --bin --edition 2018


我为该项目命名os-in-rust(以避免与原始博客混淆),但是您可以选择任何名称。该标志--bin表明您需要一个将被编译成可执行文件而不是库的项目。--edition 2018意味着您需要使用Rust 2018版货物将生成这样的文件夹结构:



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), .





Rust . , . , . — Cargo.toml:



[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


. . , , . -, .




All Articles