引言

本章导读

本章展现了操作系统一系列功能:

  • 通过批处理支持多个程序的自动加载和运行

  • 操作系统利用硬件特权级机制,实现对操作系统自身的保护

批处理系统 (Batch System) 出现于计算资源匮乏的年代,其核心思想是: 将多个程序打包到一起输入计算机;当一个程序运行结束后,计算机会 自动 执行下一个程序。

应用程序难免会出错,如果一个程序的错误导致整个操作系统都无法运行,那就太糟糕了。保护 操作系统不受出错程序破坏的机制被称为 特权级 (Privilege) 机制,它实现了用户态和内核态的隔离。

本章在上一章的基础上,让我们的 OS 内核能以批处理的形式一次运行多个应用程序,同时利用特权级机制,令 OS 不因出错的用户态程序而崩溃。将待执行的程序嵌入 OS 内核之中是十分粗暴的,也不符合我们对操作系统的认知。这同时也意味着我们将开始使用独立的测例文件,并把它们打包到 os 之中。

实践体验

获取本章代码:

$ git clone https://github.com/LearningOS/rCore-Tutorial-2021Autumn.git
$ cd rCore-Tutorial-2021Autumn
$ git checkout ch2

在 qemu 模拟器上运行本章代码:

$ cd os
$ make run LOG=INFO

批处理系统自动加载并运行了所有的用户程序,尽管某些程序出错了:

[rustsbi] RustSBI version 0.2.0-alpha.4
.______       __    __      _______.___________.  _______..______   __
|   _  \     |  |  |  |    /       |           | /       ||   _  \ |  |
|  |_)  |    |  |  |  |   |   (----`---|  |----`|   (----`|  |_)  ||  |
|      /     |  |  |  |    \   \       |  |      \   \    |   _  < |  |
|  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
| _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|

[rustsbi] Implementation: RustSBI-QEMU Version 0.0.1
[rustsbi-dtb] Hart count: cluster0 with 1 cores
[rustsbi] misa: RV64ACDFIMSU
[rustsbi] mideleg: ssoft, stimer, sext (0x222)
[rustsbi] medeleg: ima, ia, bkpt, la, sa, uecall, ipage, lpage, spage (0xb1ab)
[rustsbi] pmp0: 0x80000000 ..= 0x800fffff (rwx)
[rustsbi] pmp1: 0x80000000 ..= 0x807fffff (rwx)
[rustsbi] pmp2: 0x0 ..= 0xffffffffffffff (---)
[rustsbi] enter supervisor 0x80200000
[kernel] Hello, world!
[ INFO] [kernel] num_app = 6
[ INFO] [kernel] app_0 [0x8020b040, 0x8020f868)
[ INFO] [kernel] app_1 [0x8020f868, 0x80214090)
[ INFO] [kernel] app_2 [0x80214090, 0x80218988)
[ INFO] [kernel] app_3 [0x80218988, 0x8021d160)
[ INFO] [kernel] app_4 [0x8021d160, 0x80221a68)
[ INFO] [kernel] app_5 [0x80221a68, 0x80226538)
[ INFO] [kernel] Loading app_0
[ERROR] [kernel] PageFault in application, core dumped.
[ INFO] [kernel] Loading app_1
[ERROR] [kernel] IllegalInstruction in application, core dumped.
[ INFO] [kernel] Loading app_2
[ERROR] [kernel] IllegalInstruction in application, core dumped.
[ INFO] [kernel] Loading app_3
[ INFO] [kernel] Application exited with code 1234
[ INFO] [kernel] Loading app_4
Hello, world from user mode program!
[ INFO] [kernel] Application exited with code 0
[ INFO] [kernel] Loading app_5
3^10000=5079(MOD 10007)
3^20000=8202(MOD 10007)
3^30000=8824(MOD 10007)
3^40000=5750(MOD 10007)
3^50000=3824(MOD 10007)
3^60000=8516(MOD 10007)
3^70000=2510(MOD 10007)
3^80000=9379(MOD 10007)
3^90000=2621(MOD 10007)
3^100000=2749(MOD 10007)
Test power OK!
[ INFO] [kernel] Application exited with code 0
Panicked at src/batch.rs:68 All applications completed!

本章代码树

.
├── ... (配置文件等)
├── os
│  ├── build.rs (新增:生成 link_app.S 将应用作为一个数据段链接到内核)
│  ├── Cargo.lock
│  ├── Cargo.toml
│  ├── Makefile (修改:构建内核之前先构建应用)
│  └── src
│     ├── batch.rs (新增:实现了一个简单的批处理系统)
│     ├── console.rs
│     ├── entry.asm
│     ├── lang_items.rs
│     ├── link_app.S (构建产物,由 os/build.rs 输出)
│     ├── linker.ld
│     ├── logging.rs
│     ├── main.rs (修改:主函数中需要初始化 Trap 处理并加载和执行应用)
│     ├── sbi.rs
│     ├── sync (新增:包装了RefCell,暂时不用关心)
│     │  ├── mod.rs
│     │  └── up.rs
│     ├── syscall (新增:系统调用子模块 syscall)
│     │  ├── fs.rs(包含文件 I/O 相关的 syscall)
│     │  ├── mod.rs(提供 syscall 方法根据 syscall ID 进行分发处理)
│     │  └── process.rs(包含任务处理相关的 syscall)
│     └── trap (新增:Trap 相关子模块 trap)
│        ├── context.rs
│        ├── mod.rs
│        └── trap.S
└── user (新增:应用测例保存在 user 目录下)
   ├── Cargo.lock
   ├── Cargo.toml
   ├── Makefile
   └── src
      ├── bin (基于用户库 user_lib 开发的应用,每个应用放在一个源文件中)
      │  └── ...
      ├── console.rs
      ├── lang_items.rs
      ├── lib.rs (用户库 user_lib)
      ├── linker.ld (应用的链接脚本)
      └── syscall.rs (包含 syscall 方法生成实际用于系统调用的汇编指令,
                      各个具体的 syscall 都是通过 syscall 来实现的)

❯ tokei os
===============================================================================
Language            Files        Lines         Code     Comments       Blanks
===============================================================================
Assembly                1           12           11            0            1
GNU Style Assembly      2           64           63            0            1
Makefile                1           52           36            4           12
TOML                    1           12            9            1            2
-------------------------------------------------------------------------------
Rust                   14          507          435           14           58
|- Markdown             1           11            0            9            2
(Total)                            518          435           23           60
===============================================================================
Total                  19          647          554           19           74
===============================================================================