中断

中断是我们在操作系统上首先实现的功能,因为它是操作系统所有功能的基础。假如没有中断,操作系统在唤起一个用户程序之后,就只能等到用户程序执行完成之后才能继续执行,那操作系统完全无法进行资源调度。

操作系统就像家长,他将孩子(用户程序)送到学校(开始运行)之后便不再管。
但是如果孩子闯了祸,老师(硬件)就找到家长,这便是异常
孩子的作业可能需要家长来签字(系统调用),他就会主动找家长,这便是陷阱
放学时间(时钟中断)到,那么不管孩子想不想回家,家长都会把他接走,这便是硬件中断

RISC-V 与中断相关的寄存器和指令

RISC-V M态 S态

程序运行状态

中断时保存了各种寄存器的结构体叫做 Context,定义如下:

os/src/interrupt/context.rs
use riscv::register::{sstatus::Sstatus, scause::Scause};#[repr(C)]
#[derive(Debug)]
pub struct Context {pub x: [usize; 32],     // 32 个通用寄存器pub sstatus: Sstatus,pub sepc: usize
}

在 os/Cargo.toml 中添加依赖

os/Cargo.toml
[dependencies]
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }

状态的保存与恢复

汇编代码

os/src/interrupt/interrupt.asm
# 我们将会用一个宏来用循环保存寄存器。这是必要的设置
.altmacro
# 寄存器宽度对应的字节数
.set    REG_SIZE, 8
# Context 的大小
.set    CONTEXT_SIZE, 34# 宏:将寄存器存到栈上
.macro SAVE reg, offsetsd  \reg, \offset*8(sp)
.endm.macro SAVE_N nSAVE  x\n, \n
.endm# 宏:将寄存器从栈中取出
.macro LOAD reg, offsetld  \reg, \offset*8(sp)
.endm.macro LOAD_N nLOAD  x\n, \n
.endm.section .text.globl __interrupt
# 进入中断
# 保存 Context 并且进入 Rust 中的中断处理函数 interrupt::handler::handle_interrupt()
__interrupt:# 在栈上开辟 Context 所需的空间addi    sp, sp, -34*8# 保存通用寄存器,除了 x0(固定为 0)SAVE    x1, 1# 将原来的 sp(sp 又名 x2)写入 2 位置addi    x1, sp, 34*8SAVE    x1, 2# 保存 x3 至 x31.set    n, 3.rept   29SAVE_N  %n.set    n, n + 1.endr# 取出 CSR 并保存csrr    s1, sstatuscsrr    s2, sepcSAVE    s1, 32SAVE    s2, 33# 调用 handle_interrupt,传入参数# context: &mut Contextmv      a0, sp# scause: Scausecsrr    a1, scause# stval: usizecsrr    a2, stvaljal  handle_interrupt.globl __restore
# 离开中断
# 从 Context 中恢复所有寄存器,并跳转至 Context 中 sepc 的位置
__restore:# 恢复 CSRLOAD    s1, 32LOAD    s2, 33csrw    sstatus, s1csrw    sepc, s2# 恢复通用寄存器LOAD    x1, 1# 恢复 x3 至 x31.set    n, 3.rept   29LOAD_N  %n.set    n, n + 1.endr# 恢复 sp(又名 x2)这里最后恢复是为了上面可以正常使用 LOAD 宏LOAD    x2, 2sret

进入中断处理流程

开启中断

