开篇

异常这个名词应该大家都不陌生,很多人都听说过。系统调用知道吧?其实系统调用也是一种异常。但是具体的什么是异常呢?他在计算机中有什么作用?他是如何工作,如何被我们利用的?我想很多人都还不都是很清楚。、

了解异常有诸多好处,可以让你更好的理解操作系统和应用程序的交互,更好的理解并发等。

所以今天就简单的来说一下异常。

 注:本博文图片来源《Computer system-A Programmer's Perspective》

什么是异常

为了便于理解,我就不按照书本来了啊,异常可以这样理解:

计算机执行一个连续的指令序列,如:a1,a2,a3,,,ak,这些指令执行的时候是顺序执行的,相邻的两条指令ak,ak+1在存储中也是相邻的,也就是说他们是一个平滑的指令流。

而有时候这种指令流会发生突变,也就是说相邻执行的两条指令ak,ak+1在存储器中是不相邻的。造成这种突变的可能有:跳转,函数调用,返回等。今天我们所讨论的异常,也是造成这种指令流突变的原因之一。

所以异常可以认为是指令顺序执行的时候,突然跳转到别的地方执行指令。

现在就可以来看相对专业的说法了:异常是控制流中的突变,用来相应处理器状态中的某些变化。

可以通过下图来更好的理解上述内容:

说说计算机中的异常-LMLPHP

那么异常处理结束后计算机中的指令如何继续往下执行呢?根据触发异常的种类,会有三种情况:

1)处理程序将控制返回给当前指令I currr,即当事件发生时正执行的指令。

2)将控制返回给下一条指令,即如果没有发生异常的下一条指令。

3)终止发生异常的程序。

异常处理

 现在应该基本搞懂什么是异常了吧,发生了异常,总不能就不管吧,呵呵,有异常总是要处理的。这个部分就简单的说一下异常处理。

按照上面所说的,异常是在指令顺序执行的时候由于某些突发情况指令跳到其他地方执行。注意上面说的是“跳到其他地方执行”所以说,异常处理也是通过固定的程序代码来实现的。至于具体的怎么实现,我们并不关心,这里要关注的是控制是如何从发生异常的程序跳转到处理程序的。

系统中为可能的每种异常都分配了一个唯一的非负数异常号。每个异常号记录了处理该异常的代码。这些数据被放在一个称为异常表的结构里,当系统初始化的时候会初始化这个表。所以当发生异常的时候,对应于异常表中的那个异常号,就能定位到具体的异常处理程序了。

下面是一个异常表:

说说计算机中的异常-LMLPHP

在系统运行时,如果发生一个异常,系统检测得到其异常号,通过异常号,就能确定要处理的异常,同时也确定了处理异常的程序地址。异常号是到异常表的一个索引,相当于一个异常号就对应于异常表中的一项。异常表的起始地址放在一个异常表基寄存器的特殊cpu寄存器里。下面是一个生成异常处理程序地址的过程:

说说计算机中的异常-LMLPHP

通过异常号和基址确定了异常表中的一个项,从而确定异常处理程序的地址。

异常的类别

什么?异常还有类别?。。。是的,在运行过程中会发生各种各样的异常,所以就把他们分为四类:中断(interrupt)陷阱(trap)故障(fault)终止(abort)

下面就简单的说一下吧:

中断:

中断是异步发生的,是来自处理器外部的I/O设备的信号的结果。为什么是异步呢?硬件中断不是由任何一条指令造成的,从这个意义上说是异步的。硬件中断的异常处理程序通常也叫中断处理程序。 

说说计算机中的异常-LMLPHP

如图中所示,中断处理程序完成时,他将控制返回给下一条指令(即如果没有发生中断,在控制流中当前指令之后的一条指令)结果是程序继续执行,就好像没发生中断一样。

 

陷阱和系统调用

系统调用应该很多人都知道,而且经常在用,其实系统调用也是异常的一种,他是”有意“的异常。

就像中断处理程序一样,陷阱处理程序将程序控制返回到下一条指令。陷阱最重要的作用是在用户程序和内核之间提供一个像过程调用一样的接口,叫做系统调用。

用户程序经常要像内核请求服务,比如读一个文件(read)创建一个进程(fork)加载以新的程序(execve)等。为了让用户程序实现这些功能,处理器提供了一条特殊的“system call n ”指令。执行system call 指令会导致一个到异常处理程序的陷阱,这个程序对参数n 进行解码,并调用适当的内核程序。

具体的过程如下图所示:

说说计算机中的异常-LMLPHP

如图所示:陷阱处理程序将程序控制返回到下一条指令.

关于系统调用和函数调用的区别可参见前一篇文章:

linux系统调用和库函数调用的区别

故障:

故障由错误情况引起,它能够被故障处理程序修正。当故障发生时,处理器将控制转移给故障处理程序。如果能修复错误,返回到引起故障的指令,重新执行它,否则终止引起故障的程序(调用abort)。

说说计算机中的异常-LMLPHP

一个经典的故障处理程序是页缺异常。当引用到一个虚拟地址,而与该地址对应的物理页面不在存储器中,必须从磁盘中取出,就会发生故障。故障处理程序(这里是页缺处理程序)会将页面从磁盘中加载到内存中,把控制返回给引起故障的指令重新执行。当指令再次执行时,相应的物理页面已经在内存中了,指令便可以没有故障的运行。

 

 终止:

终止是不可恢复的致命错误造成的结果,通常是一些硬件错误。终止处理程序不会吧控制返回给引起异常的程序,处理程序会将控制返回给一个abort,然后终止这个应用程序。

说说计算机中的异常-LMLPHP

小结

 这篇博文内容较少,理解起来也比较容易。异常在计算机中是很重要的一个概念,关于异常的东西还有很多需要学习。遇到不懂的东西,之前很喜欢google,把要搜的东西翻译为英文然后在美国的服务器搜,各种搜索。慢慢的觉得这种学习方式还是欠妥的,上网获取知识的速度确实是很快,可是知识的质量就参差不齐了,对于一个知识点的理解很难在网上找到满意的解(这个或许大家也感同身受吧)相反,看书获取知识相对慢一些,却能得到高质量的知识。所以当你对一系列的知识点模糊不清的时候,我觉的看书的最好的。当然了,看书得看经典书。何为经典书?我认为:1)在某方面的知识点全面。2)语言方面通俗易懂。3)合理的安排了学习顺序。

 

这篇博文参考了《深入理解计算机系统》,我是第二次看这个书,感觉还是很有收获。

本书英文版下载地址:http://ishare.iask.sina.com.cn/f/24228232.html

全文完,不足之处望不吝赐教!

10-07 19:10