当前位置: 首页 > news >正文

4.2说说计算机中的异常

开篇

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

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

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

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

什么是异常

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

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

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

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

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

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

 

 

 

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

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

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

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

异常处理

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

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

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

下面是一个异常表:

 

 

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

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

异常的类别

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

下面就简单的说一下吧:

中断:

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

 

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

 

陷阱和系统调用

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

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

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

具体的过程如下图所示:

 

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

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

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

故障:

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

 

 

 

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

 

 终止:

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

 

 

 

小结

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

 

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

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

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

 

 

 

 

 

 

参看资料:computer systems

如有转载请注明出处:http://www.cnblogs.com/yanlingyin/

一条鱼、尹雁铃@ 博客园 2012-5-05

 E-mail:yanlingyin@yeah.net

 

转载于:https://www.cnblogs.com/Ph-one/p/7718075.html

相关文章:

  • 并发编程的几种形式
  • 【传感器】BMA253 数字,三轴加速度传感器
  • 数据结构(六)——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现...
  • c语言的按位运算符
  • 汇编语言如何取段地址的
  • 二路归并排序算法
  • 什么是MSB/LSB码?
  • 平衡二叉树(AVL树)
  • 二叉排序树(查询、插入、删除)
  • 数据结构中的堆和操作系统里的堆不一样为什么都叫堆呢?
  • 关于Simplicity Studio使用math.h编译出错
  • 正态分布(Normal distribution)又名高斯分布(Gaussian distribution)
  • MLP(多层神经网络)介绍
  • ring0
  • 什么是“欧几里德范数”(Euclidean norm)?
  • JavaScript 如何正确处理 Unicode 编码问题!
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • classpath对获取配置文件的影响
  • ES6核心特性
  • Golang-长连接-状态推送
  • Mysql5.6主从复制
  • Netty源码解析1-Buffer
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 实习面试笔记
  • 通过npm或yarn自动生成vue组件
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 小李飞刀:SQL题目刷起来!
  • 学习HTTP相关知识笔记
  • 一文看透浏览器架构
  • 用 Swift 编写面向协议的视图
  • 源码安装memcached和php memcache扩展
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • #QT(智能家居界面-界面切换)
  • (python)数据结构---字典
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (区间dp) (经典例题) 石子合并
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)RocketMQ初步认识
  • (转载)hibernate缓存
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .Family_物联网
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .Net中的集合
  • .Net组件程序设计之线程、并发管理(一)
  • @vue/cli脚手架
  • [ 隧道技术 ] 反弹shell的集中常见方式(二)bash反弹shell
  • [ai笔记9] openAI Sora技术文档引用文献汇总
  • [ComfyUI进阶教程] animatediff视频提示词书写要点