(8).本章小结
1.5_中断和异常
(1).中断机制的诞生
早期的计算机,各程序只能串行执行,系统资源利用率低。
也就是: 一个个执行,这个执行完毕之后下面的才能继续执行。
为了解决上面的问题:
人们发明了操作系统(作为计算机的管理者),引入中断机制,实现了多道程序并发执行。
本质: 发生中断就以为着需要操作系统介入(不停变态->用户态和核心态
),开展管理工作。
(2).中断的概念和作用
1.当中断发生时,CPU立即进入核心态
2.当中断发生后,当前运行的进程暂停运行,并由操作系统内核对中断进行处理。
3.对于不同的中断信号,会进行不同的处理。
发生了中断,就意味着需要操作系统接入,开展管理工作。由于操作系统的管理工作(比如: 进程进程切换、分配I/O设备等)需要使用特权指令,因此CPU要从用户态转换为核心态。中断可以使用CPU从用户态切换为核心态,使操作系统获得计算机的控制权。有了中断,才能实现多道程序并发执行。
用户态->核心态 就是通过中断实现的。并且中断是唯一途径
核心态->用户态 的切换时通过一个特权指令,将程序状态字(PSW)的标志位设置为"用户态"
(3).中断的类型
内中断的例子
例子1:试图在用户态下执行特权指令
例子2:执行除法指令时发现除数为0
总之若当前执行的指令本身或者指令的一些参数是非法的,则会引发一个中断信号
例子3:有时候应用程序想请求操作系统内核的服务,此时会执行一条特殊的指令陷入指令,该指令会引发一个内部中断信号。执行“陷入指令”,意味着应用程序主动地将CPU控制权还给操作系统内核。“系统调用”就是通过陷入指令完成的
注意陷入指令并不是特权指令。因为这个程序是运行在用户态的,而在用户态下可以执行的指令不可能是特权指令
外中断的例子
例子1:时钟中断,由时钟部件发来的中断信号
例子2:I/O中断,由输入/输出设备发来的中断信号
时钟部件每隔一个时间片(如50ms)会给CPU发送一个时钟中断信号。通过时钟中断信号就可以实现多道程序并发运行了。当某应用程序执行了几条指令后,时钟部件发现此时已经过了50ms,它会给CPU发送一个中断信号(注意这个中断信号和当前执行的指令是没有关系的,它来自CPU的外部)。然后根据我们之前学习的知识,CPU检测到该信号后会先暂停此时正在运行的应用程序,然后转而执行一个相应的内核程序来处理这个中断信号。所以接下来CPU会对时钟中断信号进行处理,并且转为内核态。在内核态下CPU开始执行内核程序来处理刚才收到的中断信号,这个内核程序执行的过程当中发现该应用程序已经用了50ms的时间,应该让下一个应用程序上CPU运行。于是接下来这个内核程序会把CPU的使用权给下一个应用程序,接下来又会切换回用户态,然后下一个程序上CPU运行。之后的过程都是类似的,通过这个例子可以看出应用程序是如何在中断机制的支持下一直不断地切换来实现并发运行的,以及中断在现代计算机中到底有多大的作用。
除了时钟发出的中断信号之外,有时候还会有来自I/O设备的中断信号。比如说某个应用程序可能会请求打印机的打印服务,打印机在打印输出完成之后会向CPU发出中断信号用来通知CPU任务完成。接下来CPU会用中断信号相对应的内核程序来对中断信号进行处理。
每一条指令执行结束时,CPU都会例行检查是否有外中断信号
(4).中断机制的基本原理
不同的中断信号,需要用不同的中断处理程序来处理。当CPU检测到中断信号后,会根据中断信号以此来找到相应的中断处理程序在内存中的存放位置。的类型去查询“中断向量表
1.6_系统调用
(1).什么是系统调用,有何作用?
操作系统作为用户和计算机硬件之间的接口,需要向上提供一些简单易用的服务。主要包括命令接口(用户)和程序接口(程序)。其中,程序接口由一组系统调用
组成。
“系统调用
”是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以通过系统调用来请求获得操作系统内核的服务
(2).系统调用与库函数的区别
其实我们在写程序的时候可以用汇编语言的方式来直接请求系统调用服务的,但是现在的编程更多地是使用高级语言来编程,所以我们一般会直接使用高级语言的库函数,但是这些高级语言的库函数在底层其实也会用到操作系统提供的系统调用功能来请求操作系统的服务。所以系统调用应该是比高级语言的库函数更为底层的接口。
我们的裸机之上是操作系统,操作系统向上层提供的接口是系统调用,使上面的库函数和应用程序能够通过系统调用的方式来请求操作系统的内核的服务。然后在操作系统之上各种各样的高级编程语言会用库函数的方式来封装这些系统调用,然后向更上层的应用程序的程序员来暴露一些更好用的编程接口。
不过也并不是所有的库函数都会使用系统调用
(3).为什么系统调用是必须的?
通过系统调用来实现并发进程对共享资源的互斥访问
由操作系统内核对共享资源进行统一的管理,并向上提供“系统调用”,用户进程想要使用打印机这种共享资源,只能通过系统调用向操作系统内核发出请求。内核会对各个请求进行协调处理。
(4).什么功能要用到系统调用?
应用程序通过系统调用请求操作系统的服务。而系统中的各种共享资源都由操作系统内核统一掌管,因此凡是与共享资源有关的操作(如存储分配、/操作、文件管理等),都必须通过系统调用的方式向操作系统内核提出服务请求,由操作系统内核代为完成
。这样可以保证系统的稳定性和安全性,防止用户进行非法操作。
(5).系统调用的过程
假设一个应用程序想要进行系统调用,它在背后需要做什么事情呢?
现有一个应用程序运行在用户态,然后这个应用程序的各个指令会被CPU依次执行。当它想要发出系统调用的时候,他需要用传参数的指令给CPU的寄存器当中传递一些必要的参数,比如说在某一个寄存器中放入了参数1,这个参数1是指明了此次要进行哪种类型的系统调用,比如说像Linux里的“folk”系统调用。传递参数的指令可能要有多条,主要看我们的系统调用需要传递几个参数。操作系统会根据应用程序提供的这些参数来判断它想要的到底是哪种服务,当这些参数都放入了寄存器之后,应用程序就会执行一条特殊的指令叫陷入指令,该指令会引发一个内中断,CPU在检测到这个内部中断信号之后,它发现这个内部中断信号是由陷入指令引起的,于是这个CPU接下来就会暂停运行这个应用程序,转而去执行处理陷入指令的那个处理程序,这个程序就是系统调用入口程序。显然接下来要执行的程序肯定是属于内核程序,因此它需要在内核态下运行,我们也可以说这个程序也是某一种中断处理程序,只不过它处理的是由陷入指令引发的那个内中断。接下来系统调用入口程序会检查寄存器里的参数,通过第一个参数它会知道此时这个应用程序想要的是这种类型的系统调用服务,于是接下来入口程序就会调用与特定的系统调用类型所对应的处理程序,然后让这个程序上CPU运行。那这个系统调用处理程序在执行的时候就可以根据应用程序传递的其他参数来看一下它所需要的具体是哪些服务。当系统调用被处理完之后CPU又会转回用户态,然后接着执行之前的那个应用程序。
执行了陷入指令之后就意味着这个应用程序把CPU的控制权主动交还给了操作系统的内核,用这样的方式来请求操作系统的服务,注意它并不是特权指令。
陷入指令是唯一一个只能再用户态执行,而不可在核心态执行的命令。