中断和异常
中断机制的诞生
在早期计算机里,只有一个程序执行完以后,另一个程序才能进行。因此,各个程序只能串行执行,系统利用率很低。
为了解决上述问题,人们发明了操作系统,引入中断机制,实现了多道程序并发执行。
本质:发生中断就意味着需要操作系统进行介入,开展管理工作
那么操作系统又是怎么进行中断这一行为的呢?
首先,进程1会在用户态下执行,cpu会收到操作系统的计时部件发出的中断信号。它会切换成核心态(核心态权限高,能中断) ,它将cpu的使用权限交给操作系统,操作系统内核负责中断信号进行处理。
操作系统之后就会告诉进程,进程1的时间片已经用完,换进程2运行
之后,操作系统会将cpu的使用权交还给用户进程,进城2就会继续执行。
等进程2执行一段时间以后,它想做io操作了,于是它发出系统调用(内中断信号),请求输出。于是,cpu就切换为核心态,对中断进行处理,进行io操作。(因为io操作只能核心态处理)
之后呢,操作系统就乖乖听从进程2的请求,调用打印机,进程2暂停运行,等待I/O操作。
之后呢,操作系统会把用户态还给进程3 。此时打印机是和进程3并行执行的。等打印机操作完成,它会像cpu发送中断信号。
cpu接收到信号之后,又会切换到核心态对中断进行处理了。
总结
- 当中断发生,cpu立刻进入核心态
- 中断发生以后,当前运行的进程暂停运行,并且由操作系统内核对中断进行处理
- 对于不同的中断信号,会有不同的处理
发生了中断就意味着,需要操作系统进行介入,开展管理工作。但是这些管理工作(如进程切换,I/O设备)需要用到特权指令,因此,cpu需要从用户态转变成核心态才行。而中断可以使CPU从用户态转化为核心态,使操作系统获得对计算机的控制权。有了中断,程序才可以并发的执行。
注意:用户态——>核心态是通过中断实现的。而中断是唯一的途径
而 核心态——>用户态则是通过执行一个特权指令,将程序状态字PSW(0和1)的标志位设置为“用户态”。
中断的分类
中断分为两类,分别是内中断和外中断。
内中断也叫异常,例外,陷入。异常我们大伙儿很熟悉,就是程序里面的异常如 i/0 这种,这种中断叫强迫中断。和此种软件中断相并列的还有硬件故障,他也是强迫中断。
和强迫中断对应的则是自愿中断——指令中断,这是通过指令实现的中断。
外中断处理过程
其实对于外中断的处理。cpu是这样做的:
- 在每条指令完成以后,cpu都会检查是否有外部中断信号
- 如果检测到有外部中断信号,那么就需要保护被终端进程的cpu环境(如程序状态字PSW,各种通用寄存器等)
- 根据中断信号类型,转入相应中断处理程序,从用户态到核心态的改变
- 恢复原来的进程的cpu环境,返回原进程继续向下执行
系统调用
知识点回顾:
操作系统作为一个桥梁,需要向上提供简单易用的服务。主要包括,命令接口和程序接口。
我们今天要讲的系统调用,就是在程序接口中提到的。
系统调用是操作系统提供给程序员使用的接口,可以理解为一种可供应用程序调用的特殊函数。应用程序可以发出系统调用请求来获得操作系统的服务
什么是系统调用?有什么作用?
其实,存储分配,I/O操作,文件管理等,都是通过系统调用的方式向操作系统提出服务请求,由操作系统代为完成。这样可以保证用户的稳定性和安全性。防止用户进行非法操作。
像上面这些,设备管理,文件管理,进程控制,进程通信,内存管理的功能,都是需要特权指令才能完成。因此,系统调用的相关处理需要在核心态下进行。
系统调用和库函数的区别
刚刚提到的系统调用是操作系统为了服务于上层的函数。
那么它和java,c语言的库里面的函数又有有什么区别呢?
其实应用程序可以先调用语言的库函数,然后这些库函数,会再调用专门为了系统调用的函数。
注意,系统调用的相关处理在核心态上进行
不涉及系统调用的库函数:比如加减,取绝对值
涉及系统调用的库函数:比如创建新的文件
高级语言代码调用参数 ——> 用户态下汇编语言执行陷入指令 ——> 在核心态下,调用 相应服务程序 ——> 返回用户程序
注意
- 陷入指令是在用户态完成的,执行陷入指令之后,会立刻引发一个内中断,让cpu进入核心态
- 发出系统调用请求是在用户态,而对于系统调用的处理是在核心态下进行的
- 由于核心态可以执行特权指令和非特权指令,而陷入指令是唯一一个只能在用户态下执行,而不可在核心态下执行的指令
核心考点
- 系统调用会让发生内中断,CPU从用户态进入核心态
- 设备管理,文件管理,进程控制,进程通信,内存管理,这些凡是于资源有关的操作,会直接影响到其它进程的操作,一定会需要操作系统进行介入,也就是通过系统调用来实现。
- 系统调用发生在用户态,而对系统调用的处理发生在核心态
- 执行陷入指令会产生内中断,让 用户态进入核心态