os/src/interrupt/handler.rs
use super::context::Context;
use riscv::register::stvec;global_asm!(include_str!("./interrupt.asm"));/// 初始化中断处理
///
/// 把中断入口 `__interrupt` 写入 `stvec` 中,并且开启中断使能
pub fn init() {unsafe {extern "C" {/// `interrupt.asm` 中的中断入口fn __interrupt();}// 使用 Direct 模式,将中断入口设置为 `__interrupt`stvec::write(__interrupt as usize, stvec::TrapMode::Direct);}
}

处理中断

os/src/interrupt/handler.rs
/// 中断的处理入口
///
/// `interrupt.asm` 首先保存寄存器至 Context,其作为参数和 scause 以及 stval 一并传入此函数
/// 具体的中断类型需要根据 scause 来推断,然后分别处理
#[no_mangle]
pub fn handle_interrupt(context: &mut Context, scause: Scause, stval: usize) {panic!("Interrupted: {:?}", scause.cause());
}

触发中断

  • 封装函数
os/src/interrupt/mod.rs
//! 中断模块
//!
//! mod handler;
mod context;/// 初始化中断相关的子模块
///
/// - [`handler::init`]
/// - [`timer::init`]
pub fn init() {handler::init();println!("mod interrupt initialized");
}
os/src/main.rs
...
mod interrupt;
.../// Rust 的入口函数
///
/// 在 `_start` 为我们进行了一系列准备之后,这是第一个被调用的 Rust 函数
pub extern "C" fn rust_main() -> ! {// 初始化各种模块interrupt::init();unsafe {llvm_asm!("ebreak"::::"volatile");};unreachable!();
}

编译
报错:

error[E0412]: cannot find type `Scause` in this scope--> src/interrupt/handler.rs:25:56|
25 | pub fn handle_interrupt(context: &mut Context, scause: Scause, stval: usize) {|                                                        ^^^^^^ not found in this scope|
help: consider importing one of these items

加入use riscv::register::scause::Scause;后
报错:

error: linking with `rust-lld` failed: exit status: 1|= note: "rust-lld" "-flavor" "gnu" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.1ex99mf92c1k73uw.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.1ggdewapwkd1laqm.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.1ie31wabbm6ma0bz.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.1msf1xdur9ui8t9t.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.21ifuvg1o556i0c9.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.26cy7179ka0d3b2o.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.2ajqzoj5o4lz6jqy.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.2olz1bixrztlx2qd.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.39g5l48jtbww5oxy.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.3g5qfmj2sipxrbv3.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.3gf88199k5ckaa2l.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.3u7lv19nlqbdhs8q.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.3v10y6d584e7au7t.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.3y2vu1f2a6mjmotg.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.4a6el1ytmlp8oxe7.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.4bm9ko0qh9wtzjx3.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.4hj0bw2aizfbk7uk.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.4p4vwi4bflbrbo3j.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.4syp7arr0xkhiqi2.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.4weud7xykyeaetmt.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.5122mutc9m7rkvj.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.517zv5ej306td7t8.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.57um9izm3s7k2ufz.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.58vtjgsrhpt1zo8a.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.5eeguwqj23tmn6ej.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.6s24bfn3o7ymfxr.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.bf7lhn7g7fz1a2g.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.eo197rx0sduxol5.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.iw0zfc38qhinii8.rcgu.o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.w4e4d2liakxudwd.rcgu.o" "--as-needed" "-L" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps" "-L" "/lab0/os/target/debug/deps" "-L" "/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv64imac-unknown-none-elf/lib" "-Bstatic" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/libriscv-f1160240c362ec62.rlib" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/libbit_field-0472c664a3ec824d.rlib" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/libbitflags-91eac2b932888616.rlib" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/libbare_metal-d997dd11e1f93a40.rlib" "/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv64imac-unknown-none-elf/lib/librustc_std_workspace_core-dfdcb86d1811d0a1.rlib" "/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv64imac-unknown-none-elf/lib/libcore-9ef51ad0e820a151.rlib" "/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv64imac-unknown-none-elf/lib/libcompiler_builtins-dc1b8d595fc78378.rlib" "-Bdynamic" "-znoexecstack" "-L" "/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv64imac-unknown-none-elf/lib" "-o" "/lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad" "--gc-sections" "-Tsrc/linker.ld"= note: rust-lld: error: undefined symbol: rust_main>>> referenced by 39g5l48jtbww5oxy>>>               /lab0/os/target/riscv64imac-unknown-none-elf/debug/deps/os-c764c360a07ebfad.39g5l48jtbww5oxy.rcgu.o:(.text.entry+0x8)error: aborting due to previous error; 3 warnings emittederror: could not compile `os`To learn more, run the command again with --verbose.
Makefile:20: recipe for target 'kernel' failed
make: *** [kernel] Error 101

rcore lab1相关推荐

  1. rust 实现 rCore lab1

    lab1 本实验目标是实现中断系统. lab1实验指导书 实验完成后目录结构如下: Project │ rust-toolchain │ └─os│ .gitignore│ Cargo.lock│ C ...

  2. THU-OS rCore学习总结 基于Rust + RISC-V

    文章目录 之后在知乎更新了: **[操作系统学习之路](https://www.zhihu.com/column/c_1368645188836106240)** --- ^^ --- 资料汇总 实验 ...

  3. ucore操作系统实验笔记 - Lab1

    最近一直都在跟清华大学的操作系统课程,这个课程最大的特点是有一系列可以实战的操作系统实验.这些实验总共有8个,我在这里记录实验中的一些心得和总结. Task1 这个Task主要是为了熟悉Makfile ...

  4. [ST2017] Lab1: Triangle type and Junit test

    Lab1 3014218071 王汉超 Request: Write a program with a function(getTriangleStatus) and test it, which t ...

  5. 6.824 MapReduce lab1 2020(一)

    文章目录 MIT 6.824 分布式系统 lab1:MapReduce Notes wordcount's MapReduce Model look like a simple sequential ...

  6. MIT6.830 lab1 SimpleDb 实验报告

    一.环境搭建 1.课程官网:6.830/6.814: Database Systems 2.Github地址:simple-db-hw-2021 3.安装配置ant 二.实验概览 SimpleDB c ...

  7. EIGRP分解试验部分-LAB1:EIGRP基本试验

    LAB1:EIGRP基本试验 拓扑图: 试验需求: 全网运行EIGRP路由协议,能够实现全网的互通,并且掌握主要几种show 命令的使用. 主要配置命令: R1(config)#router eigr ...

  8. ucore lab1 任务六

    任务六: 1.首先要明白什么是函数调用堆栈(上网查资料) 分析下述代码的堆栈调用 int Add(int x, int y) { return x + y; } void main() { int * ...

  9. MIT 操作系统实验 MIT JOS lab1

    JOS lab1 首先向MIT还有K&R致敬! 没有很好的开源环境我不可能拿到这么好的东西. 向每一个与我一起交流讨论的programmer致谢!没有道友一起死磕,我也可能会中途放弃. 跟丫死 ...

最新文章

  1. 前端面试题目汇总摘录(JS 基础篇 —— 2018.11.01更新)
  2. EBS R12中如何使用CGI登录Form
  3. 汇编指令mrs_汇编指令 - Mrs.kang - 博客园
  4. PAT甲级1146 Topological Order :[C++题解]拓扑排序、结构体存边、图论
  5. DBA查询命令积累——不断更新
  6. go语言调用python_Golang中调用Python3
  7. oracle 10g 关库,Oracle Db10g 启动和关闭数据库
  8. 数据结构(一)线性表
  9. AI开发者福音!阿里云推出国内首个基于英伟达NGC的GPU优化容器
  10. hibernate(3)对象关联映射
  11. PHP处理海量样本相似度聚类算法
  12. C语言基础-01-指针
  13. ubuntu14.04 下 mysql 存储目录迁移
  14. 没有搭讪的人生是不完整的
  15. R 和 rgl 绘制 3D 结
  16. 实战tkinter图形界面开发_Tkinter python(图形开发界面)
  17. PS 页面描述性语言PostScript
  18. harbor 安装启动遇到的keng
  19. 思维导图工具---Xmind使用方法和快捷键汇总(精简版)
  20. 软件测试中的软件质量保证,软件质量保障全流程(上)

热门文章

  1. 【LabVIEW懒人系列教程-视觉入门】2.3LabVIEW之Vision视觉助手案例
  2. axure详细教程 做app
  3. vue前端移动端UI框架比较分析
  4. Error:Could not expand ZIP *.aar
  5. itext总页数_itext 生成pdf文件添加页眉页脚
  6. 介绍一下神器mimikatz,从lsass里抓密码
  7. 每周全球科技十大新闻(2021.1.4-1.10)
  8. AndroidStudio当你在布局中创建一个Button想要设置它的颜色时,无法更改。。。。。。。。
  9. Unity Learn 项目 2D Platformer Microgame 教程(代码分析-功能实现方法)
  10. Web前端学习笔记05:CSS_盒子模型_复合选择器_标签显示 模式_三大特性_书写规范