2.操作系统的启动、中断、异常和系统调用

  • 启动
(1)计算机体系结构概述
(2)计算机内存和硬盘布局
(3)开机顺序
  • 中断、异常和系统调用
(1)背景
(2)中断、异常和系统调用相比较
(3)系统调用的概念
(4)系统调用的实现
(5)程序调用与系统调用的不同之处
(6)开销

2.1 操作系统的启动

2.操作系统的启动、中断、异常和系统调用
DISK:存放OS
BIOS:基本I/O处理系统
Bootloader:加载OS
2.操作系统的启动、中断、异常和系统调用
BIOS需要从一个特定的地址开始执行,以x86的地址来看是一个固定的地址, 上电之后将会从这个地址来执行,执行一些列的工作包括(自检:寻找显卡和执行BIOS)。
2.操作系统的启动、中断、异常和系统调用
BIOS是如何把Bootloader放进去的?
Bootloader是放在硬盘上的,一般放在硬盘的第一个主引导扇区(512个字节)。BIOS加载Bootloader,bootloader再负责加载OS。
BIOS将Bootloader从硬盘的引导扇区(512字节)加载到0x7c00,跳转到CS:IP = 0x7C00。
Bootloader将操作系统的代码和数据从硬盘加载到内存中,跳转到操作系统的起始地址。


操作系统与设备和程序的交互
操作系统的interface:系统调用、异常和中断

定义:
  •  系统调用(来源于应用程序):应用程序主动向操作系统发出服务请求
  • 异常(来源于不良的应用程序):非法指令或者其它坏的处理状态(如内存出错)
  • 中断(来源于外设):来自不同的硬件设备的计时器和网络的中断
在计算机的运行中,内核是被信任的第三方,只有内核可以执行特权指令,为了方便应用程序。

操作系统如何设计和实现中断、异常和系统调用?
它们三者有什么区别和特点?
2.操作系统的启动、中断、异常和系统调用
源头:
  • 中断:外设
  • 异常:应用程序意想不到的行为
  • 系统调用:应用程序请求操作提供服务

处理时间
  • 中断:异步。异步就是说,当这个事件产生的时候,我们的应用程序并不知道这个事件什么时候会产生,这就是异步。
  • 异常:同步
  • 系统调用:同步或异步

响应:
  • 中断:持续,对用户应用程序是透明的
  • 异常:杀死或者重新执行意想不到的应用程序指令
  • 系统调用:等待和持续

2.2 操作系统的中断、异常和系统调用

中断和异常处理机制:
  • 中断是外设的事件
  • 异常是内部CPU的事件
  • 中断和异常迫使CPU访问一些被中断和异常服务访问的功能

硬件:设置中断标记(CPU初始化)
(1)将内部、外部事件设置中断标记
(2)中断事件的ID

软件:
(1)保存当前处理状态
(2)中断服务程序处理
(3)清除中断标记
(4)恢复之前保存的处理状态

异常:异常编号
  • 保存现场
  • 异常处理:杀死产生了异常的程序;重新执行异常指令
  • 恢复现场


系统调用

标准C库例子:应用程序调用printf()时,会触发系统调用write()

程序访问主要是通过高层次的API接口而不是直接进行系统调用

Win32 API用于Windows
POSIX API用于POSIX-based system(包括UNIX,LINUX,Mac OS X的所有版本)
Java API用于JAVA虚拟机(JVM)

  • 通常情况下,与每个系统调用相关的序号:系统调用接口根据这些序号来维护表的索引
  • 系统调用接口调用内核态中预期的系统调用,并返回系统调用的状态和其他任何返回值
  • 用户不需要知道系统调用是如何实现的,只需要获取API和了解操作系统将什么作为返回结果,操作系统接口的细节大部分都隐藏再API中,通过运行程序支持的库来管理(用包含编译器的库来创建函数集)

系统调用和函数调用的区别:
当应用程序进行函数调用时,其实是在一个栈空间完成了一个函数的参数的传递,参数的返回。系统调用的执行过程中, 应用程序和操作系统的内核拥有各自的堆栈,意味着,当应用程序发出系统调用之后,切换到内核中去执行的时候,需要去切换堆栈,需要完成特权级的转换(从用户态到内核态的转换),这个转换和堆栈的转换都需要开销,这意味着,执行系统调用的开销会比函数调用大很多,这个开销是有回报的,回报是安全可靠,这是操作系统不得不付出的时间上的代价。

跨越操作系统边界的开销
  • 在执行时间上的开销超过系统调用
  • 开销
(1)建立/中断/异常/系统调用号与对应服务例程映射关系的初始化开销
(2)建立内核堆栈
(3)验证参数
(4)内核态映射到用户态的地址空间更新页面映射权限
(5)内核态独立地址空间 TLB