阅读更多
1 处理器状态(模式)
1.1 处理器和寄存器
处理器由运算器、控制器、一系列的寄存器以及高速缓存构成
其中寄存器可分为以下两种
- 用户可见寄存器:高级语言编译器通过优化算法分配并使用之,以减少程序访问内存次数
- 控制和状态寄存器:用于控制处理器的操作,通常由操作系统代码使用
- 用于控制处理器的操作
- 在某种特权级别下可以访问、修改
常见的控制和状态寄存器
- 程序计数器(PC:Program Counter),记录将要取出的指令的地址
- 指令寄存器(IR:Instruction Register),记录最近取出的指令
- 程序状态字(PSW:Program Status Word),记录处理器的运行状态如条件码、模式、控制位等信息
1.2 CPU状态
为什么要设置多个不同的处理器状态?
- 操作系统为了实现保护与控制
为了让CPU具有不同的状态,需要硬件提供基本运行机制:
- 处理器具有特权级别,能在不同的特权级运行的不同指令集合
- 硬件机制可将OS与用户程序隔离
现代处理器通常将CPU状态设计划分为两种、三种或四种。在程序状态字寄存器PSW中专门设置一位,根据运行程序对资源和指令的使用权限而设置不同的CPU状态
操作系统需要两种CPU状态
- 内核态(Kernel Mode):运行操作系统程序
- 用户态(User Mode):运行用户程序
特权指令和非特权指令
- 特权(privilege)指令:只能由操作系统使用、用户程序不能使用的指令
- 启动I/O
- 内存清零
- 修改程序状态字
- 设置时钟
- 允许/禁止中断
- 停机
- 非特权指令:用户程序可以使用的指令
- 控制转移
- 算术运算
- 访管指令
- 取数指令
X86支持4个处理器特权级别。如下图所示,特权环:R0、R1、R2和R3
- 从R0到R3,特权能力由高到低
- R0相当于内核态;R3相当于用户态;R1和R2则介于两者之间
- 不同级别能够运行的指令集合不同
- 目前大多数基于x86处理器的操作系统只用了R0和R3两个特权级别
1.3 CPU状态之间的转换
CPU状态之间的转换
- 用户态 → 内核态:唯一途径 → 中断/异常/陷入机制
- 内核态 → 用户态:设置程序状态字PSW
从用户态陷入内核态涉及到一种特殊的指令,陷入指令(又称访管指令,因为内核态也被称为supervisor mode)。该指令提供给用户程序的接口,用于调用操作系统的功能(服务)。例如:int,trap,syscall,sysenter/sysexit
2 中断与异常机制简介
中断/异常机制是操作系统的核心机制。可以说,操作系统是由“中断驱动”或者“事件驱动”的,其主要作用如下
- 及时处理设备发来的中断请求
- 可使OS捕获用户程序提出的服务请求
- 防止用户程序执行过程中的破坏性活动
- 等等
2.1 中断与异常的概念
中断与异常是CPU对系统发生的某个事件作出的一种反应:CPU暂停正在执行的程序,保留现场后自动转去执行相应事件的处理程序,处理完成后返回断点,继续执行被打断的程序
- 事件的发生改变了处理器的控制流
- 特点:是随机发生的、是自动处理的、是可恢复的
2.2 为什么引入中断与异常
中断的引入:为了支持CPU和设备之间的并行操作
- 当CPU启动设备进行输入/输出后,设备便可以独立工作,CPU转去处理与此次输入/输出不相关的事情;当设备完成输入/输出后,通过向CPU发中断报告此次输入/输出的结果,让CPU决定如何处理以后的事情
异常的引入:表示CPU执行指令时本身出现的问题
- 如算术溢出、除零、取数时的奇偶错,访存地址时越界或执行了“陷入指令”等,这时硬件改变了CPU当前的执行流程,转到相应的错误处理程序或异常处理程序或执行系统调用
2.3 中断与异常的区别
中断与异常本质上来说都是事件,都会改变处理器的控制流。但根据产生原因的不同将其分为中断与异常,其中
- 中断(外中断):外部事件,正在运行的程序所不期望的
- IO中断
- 时钟中断
- 硬件异常
- 异常(内中断):由正在执行的指令引发
- 系统调用
- 页故障/页错误
- 保护性异常
- 断点指令
- 其他程序性异常(如算术溢出等)
类别 | 原因 | 异步/同步 | 返回行为 |
---|---|---|---|
中断Interrupt | 来自I/O设备、其他硬件部件 | 异步 | 总是返回到下一条指令 |
陷入Trap | 有意识安排的 | 同步 | 返回到下一条指令 |
故障Fault | 可恢复的错误 | 同步 | 返回到当前指令 |
终止Abort | 不可恢复的错误 | 同步 | 不会返回 |
3 中断异常机制工作原理
中断/异常机制是现代计算机系统的核心机制之一,通过硬件和软件相互配合而使计算机系统得以充分发挥能力
- 硬件该做什么事? —— 中断/异常响应:捕获中断源发出的中断/异常请求,以一定方式响应,将处理器控制权交给特定的处理程序
- 软件要做什么事? —— 中断/异常处理程序:识别中断/异常类型并完成相应的处理
3.1 中断响应
中断响应包括发现中断、接收中断的过程,由中断硬件部件完成,处理器控制部件中设有中断寄存器
中断总是在一条指令执行完毕后得到响应(如果允许中断的话)。见如下示意图
上图中提到了中断向量表这一概念,中断向量表是由一系列中断向量构成的数据表,而中断向量是一个内存单元,存放中断处理程序入口地址和程序运行时所需的处理机状态字,如下图所示
- 执行流程按中断号/异常类型的不同,通过中断向量表转移控制权给中断处理程序
下面给出Linux操作系统中的中断向量表
向量范围 | 用途 |
---|---|
0~19 | 不可屏蔽中断和异常 |
20~31 | Intel保留 |
32~127 | 外部中断(IRQ) |
128(0x80) | 用于系统调用的可编程异常 |
129~238 | 外部中断 |
239 | 本地APIC时钟中断 |
240 | 本地APIC高温中断 |
241~250 | Linux保留 |
251~253 | 处理器间中断 |
254 | 本地APIC错误中断 |
255 | 本地APIC伪中断 |
其中,常见的不可屏蔽中断有
- 0 – 除零
- 1 – 单步调试
- 4 – 算术溢出
- 6 --非法操作数
- 12 – 栈异常
- 13 – 保护性错误
- 14 – 缺页异常
中断响应过程,见如下示意图
- 设备发中断信号
- 硬件保存现场
- 根据中断码查表
- 把中断处理程序入口地址等推送到相应的寄存器
- 执行中断处理程序
3.2 中断处理程序
设计操作系统时,为每一类中断/异常事件编好相应的处理程序,并设置好中断向量表
系统运行时若响应中断,中断硬件部件将CPU控制权转给中断处理程序
- 保存相关寄存器信息
- 分析中断/异常的具体原因
- 执行对应的处理功能
- 恢复现场,返回被事件打断的程序
4 中断异常机制实例
待补充
5 系统调用机制
什么是系统调用
- 用户在编程时可以调用的操作系统功能
系统调用的作用
- 系统调用是操作系统提供给编程人员的唯一接口
- 使CPU状态从用户态陷入内核态
系统调用的典型例子
- 每个操作系统都提供几百种系统调用(进程控制、进程通信、文件使用、目录操作、设备管理、信息维护等)
5.1 系统调用的设计
系统调用由以下几个部分构成
- 中断/异常机制:支持系统调用服务的实现
- 选择一条特殊指令:陷入指令(亦称访管指令):引发异常,完成用户态到内核态的切换
- 系统调用号和参数:每个系统调用都事先给定一个编号(功能号)
- 系统调用表:存放系统调用服务例程的入口地址
如何传递系统调用号和参数呢?有下面三种方式
- 由陷入指令自带参数:陷入指令的长度有限,且还要携带系统调用功能号,只能自带有限的参数
- 通过通用寄存器传递参数:这些寄存器是操作系统和用户程序都能访问的,但寄存器的个数会限制传递参数的数量
- 在内存中开辟专用堆栈区来传递参数
5.2 系统调用执行过程
当CPU执行到特殊的陷入指令时:
- 中断/异常机制:硬件保护现场;通过查中断向量表把控制权转给系统调用总入口程序
- 系统调用总入口程序:保存现场;将参数保存在内核堆栈里;通过查系统调用表把控制权转给相应的系统调用处理例程或内核函数
- 执行系统调用例程
- 恢复现场,返回用户程序
6 参考
- 《MOOC-操作系统原理-陈向群》