操作系统的启动
- CPU, I/O, 内存通过总线连接。
- DISK: 存放OS;
BIOS:基本I/O处理系统( basic I/O system); Bootloader: 加载OS到内存中。- 当电脑通电时,段寄存器CS和指令寄存器IP能够确定一个内存地址,例如CS:IP = 0xf000:fff0.
- POST(加电自检),寻找显卡和执行BIOS。(显示器,键盘…是否正常)。
- 步骤:
- BIOS: 将Bootloader从磁盘的磁盘的引导扇区(512字节)加载到0x7c00;跳转到CS:IP=0000:7c00的内存区域(以便下一步)
- Bootloader:将操作系统的代码和数据从硬盘加载到内存中;跳转到操作系统的起始地址。
- 系统调用:应用程序主动向操作系统发出服务请求
- 异常:非法指令或者其它坏的处理状态,如:内存出错
- 中断:来自不同硬件设备的计时器和网络中断。
为什么应用程序需要通过操作系统才能访问硬件
- 因为计算机运行时,内核才是被信任的第三方,只有内核才能执行特权指令
- 另一方面,应用程序无法和硬件底层打交道,就可以简化操作
操作系统如何设计和实现中断/异常和系统调用;他们三者的区别和特点。
- 产生的源头
- 中断: 由外设产生,例如键盘的输入
- 异常: 应用程序在运行时,发生的意想不到的行为
- 系统调用: 应用程序请求操作系统提供服务
- 处理时间
- 中断: 异步,就是不知道什么时候会发生
- 异常:同步,在运行到某一行程序,一定会发生的
- 系统调用: 同步/异步,同步是指应用程序发起请求的行为是可预见的,异步是指操作系统何时完成的时间不可知。
- 响应
- 中断: 持续的,对于应用程序而言是透明的,也就是感受不到发生了中断
- 异常: 会导致该应用程序被杀死,或者重新执行(可能是运行环境的问题,会重试)
- 系统调用: 等待和持续
中断/异常和系统调用
- 中断和异常处理机制:中断是外设的时间,异常时CPU的事件。二者都会使得CPU被迫访问中断和异常服务。
- 中断处理机制
- 硬件设置中断标志位、将内部事件/外部事件设置中断标记、中断事件的id(程序访问的中断向量地址)
- 软件(操作系统):保存当前的处理状态、中断服务程序处理、清除中断标记、恢复至之前保存的处理状态
- 异常处理机制
- 保护现场
- 异常处理:杀死应用程序或重新执行
- 恢复现场
1. 系统调用
- 一条指令会触发一个系统调用
- 程序的访问主要是通过高层次的接口,而非直接进行系统调用
- 通常情况下,存在于每个系统调用相关的序号,系统调用接口根据这些序号来维护表的索引
- 系统调用接口调用内核态中预期的系统调用,并返回系统调用的状态和其它任何返回值
- 用户不需要知道系统调用是如何实现的,只需要获取API和了解操作新系统将什么作为返回结果。操作系统接口的细节大部分都隐藏在API中,并通过运行程序支持的库来管理
- 用户态:应用程序在执行的过程中,CPU执行的特权级的状态(很低,不能访问特殊机器指令和IO)。
- 内核态:应用程序在执行的过程中,CPU执行的特权级的状态(高,操作系统可以执行CPU任何一条指令
- 系统调用时涉及到特权级从用户态到内核态的转换,应用程序和操作系统有各自的堆栈,这两个变化比函数调用的开销更大,但更安全和可靠。(而程序调用是在一个栈空间实现参数的调用和返回)。
在跨越操作系统边界带来的开销
- 建立中断/异常/系统调用号与对应服务例程映射关系的初始化开销;
- 建立内核堆栈(操作系统和应用程序的堆栈不一样);
- 验证参数(操作系统会检查数据);
- 内核态映射到用户态的地址空间,更新页面映射权限(内存拷贝开销);
- 内核态独立地址空间TLB。