Rust in Action笔记 第十一、十二章 简易操作系统内核

本章讲了如何用Rust写一个简易的操作系统(FledgeOS),除了Rust的知识外,可以了解操作系统主要的组成部分,加深对操作系统的理解

  1. 首选需要掌握和了解一些工具或者技术,QEMU是一种虚拟化技术,用于搭建一个虚拟机来让你的程序运行在上面;bootimage库可以帮助减少底层代码的开发;
  2. 一开始需要安装几个库,cargo-binutils可以让cargo直接操作可执行文件,bootimage让cargo可以直接构建一个初始化镜像(boot image),镜像可以直接在硬件上初始化;rustup toolchain install nightly & rustup default nightly使用rust的一些尚未稳定的特性和功能;rustup component add rust-src下载rust语言的源码,让rust能为新的操作系统编译一个编译器;rustup component add llvm-tools-preview安装LLVM编译器的扩展,是rust编译器的一部分;
  3. 使用书中对应的代码编译成功后可以看到一个QEMU的黑色框,说明成功编译,在这个过程中bootimage库帮忙做了很多事情,a. 为目标操作系统创建了一系列机器可读(machine-readable)的定义和术语,例如目标CUP架构;b. 编译Rust core代码在目标OS上运行;c. 用刚编译的Rust语言来编译OS内核;d. 编译一个引导程序(bootloader)来读取刚编译的OS内核;e. 在虚拟环境QEMU中执行引导程序,引导程序运行OS内核;
  4. 项目结构中出现了.cargo/config.toml,里面提供了额外的配置参数,这里的作用是让编译器自己来编译std::core的部分,而不是依赖已经预先安装好的版本;cargo.toml里出现的run-command = ["qemu-system-x86_64", "-drive", "format=raw,file={}"]表示在cargo run的时候运行一个QEMU session,
  5. 代码列表11.4里出现了很多新的属性(attributes),Page373页有详细介绍;主程序的代码永不返回,设置了返回值是!;当程序挂掉的时候相当于整个电脑崩溃了,这里用到的是LLVM的abort()方法;在新的OS里为了避免动态分配内存选择了禁用标准库#![no_std];Rust的编译器有一部分是LLVM提供的,叫做intrinsic functions,为了使用这部分功能需要在开头加上#![core_intrinsics]属性,同时由于LLVM跟Rust的非耦合关系,其提供的API可能会变化,所以要显式地引入Rust nightly的编译器;Rust在引入外部crate的时候为了避免有些变量的名称冲突会引入name_mangling,但在这里需要禁用这个功能,通过#![no_mangle]属性;引入外部C代码要加上关键字extern "C";禁用main函数,使用#![no_main]属性,因为main函数的参数是由编译器_start()提供,所以这里不能有main函数;
  6. VGA兼容的模式下,往屏幕写数据的逻辑是,屏幕在硬件里被划分成一个80x25的网格,每一格由2个字节来表示,包括背景色、字符色等等,具体可见Page375,这个网格被叫做frame buffer,通过计算知道buffer大小是4000字节,本项目设置0xb8000为buffer的起始位置,通过.offset(1)来定位要写的buffer的位置,.write_volatie(0x30)来往对应的byte写入数据;
  7. FledgeOS如何启动,不是通过main()函数,而是需要软件能直接跟CPU通信,这个软件是BootLoader,由linker将某个符号(_start)链接到初始代码(entry point)处,CPU读取初始代码的指令开始执行;
  8. x86_64库能直接写指令跟CPU沟通,例如hlt()能让CPU休眠,减少CPU的使用率和电量;
  9. #![feature(lang_items)]注释表示当前文件提供的是语言条款(language item),语言条款是Rust实现的除了编译器以外的库,因为一开始标注了#[no_std]不能使用Rust标准库,所以为了新OS必须实现一些必要的库和函数;
  10. 后续这个OS主要讲了如何在QEMU虚拟环境如何处理输入输出和panic handling,与其他OS开发无异,详细可以看对应的章节;
  11. 区分信号(signals)和中断(interrupts),信号是软件层级的一种抽象,与OS相关;中断是硬件层级的抽象,主要是跟CPU有关;可见下图图12.1
  12. 中断(interrupt)会强制让应用的控制流改变,信号(signal)在某些情况下可以忽略(ignored),一旦收到中断,CPU要跳到对应的中断处理代码,中断处理代码由BIOS和OS在初始化进程(bootup process)预先定义;
  13. Rust实现软中断可以通过std::asm库带上#![feature(asm)属性,asm!("int 42") 宏可以插入中断,硬件中断最常见的是键盘中断,原理如下图12.3所示fig12.3

猜你喜欢

转载自blog.csdn.net/Mint2yx4/article/details/131538509
今日推荐