2 启动、中断和系统调用
启动
- 启动BIOS,从内存特定地址开始执行(CS段寄存器:IP指令指针寄存器 0xf000:fff0),检测各类外设(开机自检),从特定地址将bootloader加载到内存
- OS存放在Disk上
- bootloader一般存放在Disk的第一个主引导扇区(512个字节)。bootloader将OS从硬盘放到内存中去
以x86为例:
- BIOS将Bootloader从Disk引导扇区(512bytes)加载到内存0x7c00,跳转到CS:IP = 0000:7c00
- Bootloader将OS代码和数据从Disk加载到内存中,并跳转到到OS的真实地址
OS与设备、应用程序的交互
- 3个接口(系统调用、异常、中断):
- 面向外设:通过中断和IO
- 面向应用程序:通过系统调用和异常
- 定义:
- 系统调用(from app):应用程序主动向操作系统发出服务请求
- 异常(from bad app):非法指令或其他坏的处理状态
- 中断(from peripherals):来自不同的硬件设备的计时器和网络中断
- OS存在的意义:
- 计算机运行中,kernel是被信任的第三方,只有kernel可以执行特权指令(避免恶意软件获得特权)
- OS为应用程序提供统一的接口,使应用程序不用关注底层的具体硬件
中断、异常、系统调用的区别
- 源头:
- 中断:外设产生(如鼠标点击)
- 异常:应用程序意外产生
- 系统调用:应用程序主动向OS请求服务
- 处理时间:
- 中断:异步(app执行到任意指令时都有可能发生)
- 异常:同步(app执行到某一条指令)
- 系统调用:同步(app执行到某一条指令时发起),但返回消息的时间点可能是异步的(OS完成系统调用任务时,app没有等待OS响应,先切换到其他任务)
- 响应:
- 中断: 持续,对用户应用程序是透明的
- 异常: 杀死进程, 或OS(自动做出调整后)重新执行出现异常处的应用程序指令
- 系统调用: 等待和持续
中断、异常、系统调用的过程:
中断
- 硬件:
- 对内部、外部事件设置中断标记[CPU初始化]
- CPU将中断事件ID传递给OS,OS根据中断号交相应的例程处理
- 软件:
- 保持现场(当前处理状态,如中断位置、寄存器等)
- 中断服务程序(例程)处理
- 中断结束,清除中断标记
异常
- 保持现场(异常位置、寄存器等)
- 异常处理
- kill异常程序
- OS自身调整后,重新执行异常指令
- 恢复现场
系统调用
- 程序访问主要通过高层次API接口而非直接进行系统调用
- Win32(Windows系统)
- Posix(Unix、linux、macOS)
- Java的API(不是真的系统调用,而是虚拟机JVM的API)
- 完成用户态到内核态的转化
- 用户态权限低,无法执行系统特权指令
- 内核态权限高,能够执行所有特权指令
- 系统调用与函数调用区别
- 函数调用:在一个存储空间、堆栈中完成函数参数传递和返回
- 系统调用:OS和应用程序有各自的堆栈,数据传递需要额外的开销
跨越系统边界的开销
- 执行时间上的开销超过一般的函数调用
- 开销
- 建立中断/异常/系统调用号与对应服务例程映射关系的初始化开销
- 建立内核堆栈
- OS不信任应用程序,需要验证参数
- 内核态映射到用户态的地址空间,如更新页面映射权限
- 内核态独立地址空间 TLB