XV6操作系统:trap机制学习笔记
参考CSAPP 第8章pleasewhy/xv6-book-2020-Chinese: MIT 6.S801 xv6 book 2020版 中文翻译 第4章ECF(Exceptional Control Flow) 异常控制流ECF是实现I/O、进程、虚拟内存的基本机制应用程序通过ECF与操作系统进行交互分为trap和system call系统调用在xv6中被统称为trap。通过ECF来向操作系统请求服务。理解ECF就明白怎么调用C API进而可以写各种各样的程序ECF是操作系统中实现并发的基本机制这种形式在简单的嵌入式程序中被称作中断。ECF也可以实现应用程序的报错信息响应总之ECF是非常强大的系统功能。1.异常当CPU检测到异常出现的时候无论是硬件的还是软件的操作系统会根据既有的异常表exception table来跳转到各种异常处理程序exception handler。异常分为四类中断interrupt、陷阱trap、故障fault、终止abort类别原因异步/同步返回行为举例中断来自IO设备的信号异步总是返回到下一条指令reset按键陷阱有意的异常同步总是返回到下一条指令open系统调用故障潜在可恢复的错误同步可能会返回到当前指令page fault不一定是真的错误终止不可恢复的错误同步不会返回Data abort 非法指针访问野指针1.1中断中断无时无刻都在发生时钟中断非常频繁键盘输入也是。中断恢复后根本没有任何问题。完全是一种健康的机制。1.2陷阱和系统调用trap和syscall用户经常要向操作系统请求服务看起来和中断没什么区别。区别在于其中cpu的状态发生了转变从用户态到核心态再恢复到用户态。Trap 是一种由软件指令有意触发的异常。它是 CPU 从用户模式权限低切换到内核模式权限最高的专用通道。Trap 也被称为软件中断 (Software Interrupt)。system call系统调用是操作系统OS提供给应用程序的标准化接口。它是程序向操作系统请求服务的唯一合法途径。printf就是最常见的系统调用通过write实现。常见的系统调用任务文件操作打开、读取、写入、关闭open, read, write, close。进程控制创建一个新进程、终止当前进程fork, exit。网络通信发送或接收网络数据包。设备管理请求使用摄像头、打印机等。linux的系统调用可以参考https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/1.3故障由当前指令引起但硬件认为还有救操作系统尝试修复。修复成功则重新执行当前指令修复失败则转为终止Abort。1.4终止程序或系统直接崩溃蓝屏或段错误直接被踢出运行队列。如硬件损坏、严重的内存访问冲突。2.risc-v如何处理trap2.1 名词解释stvecSupervisor Trap Vectortrap向量表ecallEnvironment Call环境调用指令sepcSupervisor Exception Program Counter异常计数器SIESupervisor Interrupt Enable中断标志位scauseSupervisor Cause记录trap原因MPPMachine Previous Privilege机器模式下SPP状态位sscratchSupervisor Scratch方便trap发生后恢复环境SPPSupervisor Previous Privilege记录Trap发生前cpu的状态sstatusSupervisor Status记录trap时系统状态hartidHardware Thread IDCPU idsretSupervisor Return汇编指令trapframe陷阱帧用来在 Trap 刚发生时保存事故现场信息pc程序计数器当前程序运行到内存的哪个地址了PTEPage Table Entry页表的最小单位satpSupervisor Address Translation and ProtectionTLBTranslation Lookaside BufferMMU的一级cachetrampoline跳板页用户页表和内核页表映射到了完全相同的虚拟地址page-fault缺页异常页表中找不到时发生的错误COWCopy-On-Write, 写时复制uservec / usertrap / userretuservec 是汇编入口负责保存寄存器并切换页表usertrap 是 C 语言决定如何响应userret 则是恢复环境、返回用户空间的出口。lazy allocation延迟分配 应对程序贪婪要内存的策略。内核先在页表打个无效标记等程序真正去访问这块内存触发 page-fault时才动真格分配物理内存2.2 寄存器功能stvec内核在这里写下 trap 处理程序的地址RISC-V 到这里来处理 trap。sepc当 trap 发生时RISC-V 会将程序计数器保存在这里因为PC会被stvec覆盖。sret(从 trap 中返回)指令将sepc复制到 pc 中。内核可以写sepc来控制sret的返回到哪里。scauseRISC -V 在这里放了一个数字描述了 trap 的原因。sscratch内核在这里放置了一个值这个值会方便 trap 恢复/储存用户上下文。sstatus:sstatus中的SIE位控制设备中断是否被启用如果内核清除SIERISCV 将推迟设备中断直到内核设置SIE。如果内核清除SIERISC-V 将推迟设备中断直到内核设置SIE。SPP位表示 trap 是来自用户模式还是监督者模式并控制sret返回到什么模式。2.3 trap处理流程当需要执行 trap 时RISC-V 硬件对所有的 trap 类型除定时器中断外进行以下操作如果该 trap 是设备中断且sstatus SIE位为 0则不要执行以下任何操作。通过清除 SIE 来禁用中断。复制 pc 到sepc将当前模式(用户或监督者)保存在 sstatus 的SPP位。在scause设置该次 trap 的原因。将模式转换为监督者。将stvec复制到 pc。执行新的 pc2.4 举例以下为write的一次完整系统调用。解析trampoline.S文件参见kernel.ld链接文件可以知道物理内存地址开始于0x80000000 接下来是.text段。这段相当于text段中特殊化了trampoline段trampoline实际上的功能就是在用户态与内核态切换时会发生用户虚拟页表、内核虚拟页表的切换。trampoline是变化中的不变这样才能保证内存不跑飞。它在两个表中都指向同一个物理地址。uservec是用户态到内核态的切换保存寄存器内容到内存trapframeuserret是内核态到用户态的切换从内存trapframe恢复寄存器以下为完整的write流程说明trampoline就像小孩蹦床一样让操作系统在用户态和内核态之间安全的反复横跳。其他的系统调用都是类似的。