1、概念:系统中每种可能的类型都分配了一个非负的异常号,当处理器检测到有事件发生时,就会通过一个叫做异常表的跳转表进行间接过程调用(异常),到一个专门用来处理这类事件的操作系统子程序(异常处理程序)。系统启动时操作系统会初始化异常表,表中的条目k包含异常k的处理程序地址,下图展示了处理器如何用异常表生成异常处理程序的地址,异常表的起始地址存放在一个叫做异常表基址寄存器的特殊CPU寄存器里面,其中异常号是异常表中的索引。
异常与过程调用的不同:
①两者都需要将返回地址压入栈中,但异常压入栈中的地址可能是当前指令的也可能是下一条指令的。
②处理器会把一些额外的状态压入栈中,当处理程序返回执行被中断的程序会需要这些状态。如果控制从用户转移到内核,所有的项目都会被压入内核栈而不是用户栈。
③异常处理程序运行在内核模式下,对所有的系统资源具有完全访问权。
2、分类:异常分为中断(interrupt)、陷阱(trap)、故障(fault)和中止(abort)。如下图:
①中断:中断时异步发生的,来自处理器外部的I/O设备信号,它不是由专门的指令产生的,从这个方面来说它是异步的。硬件中断的处理程序通常叫做中断处理程序。
②陷阱:它是有意的异常,是处理一条指令的结果。它最重要的作用是在用户程序和内核之间提供一个像过程一样的接口,也叫系统调用,执行完这条指令它就会陷入内核。用户程序经常会请求内核服务,比如如文件(read)、创建进程(fork)、加载程序(execve)、终止当前进程(exit)等。处理器提供了一条‘syscall n’指令来允许对这些内核服务进行受控的访问,执行syscall指令会导致异常处理程序的陷阱。
③故障:故障由错误情况引起,可能能被故障处理程序处理。否则会返回内核的abort例程,终止应用程序。一个经典的故障是缺页,当指令引用一个虚拟地址,而与其对应的物理地址不存在就会引发一个缺页异常,缺页处理程序会从磁盘中加载对应页,然后将控制返回给引发故障的指令。
④终止:会将控制返回给内核的abort例程,终止应用程序。
x86_64系统中有高达256种异常,0~31号是由Intel架构师定义的异常,32~256号则是由操作系统定义的中断和陷阱。