mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 14:27:49 +00:00
Compare commits
10 Commits
5baf50a5b4
...
c728cf8225
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c728cf8225 | ||
|
|
f38c11ae8e | ||
|
|
a1b195ede0 | ||
|
|
cfd31a977d | ||
|
|
06dd5edb3f | ||
|
|
685f55dd31 | ||
|
|
0b6b053c54 | ||
|
|
e0464fbd44 | ||
|
|
5e88b86d1e | ||
|
|
e6b507e6d2 |
@@ -1,5 +1,5 @@
|
||||
+++
|
||||
title = "Un binaire Rust autonome"
|
||||
title = "Un binaire Rust autoporté"
|
||||
weight = 1
|
||||
path = "fr/freestanding-rust-binary"
|
||||
date = 2018-02-10
|
||||
@@ -29,7 +29,7 @@ Ce blog est développé sur [GitHub]. Si vous avez un problème ou une question,
|
||||
|
||||
## Introduction
|
||||
Pour écrire un noyau de système d'exploitation, nous avons besoin d'un code qui ne dépend pas de fonctionnalités de système d'exploitation. Cela signifie que nous ne pouvons pas utiliser les fils d'exécution, les fichiers, la mémoire sur le tas, le réseau, les nombres aléatoires, la sortie standard ou tout autre fonctionnalité nécessitant une abstraction du système d'exploitation ou un matériel spécifique. Cela a du sens, étant donné que nous essayons d'écrire notre propre OS et nos propres pilotes.
|
||||
Cela signifie que nous ne pouvons pas utiliser la majeure partie de la [bibliothèque standard de Rust]. Il y a néanmoins beaucoup de fonctionnalités de Rust que nous _pouvons_ utiliser. Par exemple, nous pouvons utiliser les [iterators], les [closures], le [pattern matching], l'[option] et le [result], le [string formatting], et bien-sûr l'[ownership system]. Ces fonctionnalités permettent l'écriture d'un noyau d'une façon expressive et haut-niveau sans se soucier des [comportements indéfinis] ou de la [sécurité de la mémoire].
|
||||
Cela signifie que nous ne pouvons pas utiliser la majeure partie de la [bibliothèque standard de Rust]. Il y a néanmoins beaucoup de fonctionnalités de Rust que nous _pouvons_ utiliser. Par exemple, nous pouvons utiliser les [iterators], les [closures], le [pattern matching], l'[option] et le [result], le [string formatting], et bien sûr l'[ownership system]. Ces fonctionnalités permettent l'écriture d'un noyau d'une façon expressive et haut-niveau sans se soucier des [comportements indéfinis] ou de la [sécurité de la mémoire].
|
||||
|
||||
[option]: https://doc.rust-lang.org/core/option/
|
||||
[result]:https://doc.rust-lang.org/core/result/
|
||||
@@ -47,18 +47,18 @@ Cet article décrit les étapes nécessaires pour créer un exécutable Rust aut
|
||||
|
||||
## Désactiver la Bibliothèque Standard
|
||||
|
||||
Par défaut, tous les crates Rust relient la [bibliothèque standard], qui dépend du système d'exploitation pour les fonctionnalités telles que les fils d'exécution, les fichiers ou le réseau. Elle dépend aussi de la bibliothèque standard de C `libc`, qui intéragit de près avec les services de l'OS. Comme notre plan est d'écrire un système d'exploitation, nous ne pouvons pas utiliser des bibliothèques dépendant de l'OS. Nous devons donc désactiver l'inclusion automatique de la bibliothèque standard en utilisant l'[attribut `no std`].
|
||||
Par défaut, toutes les crates Rust sont liées à la bibliothèque standard, qui repose sur les fonctionnalités du système d’exploitation telles que les fils d'exécution, les fichiers et la connectivité réseau. Elle est également liée à la bibliothèque standard C `libc`, qui interagit étroitement avec les services fournis par l'OS. Comme notre plan est d'écrire un système d'exploitation, nous ne pouvons pas utiliser des bibliothèques dépendant de l'OS. Nous devons donc désactiver l'inclusion automatique de la bibliothèque standard en utilisant l'[attribut `no std`].
|
||||
|
||||
[bibliothèque standard]: https://doc.rust-lang.org/std/
|
||||
[attribut `no std`]: https://doc.rust-lang.org/1.30.0/book/first-edition/using-rust-without-the-standard-library.html
|
||||
|
||||
Nous commencons par créer un nouveau projet d'application cargo. La manière la plus simple de faire est avec la ligne de commande :
|
||||
Nous commençons par créer un nouveau projet d'application cargo. La manière la plus simple de faire est avec la ligne de commande :
|
||||
|
||||
```
|
||||
cargo new blog_os --bin --edition 2018
|
||||
```
|
||||
|
||||
J'ai nommé le projet `blog_os`, mais vous pouvez bien-sûr choisir le nom qu'il vous convient. Le flag `--bin` indique que nous voulons créer un exécutable (contrairement à une bibliothèque) et le flag `--edition 2018` indique que nous voulons utiliser l'[édition 2018] de Rust pour notre crate. Quand nous lançons la commande, cargo crée la structure de répertoire suivante pour nous :
|
||||
J'ai nommé le projet `blog_os`, mais vous pouvez évidemment choisir le nom qu'il vous convient. Le flag `--bin` indique que nous voulons créer un exécutable (contrairement à une bibliothèque) et le flag `--edition 2018` indique que nous voulons utiliser l'[édition 2018] de Rust pour notre crate. Quand nous lançons la commande, cargo crée la structure de répertoire suivante pour nous :
|
||||
|
||||
[édition 2018]: https://doc.rust-lang.org/nightly/edition-guide/rust-2018/index.html
|
||||
|
||||
@@ -75,7 +75,7 @@ Le fichier `Cargo.toml` contient la configuration de la crate, par exemple le no
|
||||
|
||||
### L'Attribut `no_std`
|
||||
|
||||
Pour l'instant, notre crate relie la bilbiothèque standard implicitement. Désactivons cela en ajoutant l'[attribut `no std`] :
|
||||
Pour l'instant, notre crate relie la bibliothèque standard implicitement. Désactivons cela en ajoutant l'[attribut `no std`] :
|
||||
|
||||
```rust
|
||||
// main.rs
|
||||
|
||||
@@ -49,7 +49,7 @@ pub extern "C" fn _start() -> ! {
|
||||
|
||||
// trigger a page fault
|
||||
unsafe {
|
||||
*(0xdeadbeef as *mut u64) = 42;
|
||||
*(0xdeadbeef as *mut u8) = 42;
|
||||
};
|
||||
|
||||
// as before
|
||||
|
||||
@@ -45,7 +45,7 @@ pub extern "C" fn _start() -> ! {
|
||||
|
||||
// ページフォルトを起こす
|
||||
unsafe {
|
||||
*(0xdeadbeef as *mut u64) = 42;
|
||||
*(0xdeadbeef as *mut u8) = 42;
|
||||
};
|
||||
|
||||
// 前回同様
|
||||
|
||||
@@ -48,7 +48,7 @@ pub extern "C" fn _start() -> ! {
|
||||
|
||||
// 페이지 폴트 일으키기
|
||||
unsafe {
|
||||
*(0xdeadbeef as *mut u64) = 42;
|
||||
*(0xdeadbeef as *mut u8) = 42;
|
||||
};
|
||||
|
||||
// 이전과 동일
|
||||
|
||||
@@ -42,7 +42,7 @@ pub extern "C" fn _start() -> ! {
|
||||
|
||||
// trigger a page fault
|
||||
unsafe {
|
||||
*(0xdeadbeef as *mut u64) = 42;
|
||||
*(0xdeadbeef as *mut u8) = 42;
|
||||
};
|
||||
|
||||
// as before
|
||||
@@ -374,9 +374,9 @@ pub fn init() {
|
||||
}
|
||||
```
|
||||
|
||||
We reload the code segment register using [`set_cs`] and load the TSS using [`load_tss`]. The functions are marked as `unsafe`, so we need an `unsafe` block to invoke them. The reason is that it might be possible to break memory safety by loading invalid selectors.
|
||||
We reload the code segment register using [`CS::set_reg`] and load the TSS using [`load_tss`]. The functions are marked as `unsafe`, so we need an `unsafe` block to invoke them. The reason is that it might be possible to break memory safety by loading invalid selectors.
|
||||
|
||||
[`set_cs`]: https://docs.rs/x86_64/0.14.2/x86_64/instructions/segmentation/fn.set_cs.html
|
||||
[`CS::set_reg`]: https://docs.rs/x86_64/0.14.5/x86_64/instructions/segmentation/struct.CS.html#method.set_reg
|
||||
[`load_tss`]: https://docs.rs/x86_64/0.14.2/x86_64/instructions/tables/fn.load_tss.html
|
||||
|
||||
Now that we have loaded a valid TSS and interrupt stack table, we can set the stack index for our double fault handler in the IDT:
|
||||
|
||||
@@ -47,7 +47,7 @@ pub extern "C" fn _start() -> ! {
|
||||
|
||||
// trigger a page fault
|
||||
unsafe {
|
||||
*(0xdeadbeef as *mut u64) = 42;
|
||||
*(0xdeadbeef as *mut u8) = 42;
|
||||
};
|
||||
|
||||
// as before
|
||||
|
||||
@@ -322,7 +322,7 @@ pub extern "C" fn _start() -> ! {
|
||||
blog_os::init();
|
||||
|
||||
// new
|
||||
let ptr = 0xdeadbeaf as *mut u32;
|
||||
let ptr = 0xdeadbeaf as *mut u8;
|
||||
unsafe { *ptr = 42; }
|
||||
|
||||
// as before
|
||||
@@ -347,7 +347,7 @@ pub extern "C" fn _start() -> ! {
|
||||
```rust
|
||||
// Note: The actual address might be different for you. Use the address that
|
||||
// your page fault handler reports.
|
||||
let ptr = 0x2031b2 as *mut u32;
|
||||
let ptr = 0x2031b2 as *mut u8;
|
||||
|
||||
// read from a code page
|
||||
unsafe { let x = *ptr; }
|
||||
|
||||
@@ -329,7 +329,7 @@ pub extern "C" fn _start() -> ! {
|
||||
blog_os::init();
|
||||
|
||||
// ここを追加
|
||||
let ptr = 0xdeadbeaf as *mut u32;
|
||||
let ptr = 0xdeadbeaf as *mut u8;
|
||||
unsafe { *ptr = 42; }
|
||||
|
||||
// ここはこれまでと同じ
|
||||
@@ -354,7 +354,7 @@ pub extern "C" fn _start() -> ! {
|
||||
```rust
|
||||
// 注意:実際のアドレスは個々人で違うかもしれません。
|
||||
// あなたのページフォルトハンドラが報告した値を使ってください。
|
||||
let ptr = 0x2031b2 as *mut u32;
|
||||
let ptr = 0x2031b2 as *mut u8;
|
||||
|
||||
// コードページから読み込む
|
||||
unsafe { let x = *ptr; }
|
||||
|
||||
@@ -316,7 +316,7 @@ pub extern "C" fn _start() -> ! {
|
||||
blog_os::init();
|
||||
|
||||
// new
|
||||
let ptr = 0xdeadbeaf as *mut u32;
|
||||
let ptr = 0xdeadbeaf as *mut u8;
|
||||
unsafe { *ptr = 42; }
|
||||
|
||||
// as before
|
||||
@@ -341,7 +341,7 @@ We see that the current instruction pointer is `0x2031b2`, so we know that this
|
||||
```rust
|
||||
// Note: The actual address might be different for you. Use the address that
|
||||
// your page fault handler reports.
|
||||
let ptr = 0x2031b2 as *mut u32;
|
||||
let ptr = 0x2031b2 as *mut u8;
|
||||
|
||||
// read from a code page
|
||||
unsafe { let x = *ptr; }
|
||||
|
||||
@@ -325,7 +325,7 @@ pub extern "C" fn _start() -> ! {
|
||||
blog_os::init();
|
||||
|
||||
// new
|
||||
let ptr = 0xdeadbeaf as *mut u32;
|
||||
let ptr = 0xdeadbeaf as *mut u8;
|
||||
unsafe { *ptr = 42; }
|
||||
|
||||
// as before
|
||||
@@ -350,7 +350,7 @@ pub extern "C" fn _start() -> ! {
|
||||
```rust
|
||||
// Note: The actual address might be different for you. Use the address that
|
||||
// your page fault handler reports.
|
||||
let ptr = 0x2031b2 as *mut u32;
|
||||
let ptr = 0x2031b2 as *mut u8;
|
||||
|
||||
// read from a code page
|
||||
unsafe { let x = *ptr; }
|
||||
|
||||
Reference in New Issue
Block a user