之前都是程序正常运行的、不需要网络交互、无IO交互、执行过程无错误、
但: 实际的软件、程序不仅执行简单指令、还会和IO打交道、执行过程中也会遇到各种异常情况
此时计算机如何工作呢?
异常
关于异常、其实是一个硬件和软件结合到一起的处理过程、异常的发生和捕获、是在硬件层面完成的; 异常的处理、是软件完成的
计算机会为每一种可能发生的异常、分配异常代码(Exception Number), 或者叫中断向量(Interrupt Vector), 异常发生的时候、通常是CPU检测到了一个特殊的信号、eg. 按下键盘上个的按键、输入设备就会给CPU发送信号、或者 正在执行的指令发生了加法溢出、会有一个进位溢出的信号、
这些信号在组成原理里, 一般叫 发生了一个事件(event)
CPU在检测到事件的时候、就拿到了对应的异常代码
这些异常代码里、
1.IO发出的信号的异常代码是操作系统分配的、即: 软件来设定的、
2.像加法溢出这样的异常代码、则是CPU预先分配好的、也就是硬件来分配的
拿到异常代码之后、CPU会触发异常处理的流程, 在计算机的内存里、会保留一个异常表 (Exception Table), 又叫中断向量表、存放了不同异常代码对应的异常处理程序(Exception Handler)的地址
CPU拿到异常码 -> 保存当前程序执行现场(到程序桟) -> 根据异常码找到对应处理程序 -> 把后续指令执行的指挥权、交给异常处理程序来处理
异常的分类: 中断、陷阱、故障和终止
中断(Interrupt): 在程序执行的过程中被打断、这个打断执行的信号、来自于CPU外部的IO设备、eg. 按下键盘按键
陷阱(Trap): 主动触发的异常,
eg. 1. 程序调试时、设定断点
2.应用程序产生系统调用的时候、从用户态切换到内核态、
3. 应用程序通过系统调用去读取文件、创建进程、其实也是通过触发陷阱完成的
故障(Fault): 和陷阱的区别在于: 陷阱是开发者主动触发的、故障是意料之外的、会导致系统异常
和前两者的区别在于: 故障在异常处理完成后、仍然回来处理当前指令、而不是执行下一条指令、因为当前指令由于故障没有执行完成
中止(Abort): 与其说是一种异常、不如说是故障的特殊情况、当CPU遇到故障、但无法恢复时、就不得不终止
异常的处理: 上下文切换
在实际异常处理程序之前、CPU需要一次保存现场的操作、过程与函数调用类似
实际更复杂一些:
1. 异常情况往往发生在正常执行的预期之外、eg. 中断、故障发生时、除了本来程序压桟要做的事情、还要把CPU内当前运行程序用到的所有寄存器、放到桟中、最典型的是 条件码寄存器
2. 像陷阱这种异常、涉及程序指令在用户态和内核态之间的切换、对应压桟的时候、对应数据要压到内核栈、而不是程序桟
3. 像故障这样的异常、在异常处理程序执行完成之后、从桟里返回、继续执行的是引起故障的当前指令、而不是顺序的下一条指令
对于异常这样的处理流程、不像是顺序执行的指令间的函数调用关系、更像是两个不同的独立进程在CPU层面的切换、这个过程称为 上下文切换(Context Switch)
网友评论