Rust开发操作系统系列:从零制作x86_64位系统

Written by with ♥ on in Linux的日常, 程序员

在发表这个文章之前,我曾发布过另一篇文章:Rust开发操作系统系列:全新Hello World系统
那篇文章我发布在云栖社区以及我自己的博客:青藤木子上,但是这是我第一次认真的写一篇文章,虽然看的人不多,也没几个人回复我,文章里也有很多的问题,目前你可以在我的博客上找到最新的修订版本,感谢转载和分享,也请您在转发文章时添加上原文章地址。也希望有更多人回复我、批评我、分享一些我不知道的知识。

这个系统可以干什么??

  • [ ] 内存分页
  • [ ] 线程
  • [ ] 中断
  • [o] 一个打印(print)功能
  • [o] 在qemu上能够运行
  • [o] VGA驱动
  • 注意⚠️

  • 本人是在Mac OSX 上工作的,因此作者目前不会在其他平台上出教程,不过您有需要的话,请留言告知我
  • 在使用Rust的时候请安装每夜版(nightly),这样方便同步,使用稳定版或beta版时将无法编译!
  • 资料我将打包成zip,您可以自行下载固件编译运行。
  • 目前来说这个自制的系统还无法直接在裸机上运行,而编译固件时编译的是bin固件。
  • 如果您遇到了什么问题,可以下载源码查看:这里这里

编译环境安装

Rust安装是及其简单的,而且之前我的文章里也提到过安装Rust,如果您没有跟着那篇文章尝试过编译arm架构的最微型系统,那么建议您去try一下!

安装Rust

$ curl https://sh.rustup.rs -sSf | sh

如果您安装了Rust但没有nightly版,可以使用这个命令:

$ rustup install nightly

设置nightly为默认

$ rustup default nightly

安装拓展工具

$ cargo install bootimage

$ cargo install cargo-xbuild

$ rustup component add rust-src --toolchain=nightly

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

$ brew install qemu

注意:qemu需要homebrew来安装,在中国安装homebrew可能是最麻烦的事,您可以去百度寻找解决方案或自行挂 梯子


开始书写代码

首先用cargo来创建项目

$ cargo new apps

打开apps文件,然后创建一个叫做apps.json的文件,在这个文件里写:

{
  "llvm-target": "x86_64-unknown-none",
  "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
  "arch": "x86_64",
  "target-endian": "little",
  "target-pointer-width": "64",
  "target-c-int-width": "32",
  "os": "apps",
  "linker": "rust-lld",
  "linker-flavor": "ld.lld",
  "executables": true,
  "features": "-mmx,-sse,+soft-float",
  "disable-redzone": true,
  "panic-strategy": "abort"
}

接下来就是修改Cargo.toml,就像这样:

[dependencies]
bootloader_precompiled = "0.3.0"
mars_vga = "0.0.1"

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"

[package.metadata.bootimage]
default-target = "apps.json"

然后我们打开src/main.rs,改成这样:

#![feature(core_intrinsics)]
#![no_std]
#![no_main]

// 使用 #[macro_use] 来表明使用 vga crate 的宏命令:print! 和 println!
#[macro_use]
extern crate mars_vga;
extern crate bootloader_precompiled;

use core::intrinsics;
use core::panic::PanicInfo;

#[panic_handler]
#[no_mangle]
fn panic(_info: &PanicInfo) -> ! {
    unsafe { intrinsics::abort() }
}

// 系统入口处
#[no_mangle]
pub fn _start() -> ! {
    println!("hello world");
    loop {}
}

当然您可能会说我看不懂,你就这么让我这样做,我怎么能懂?
没问题的,让我们先把系统写好后再慢慢跟您讲。


运行

打开终端,然后跳转到apps文件夹里,执行这些命令:

$ bootimage build
$ bootimage run

经过长久(如果下载时间过长,建议更换dns,比如这个: 1.0.0.1或1.1.1.1)的编译后终于运行了!

未命名.png


解释原理

