课程来源《操作系统_清华大学(向勇、陈渝)》
还参考了文章:
1.操作系统的启动
启动:
- 计算机体系结构概述
- 计算机内存和硬盘布局
- 开机顺序
中断、异常和系统调用:
- 背景
- 中断、异常和系统调用相比较
- 中断和异常处理机制
- 系统调用的概念
- 系统调用的实现
- 程序调用与系统调用的不同之处
- 开销
DISK:存放OS
BIOS:基本I/O处理系统
最初的时候,OS并不是存放在内存中,OS存放在DISK硬盘中,通过BIOS提供支持,BISO监测各种各样外设,加载相应的软件进行执行,所以可以加载Bootloader,Bootloader负责加载OS,让OS从硬盘放到内存中去,CPU执行操作系统。
BIOS需要从一个特定地址执行,CS:IP = 0xf000:fff0(CS:段寄存器;IP:指令寄存器),完成接下来一系列工作,比如加电自检(POST)等。
BIOS作用:
1.将Bootloader从磁盘的引导扇区(512字节)加载到0x7c00
2.跳到CS:IP=0000:7c00
Bootloader作用:
1.将操作系统的代码和数据从硬盘加载到内存中
2.跳转到操作系统的起始位置(CPU控制权就交到了OS上)
3.OS就可以在内存中进行些必要的工作了(这时候计算机的管理是处在OS之下了)
更详细关于BIOS介绍:
BIOS(basic input/output system,基本输入输出系统)是一组被固化到电脑中,为电脑提供最低级、最直接的硬件控制的程序,它是连接软件程序和硬件设备的枢纽。
BIOS存在目的:检测硬件、初始化硬件、分配资源(如IO地址、IRQ号、DMA通道等)以及协助加载操作系统。
它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、系统设置信息、开机上电自检程序和系统启动自举程序。 其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。
系统激活流程为:打开电源开关—CPU初始化—BIOS激活—读取并校验CMOS资料、检测硬件状态(此时BIOS代码在flash memo中运行)—生成SMBIOS表格—检测、配置并初始化各硬件—加载bootloader 。
2.操作系统的中断、异常、和系统调用
操作系统与设备和程序交互:
1.面向外设是通过I/O和中断
2.面向应用程序是通过系统调用和异常
系统调用(来源于应用程序):应用程序主动向操作系统发出服务请求
异常(来源于不良的应用程序):非法指令或者其他坏的处理状态(如:内存出错)
中断(来源于外设):来自不同的硬件设备的计时器和网络的中断
为什么应用程序不能直接访问外设呢?
1.在计算机运行中,内核是被信任的第三方(外设,应用程序不可信任)
2.只有内核可以执行特权指令
3.为了方便应用程序(通过OS给应用程序提供一个统一的接口,屏蔽外设device的不同,让应用程序通用、可移植)
操作系统如何设计和实现中断(interupt)、异常(exception)和系统调用(system call),它们三者有什么区别和特点?
1.源头不一样:
中断:外设,网卡声卡显卡等等产生事件
异常:应用程序意想不到的行为
系统调用:应用程序请求操作提供服务
2.处理时间不一样:
中断:异步;
异常:同步;
系统调用:同步或异步
异步的含义:当一个事件发生时,APP并不知道它什么时候会发生
异常和系统调用都是一个特定指令触发了事件,同步时间点。
系统调用也有可能异步,当发出请求后返回的时间是异步的。如果APP在发出请求后没有等待,而是干别的去了,返回点是异步的。而请求的点是同步的。
如两个人聊天,如果是打电话那就是同步(因为两个人必须同时在电话旁),而发短信就像异步,我发给你我就不管了,等你看到了在回我,即不同步(异步),异步是相对于同步来说的。
注意:一个是进程执行的同步和异步,一个是通信里的同步和异步,两个不一样
3.响应状态不一样:
中断:持续,app对用户是透明的,感觉不到
异常:杀死或重新执行APP的异常指令,也透明
系统调用:等待和持续,不会重复执行
中断和异常的处理机制 :
中断—-
硬件:设置中断标记(cpu初始化),CPU看到具体的中断事件的ID中断号(程序访问的中断向量地址),根据中断表,访问一些为该事件服务的功能,跳到对应地址。
软件:OS要保存当前程序处理状态,中断服务程序处理(根据具体的时间ID对应功能/地址),清除中断标记,恢复之前保存的处理状态(应用程序是不知道的,是透明的)
异常——
异常编号,OS会保存现场,异常处理(杀死程序or OS修复程序需要的服务后重新执行异常指令),恢复现场。应用程序不知道在执行到特定指令后会产生异常,也是透明的。
系统调用——
应用程序调用printf时会触发系统调用write(),OS再去访问对应的外设。执行后OS返回一个成功或者失败。程序访问主要是通过高层的API接口而不是直接系统调用。
程序访问主要是通过高层的API接口而不是直接系统调用。常用的有:
Win32 API
POSIX API 通用可移植 linux unix mac os x
最底层就是win32 or posix 定义了操作系统到底能提供哪些系统调用
JAVA API 用于JAVA虚拟机(JVM)
OS是怎么设计和实现系统调用的?
通常,系统调用接口根据与每个系统调用相关的序号维护一个索引表;系统调用接口调用内核态中预期的系统调用,并return状态和other values,用户不需要知道具体实现,只要获取API和了解return 结果,接口的细节都隐藏在API中,通过APP所支持的库来管理(用包含编译器的库来创建函数集)。
APP直接或间接通过library code库访问系统调用的接口,并触发内核态到用户态的转变,控制权从应用程序交到了OS,OS标识ID号后完成具体的服务。
内核态:OS运行中,CPU处的高权限的状态,OS可以执行任何CPU提供的任何指令或调用I/O。
用户态:APP执行中,CPU处的一个较低权限的状态。不能直接访问特殊的机器指令和I/O
系统调用与传统的函数调用区别在两点:
APP发出函数调用时,在一个栈空间完成了函数的传参和返回,系统调用时,应用程序和OS内核各自拥有堆栈,有栈的堆栈和特权级的转换,需要开销,大于函数调用。但相对更安全可靠。
三种行为(中断、异常、系统调用)跨越了OS边界。执行时间上开销超过直接程序调用。开销包括:
- 初始环节要对事件ID号与对应服务历程建立映射表
- OS有自己的堆栈,要建立和维护内核堆栈(保存,恢复)
- 操作系统不信任APP,有验证参数,检查的过程
- 从内核态映射到用户态的地址空间,如果引起内存变化,更新页面映射权限,
- 内核态独立地址空间 TLB