【rCore】用rust从零开始写一个操作系统 开源操作系统训练营:ch3 多道程序与分时多任务

需要实现什么

本章的目标是实现分时多任务系统,它能并发地执行多个用户程序,并调度这些程序。为此需要实现
一次性加载所有用户程序,减少任务切换开销;
支持任务切换机制,保存切换前后程序上下文;
支持程序主动放弃处理器,实现 yield 系统调用;
以时间片轮转算法调度用户程序,实现资源的时分复用。

拥有什么

实现了用户程序加载、用户态与内核态间的相互转换、trap处理机制、用户程序运行完成后切换至下一个程序的批处理系统。

思路

区别:

  1. 程序保存在内存中而非作为数据段链接到内核里。
  2. 同时管理多个应用程序。

定时触发时钟中断:
通过M特权级获取时间 -> 设置mtimecmp触发中断 -> 捕获中断运行下一个app

应用程序管理:
单例管理所有程序 -> 将程序保存在内存中 -> 实现应用加载、切换、退出 -> 实现yield让步

本章代码树

── os
   ├── build.rs
   ├── Cargo.toml
   ├── Makefile
   └── src
       ├── batch.rs(移除:功能分别拆分到 loader 和 task 两个子模块)
       ├── config.rs(新增:保存内核的一些配置)
       ├── console.rs
       ├── logging.rs
       ├── sync
       ├── entry.asm
       ├── lang_items.rs
       ├── link_app.S
       ├── linker.ld
       ├── loader.rs(新增:将应用加载到内存并进行管理)
       ├── main.rs(修改:主函数进行了修改)
       ├── sbi.rs(修改:引入新的 sbi call set_timer)
       ├── syscall(修改:新增若干 syscall)
       │   ├── fs.rs
       │   ├── mod.rs
       │   └── process.rs
       ├── task(新增:task 子模块,主要负责任务管理)
       │   ├── context.rs(引入 Task 上下文 TaskContext)
       │   ├── mod.rs(全局任务管理器和提供给其他模块的接口)
       │   ├── switch.rs(将任务切换的汇编代码解释为 Rust 接口 __switch)
       │   ├── switch.S(任务切换的汇编代码)
       │   └── task.rs(任务控制块 TaskControlBlock 和任务状态 TaskStatus 的定义)
       ├── timer.rs(新增:计时器相关)
       └── trap
           ├── context.rs
           ├── mod.rs(修改:时钟中断相应处理)
           └── trap.S

实现过程

定时触发时钟中断

通过M特权级获取时间

// os/src/timer.rs
use riscv::register::time;
pub fn get_time() -> usize {
   
    time::read()
}

设置mtimecmp触发中断

RISC-V 要求处理器维护时钟计数器 mtime,还有另外一个 CSR mtimecmp 。 一旦计数器 mtime 的值超过了 mtimecmp,就会触发一次时钟中断。

// os\src\sbi.rs
/// use sbi call to set timer
pub fn set_timer(timer: usize) {
   
    sbi_call(SBI_SET_TIMER, timer, 0, 0);
}

捕获中断运行下一个app

重新设置mtimecmp后运行下一个app。

timer 子模块的 set_next_trigger 函数对 set_timer 进行了封装, 它首先读取当前 mtime 的值,然后计算出 10ms 之内计数器的增量,再将 mtimecmp 设置为二者的和。 这样,10ms 之后一个 S 特权级时钟中断就会被触发。

trap_handler详解见 ch2 。

// os\src\trap\mod.rs
/// trap handler
#[no_mangle]
pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
   
		...
        Trap::Interrupt(Interrupt::SupervisorTimer) => {
   
            set_next_trigger();
            suspend_current_and_run_next();
        }
        ...
}

// os\src\timer.rs
/// Set the next timer interrupt
pub fn set_next_trigger() {
   
    set_timer(get_time() + CLOCK_FREQ / TICKS_PER_SEC);
}

应用程序管理

单例统一管理所有应用程序

TaskManager保存任务(进程)数、所有任务信息task、当前任务id。
Task包括任务状态和任务上下文TaskContext。
TaskContext包括ra、sp、s0-11寄存器。

lazy_static! {
   
    /// Global variable: TASK_MANAGER
    pub static ref TASK_MANAGER: TaskManager = {
   
        let num_app = get_num_app();
        let mut tasks = [TaskControlBlock {
   
            task_cx: TaskContext::zero_init(),
            task_status: TaskStatus::UnInit,

            syscall_t
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值