现在回过头看您的代码,是否有注意到这个crate吗:mars_vga?,这是我借鉴别人的资料写的一个crate(如果您不知道什么是crate,可以在https://kaisery.github.io/trpl-zh-cn/这个中文教程里找到,这是一个Rust教程)
这个crate里我添加了宏函数,即println!print!,这样您就可以直接打印出一串字了,但不支持中文。这是一个很好的方法,也是Rust独具一格的优点,即您可以将一些可以分开的方法打包成crate然后上传到crate.io里,当需要添加到项目里时直接在Cargo.toml这个文件里添加crate就可以了,如果您对这个mars_vga感兴趣,可以用Idea IDE工具打开这个项目,然后就可以查看这个crate的源码了

我们创建了一个apps.json文件,这个是bootimage工具编译时需要的东西,有了bootimage工具我们就可以实现交叉编译(这个平台编译另一个平台的东西)。

#![feature(core_intrinsics)]
#![no_std]
#![no_main]

// 使用 #[macro_use] 来表明使用 vga crate 的宏命令:print! 和 println!
#[macro_use]
extern crate mars_vga;
extern crate bootloader_precompiled;

use core::intrinsics;
use core::panic::PanicInfo;

#[panic_handler]
#[no_mangle]
fn panic(_info: &PanicInfo) -> ! {
    unsafe { intrinsics::abort() }
}

// 系统入口处
#[no_mangle]
pub fn _start() -> ! {
    println!("hello world");
    loop {}
}

![no_std]#用来告诉Rust编译器:我们不使用Rust标准库,在系统开发中,内存、线程、文件系统我们需要自己写,Rust标准库不适用,我们只使用Rust的核心库(core)就可以了
![no_main]用来告诉Rust:我们没有main方法,我们在做系统。因此Rust允许我们自己创建main方法。
#[macro_use]用来告诉Rust:我想使用我自己建的宏函数。这个参数让Rust允许使用我们自建的宏函数。
#[no_mangle]用来告诉Rust:我想定义一个方法,它的名字与标准库里一个叫做painc方法一样。

#[panic_handler]
#[no_mangle]
fn panic(_info: &PanicInfo) -> ! {
    unsafe { intrinsics::abort() }
}

这里是异常处理方法,因为这个系统还没有更高级的东西,因此这个方法只有终止的功能

// 系统入口处
#[no_mangle]
pub fn _start() -> ! {
    println!("hello world");
    loop {}
}

这是我们定义了_start()方法,为什么它不叫main呢?因为main仅仅是内核启动点,而最先启动的应该是_boot。那为什么会添加一个-> !?这是因为系统一旦启动,而且永远也不返回参数,系统也永远不会执行完就停止,所以我们在这个方法里添加了loop{}


还有吗???

做一个系统就这么点代码吗?当然不是,你看到的只是这几十行代码,而其他代码都是被封装成crate了。那些为计算机科学作出贡献的人,不断的、夜以继日的帮助着我们,我们可能只写了几十行,但在这几十行代码的背后,就有那么一群人写了几千行,尽了最大了努力来让我们写出高效美丽的代码!感谢这群人、这群“疯子”!

关于这件事

有人可能遇到过这种事情:好声好气告诉别人不要乱扔垃圾,结果被人骂“读书读傻了”,可能做错了一点点事情,也被骂“读书读傻了”
如果这个世上有很多的这样的人,想象一下这个世界会发生怎样的变化?世界很残酷,但是我们仍然关爱老人,以前肉弱强食,但是现在我们关爱残疾、关爱病人、帮助着在这个世界无法自足的人们。我们有着自己选择的权利,有着一颗炙热的心,每个人有不同的活法,但请做一个道德的人,如果这都无法做到的话,我也会不客气的。


2016gg.gificon_neutral.gificon_wink.gif2016kel.gif2016qd.gif2016tp.gificon_idea.gif2016tuu.gificon_evil.gif2016tx.gificon_mad.gificon_twisted.gificon_razz.gif2016ch.gificon_confused.gif2016qq.gif2016kb.gificon_sad.gif2016jk.gificon_exclaim.gificon_cool.gif2016db.gif2016zj.gif2016am.gif2016ka.gif2016xia.gificon_question.gif2016baojin.gif2016kun.gif2016bz.gif2016kuk.gif2016qiao.gif2016zk.gificon_biggrin.gif

Edit with markdown

渝ICP备17015729号-1