异常:硬件、系统和应用的组合拳
一提到计算机当中的异常(Exception),可能你的第一反应就是 C++ 或者 Java 中的Exception。不过我们今天讲的,并不是这些软件开发过程中遇到的“软件异常”,而是和硬件、系统相关的“硬件异常”。
尽管,这里我把这些硬件和系统相关的异常,叫作“硬件异常”。但是,实际上,这些异常,既有来自硬件的,也有来自软件层面的。
比如,我们在硬件层面,当加法器进行两个数相加的时候,会遇到算术溢出;或者,玩游戏的时候,按下键盘发送了一个信 给CPU,CPU要去执行现有流程之外的指令,这也是一个“异常”。
同样,来自软件层面的,比如我们的程序在进行系统调用,发起一个读文件的请求。这样应用程序向系统调用发起请求的情况,一样是通过“异常”来实现的。
异常,其实是一个硬件和软件组合在一起的处理过程。
- 异常的前半生,也就是异常的发生和捕捉,是在硬件层面发生的
- 异常的后半生,也就是异常的处理,是由软件来完成的
计算机会为每一种可能发生的异常,分配一个异常代码(也叫做中断向量)。异常发生的时候,通常是CPU检测到了一个特殊的信 。这些信 ,在组成原理里面,一般叫做发生了一个事件。CPU在检测到事件的时候,其实也就拿到了对应的异常代码。
这些异常代码里,IO发出的信 的异常代码,是由操作系统来分配的,也就是有软件来设定的。而像加法移除这样的异常代码,则是由CPU预先分配好的,也就是由硬件来分配的。可以看出,这也是由软件和硬件组合起来处理异常的过程
拿到异常代码后,CPU就会触发异常处理的流程。计算机在内存中,会保存一个异常表(也叫做中断向量表),好和上面的中断向量对应起来。表中存放的是不同的异常代码对应的异常处理程序(Exception Handler)所在的地址。
CPU拿到异常码之后,会先把当前的程序执行的现场,保存到程序栈里面,然后根据异常码查询,找到对应的异常处理程序,最后把后继指令执行的控制权,交给这个异常处理程序
再比如说,Java 里面,我们使用一个线程池去运行调度任务的时候,可以指定一个异常处理程序。对于各个线程在执行任务出现的异常情况,我们是通过异常处理程序进行处理,而不是在实际的任务代码里处理。这样,我们就把业务处理代码就和异常处理代码的流程分开了。
异常的分类:中断、陷阱、故障和中止
异常可以由硬件触发,也可以由软件触发。那我们平时会碰到哪些异常呢p>
(1)中断(Interrupt)
- 就是程序在执行到一半的时候,被打断了。这个打断执行的信 ,来自于CPU外部的IO设备
- 你在键盘上按下一个案件,就会对应触发一个响应的信 到CPU里面。CPU里面某个开关的值发生了变化,也就触发了一个中断类型的异常
(2)陷阱(Trap)
- 陷阱,是程序员“故意”主动触发的异常。就好像你在程序里面打了一个“断点”,这个断点就是设下一个“陷阱”。当程序的指令执行到这个位置的时候,就掉到了这个陷阱中。然后的,对应的异常处理程序就会来处理这个“陷阱”当中的猎物。
- 最常见的一类陷阱,发生在我们的应用程序调用系统调用的时候,也就是从程序的用户态切换到内核态的时候。
- 我们的应用程序通过系统调用去读取文件、创建进程,其实也是通过触发一次陷阱来进行的。这是因为,我们用户态的应用程序没有权限来做这些事情,需要把对应的流程交给有权限的异常处理程序来进行
(3)故障(Fault)
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!