处理器
CPU 是由运算器、控制器、 一系列的寄存器以及高速缓存Cache构成。
- 两类寄存器:
- 一类是用户可见寄存器,那么高级语言编译器通过优化算法分配这些寄存器,并且使用这些寄存器,主要的目的是为了减少访问内存的次数,来提高程序的运行效率。
- 一类是是控制和状态寄存器。 这些寄存器呢是用于控制处理器的操作,通常只能由操作系统代码来使用。
常见控制和状态寄存器:
程序计数器(PC program counter),记录将要取出的指令的地址
指令寄存器(IR instruction register),记录最近取出的指令
程序状态字(PSW program status word),记录处理器的运行状态如模式、控制位等信息
操作系统的需求——保护
操作系统的特征:并发、共享,要求保护和控制,用户程序与用户程序之间互不干扰,用户程序不对操作系统干扰。对硬件希望提供这样的一个基本运行机制。 就是CPU具有一个特权级别, 在不同的特权级下可以运行不同的指令集合,达到操作系统和用户程序的隔离。
处理器的状态(模式MODE)
CPU状态分为两种三种或四种,大部分我们所熟知的的操作系统,Linux、Windows、Unix,都是只选择了R0和R3这两个特权级别,程序状态字寄存器PSW中专门设置一位来控制。
操作系统需要两种CPU状态:
-
内核态 管态 kernel mode :运行操作系统程序,可以执行特权指令,比如:控制IO,管理内存,修改状态字,设置时钟,设置中断。
-
用户态 目态 user mode :运行用户程序,只能运行非特权指令,比如:访管指令(陷入指令),算术运算,控制转移,取数指令。
访管指令是一条特殊的指令,是提供给用户程序的借口,用于调用操作系统的功能。
如:int,trap,syscall
两种状态的转换:
- 用户态到内核态:唯一途径就是中断/异常/陷入机制。
- 内核态到用户态:设置PSW。
中断与异常机制的概念
可以说操作系统是“中断驱动”的,可以及时处理各种请求,防止破坏性活动,维持系统可靠正常工作。
中断和异常概念:CPU对系统发生的某个事件的反应。暂停正在执行的程序,保留现场之后执行相应事件的处理程序,处理完成之后返回断点,继续执行被打断的程序。中断支持了CPU与设备之间的并行操作。异常表示CPU执行指令时本身出现的问题,广义的中断包含异常。
中断与异常
- 中断(外中断):就是外部IO设备、其他硬件引发的。分为可屏蔽非可屏蔽,包括I/O中断,存储器校验,时钟中断,硬件故障。总是会返回到下一条指令。
- 异常(内中断):当前执行指令引发的。系统调用、页故障、越界、断点指令、程序性异常
- 故障 Fault:可恢复的错误,返回到下一条指令 除零
- 陷入 Trap:有意识安排的,返回到当前指令,比如断点,陷入指令
- 异常中止 Abort:不可恢复的错误,不会返回
中断与异常机制的工作原理
硬件和软件相互配合,硬件完成响应,软件完成处理。在每一次执行指令之后,处理器扫描中段寄存器,如果有中断信号,中断硬件将中断触发器内容按规定编码送入PSW的相应位,成为中断码,硬件通过查中断向量表引出中断处理程序。去执行中断处理程序。
中断向量表是一个软硬结合的数据结构
中断向量就是一个内存单元 存放中断处理程序的入口地址程序和程序状态字
中断/异常机制(软件提前设置好 硬件部件来执行)
-
给CPU发中断信号(硬件)
-
CPU处理完当前指令后,扫描检测到中断,判断出中断来源并向相关设备发送确认信号(硬件)
-
CPU开始为软件处理中断做准备:将状态切换到内核态,将重要的寄存器内容存到系统堆栈,主要是指PC,PSW。(硬件)
-
CPU根据中断码来查询中断向量表,获得中断处理程序入口地址,并将PC设置成该地址,新的指令周期开始时,CPU控制转移到中断处理程序。(硬件)
-
中断处理程序开始工作,保存不那么关键的寄存器的信息,在系统堆栈中保存现场信息等比较具体的工作。(软件)
//若I/O操作出现错误,重复执行操作,达到上限次数之后,判定硬件故障。
-
中断处理结束,CPU监测到中断返回指令,恢复到中断前的状态。(硬件)
系统调用机制
系统调用:用户在编程时可以调用的操作系统功能,是操作系统提供给编程人员的唯一接口,使CPU状态从用户态陷入内核态
区分系统调用、库函数、API、内核函数
- 应用程序可以直接调系统调用,但是通常情况下应用程序都是通过了库函数或者是API的接口来间接地调用系统调用
- 那么在操作系统内核当中,提供了很多的内核函数,这些内核函数经过封装实际上呢把它提供到了库函数或者是API接口
- 内核函数就是系统调用的处理程序
- 库函数有可能包含有一个系统调用,有可能有好几个系统调用,当然也有可能没有系统调用,也有些操作不需要涉及内核的功能。
- 库函数调用是语言或应用程序的一部分,而系统调用是操作系统的一部分。
- 从应用程序的使用角度看,库函数与系统调用没有差别;但从实现的角度看,两种有重大差别。
系统调用机制的设计
-
中断/异常机制
支持系统调用服务的实现
-
选择一条特殊指令:访管指令
引发异常,切换到内核态(软中断)
-
系统调用号和参数
每个系统调用都事先给定一个编号,传输传递的实现一般由通用寄存器传递参数,但是参数个数有限。还可以用陷入指令自带参数或是在内存中开辟堆栈传递参数
-
系统调用表
存放系统调用服务例程的入口地址
系统调用举例
c代码
write(1,string,7);
return 0;
汇编语言
mov $4, %eax #eax存放系统调用号
mov $1, %ebx #三个参数
mov $output, %ecx
mov $len, %edx
int $0x80 #引发一次系统调用
end:
mov $1, %eax
mov $0, %ebx
int $0x80 #这次调用的作用就是返回
系统调用执行过程
- 中断异常机制:硬件保护现场,查找中断向量表,将控制权转给系统调用总入口程序。
- 系统调用总入口程序:保存现场,将参数保存,利用寄存器查找系统调用入口表,找到这个系统调用的服务历程的入口地址。
- 执行系统调用例程
- 恢复现场,返回用户程序