第一章 操作系统概述
- 操作系统的作用:1)控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配;2)提供给用户和其他软件方便的接口和环境;3)实现了对计算机资源的抽象,是计算机系统中最基本的系统软件,是最接近硬件的一层软件
- 计算机系统中的资源:可分为4类:处理机、存储器、I/O设备和信息(数据和程序)。OS正是对这4类资源进行有效的管理
- 处理机管理负责处理机的分配与控制
- 存储器管理负责内存的分配与回收
- I/O设备管理负责I/O设备的分配(回收)与操纵
- 文件管理负责文件的存取、共享与保护等
- 错误说法:操作系统是对硬件进行管理的软件:
对于一个完全无软件的计算机系统(即裸机),对用户提供的只有硬件接口。为了方便使用I/O设备,人们在裸机上覆盖了一层I/O设备管理软件(I/O软件),将I/O设备抽象为数据结构以及I/O操作命令(如read, write)。将覆盖了这种软件的I/O设备称为扩充机器或虚拟器。
同时,为了方便用户使用文件系统,又可在第一层软件(I/O软件)之上再覆盖一层用于管理文件的软件,由它来实现对文件操作的细节,并向上提供一组实现对文件进行存取操作的数据结构及命令。用户可用该软件提供的数据结构及命令来对文件进行存取。此时用户看到的是一台功能更强、使用更方便的虚拟器。
因此文件管理软件实现了对硬件资源操作的第二个层次的抽象。如果在文件爱你管理软件上再覆盖一层面向用户的窗口软件,那么用户便可在窗口环境下方便地使用计算机,从而形成一台功能更强的虚机器。
因此,OS是铺设在计算机硬件上的多层软件的集合,不仅增强了系统的功能,还隐藏了对硬件操作的具体细节,实现了对计算机硬件操作的多个层次的抽象模型。一个硬件不仅可以在低层加以抽象,还可在高层对该资源低层已抽象的模型进行再次抽象,从而形成更高层的抽象模型。抽象层次越高,抽象接口所提供的功能就越强,用户使用起来就越方便 - 操作系统向用户提供的接口:有两种
- 命令接口:用户用这些操作命令来组织和控制作业的执行
- 联机命令接口:交互性
- 脱机命令接口:批处理命令接口
- 程序接口:编程人员使用它们来请求操作系统服务。由系统调用(广义指令)组成
- 命令接口:用户用这些操作命令来组织和控制作业的执行
- 操作系统的发展
- 未配置操作系统:
- 人工操作方式:用户将(有程序和数据的)纸带装入纸带输入机,纸带输入机将纸带上的程序和数据输入计算机,计算机运行程序,运行完毕后由用户取走计算结果,然后下一个用户。
- 脱机I/O方式:先将(有程序和数据的)纸带装入纸带输入机,在一台外围机的控制下,把纸带上的程序和数据输入磁带。当CPU需要这些程序和数据时,再从磁带上将它们高速调入内存。当CPU需要输出时,可先由CPU把数据直接从内存高速送到磁带上,然后在另一台外围机的控制下,将磁带上的结果通过相应的输出设备输出。
- “脱机”:由于程序和数据的输入和输出都是在外围机的控制下完成的,即都是脱离主机的情况下完成的,故称为脱机I/O方式
- 减少了CPU的空闲时间:装带、卸带以及将输入从低速I/O设备送到高速磁带上(或反之)的操作,都是在脱机情况下由外围机完成的,并不占用主机时间,因此有效减少了CPU的空闲时间
- 提高I/O速度:当CPU在运行中需要输入数据时,是从高速磁带上将数据输入的
- “脱机”:由于程序和数据的输入和输出都是在外围机的控制下完成的,即都是脱离主机的情况下完成的,故称为脱机I/O方式
- 批处理操作系统
- 单道批处理系统:先把一批作业以脱机I/O方式输入磁带,并在系统中配上监督程序。在其控制下,这批作业能一个接一个被连续处理。
- 多道批处理系统【提高资源利用率和系统吞吐量】:用户所提交的作业首先被放在外存上,并排成一个队列,称为“后备队列”。然后由作业调度程序按一定的算法从后备队列中选择若干个作业调入内存,使他们共享CPU和系统中的各种资源。
- 对于单道批处理系统,同一时刻,内存中只有一道程序;而对于多道批处理系统,同一时刻内存中同时装有若干道程序,这样便可在运行程序A时,利用其因I/O操作而暂停执行的CPU空档时间,再调度另一道程序B运行,进而实现多道程序交替运行,这样便可保持CPU处于忙碌状态
- 分时系统【实现人机交互】:将处理机的运行时间分成很短的时间片,轮流分配给各用户的作业使用。规定时间一到无论作业是否完成计算,都要暂停运行,这样使得多个用户可以同时使用系统。
- 在多道批处理系统中,用户无法与自己的作业进行交互的原因是:作业都先驻留在外存中,即使以后被调入内存,也要经过较长时间的等待方能运行;在此过程中,用户无法与自己的作业进行交互。
- 如何实现人机交互:
- 系统必须能提供多个终端同时给多个用户使用
- 当用户在自己的终端上键入命令时,系统应能及时接收并处理该命令,然后将处理结果返回给用户。此后用户可根据系统的响应情况,再继续键入下一条命令
- 即:允许有多个用户同时通过自己的键盘键入命令,系统也应能将全部命令及时接收并处理
- 及时处理需要:各个用户的作业都必须驻留在内存中,并能频繁地获得处理机运行。否则用户键入的命令将无法作用到自己的作业上。由此可见为了实现人机交互,必须彻底改变原来批处理系统的运行方式,转而采用以下方式
- 采用作业直接进入内存的方式,因为作业在磁盘上是不能运行的,所以其应直接进入内存
- 采用轮转运行的方式:若一个作业独占处理机而连续运行,那么其他作业就没有机会被调度运行。为避免一个作业长期独占处理机,引入了时间片的概念。系统规定每个作业每次只能运行一个时间片,然后就暂停该作业的运行,并立即调度下一个作业运行。若在不长的时间内能使所有的作业都执行一个时间片的时间,则可使每个用户都能及时地与自己的作业进行交互,从而可使用户的请求得到及时响应。
- 实时系统:
- 实时任务的类型:
- 周期性实时任务和非周期性实时任务
- 硬实时任务和软实时任务:硬实时(HRT, hard real time)是系统必须满足任务对截止时间的要求,用于工业控制和武器控制;软实时(SRT, soft real time)任务也联系着一个截止时间,但并不严格,错过了也影响不会太大,如用于信息查询系统和多媒体系统中的实时任务
- 实时系统与分时系统特征的比较:
- 多路性:信息查询系统和分时系统是系统按分时原则为多个终端用户服务;实时控制系统是系统周期性地对多路现场信息进行采集,并对多个对象或多个执行机构进行控制
- 独立性:都表现为每个终端用户在与系统交互时彼此相互独立、互不干扰
- 及时性:实时系统是以控制对象所要求的截止时间来确定的,一般为秒级到毫秒级
- 交互性
- 可靠性:实时系统要求系统高度可靠,因此在实时系统中往往都采取了多级容错措施
- 实时任务的类型:
- 其他操作系统
- 网络操作系统
- 分布式操作系统
- 个人计算机操作系统
- 未配置操作系统:
- 中断相关:
- 计算机通过硬件中断机制完成由用户态到核心态的转换。发生中断事件时(有可能是用户程序发出的系统调用),触发中断,硬件中断机制将计算机状态置为核心态
- 核心态程序只有在操作系统进入核心态后才可以执行
- 中断处理程序一般也在核心态执行,因此无法完成“转换成核心态”这一任务
- 用户程序也不可以将操作系统由用户态转换到核心态,因为如果这样,用户程序中就可以使用核心态指令,会威胁到计算机的安全
- 中断是现代操作系统正常运行的核心保障之一,所以关中断指令是权限非常大的指令,所以一定是特权指令
- 特权指令和非特权指令:
- 常见的非特权指令:存取数、读时钟、加减乘除、寄存器清零、压栈弹栈、跳转、trap(访管)
- 常见的特权指令:开关中断、写时钟、输入输出、写PSW
- 操作系统体系结构汇总(大内核、微内核、分层、模块化、外核)
特性、思想 | 优点 | 缺点 | |
---|---|---|---|
分层结构 | 内核分多层,每层可单向调用更低一层提供的接口 | 1. 便于调试和验证,自底向上逐层调试验证;2. 易扩充和维护,各层之间调用接口清晰固定 | 1. 仅可调用相邻低层,难以合理定义各层的边界;2. 效率低,不可跨层调用,系统调用执行时间长 |
模块化 | 将内核划分为多个模块,各模块之间相互协作(内核=主模块1+可加载内核模块2) | 1. 模块之间逻辑清晰易于维护,确定模块间接口后即可多模块同时开发;2. 支持动态加载新的内核模块(如安装设备驱动程序、安装新的文件系统模块到内核),增强OS适应性;3. 任何模块都可以直接调用其他模块,无需采用消息传递进行通信,效率高 | 1. 模块间接口定义未必合理实用;2. 模块间相互依赖,更难调试和验证 |
宏内核(大内核) | 所有的系统功能都放在内核里(大内核结构的OS通常也采用了“模块化”的设计思想 | 1. 性能高,内核内部各种功能都可以直接相互调用 | 1. 内核庞大功能复杂,难以维护;2. 大内核中某个功能模块出错,就可能导致整个系统崩溃 |
微内核 | 只把中断、原语、进程通信等最核心的功能放入内核。进程管理、文件管理、设备管理等功能以用户进程的形式运行在用户态 | 1. 内核小功能少、易于维护、内核可靠性高;2. 内核外的某个功能模块出错不会导致整个系统崩溃 | 1. 性能低,需要频繁地切换用户态/核心态;2. 用户态下的各功能模块不可以直接相互调用,只能通过内核的“消息传递”来间接通信 |
外核 | 内核负责进程调度、进程通信等功能,外核负责为用户进程分配未经抽象的硬件资源,且由外核负责保证资源使用安全 | 1. 外核可直接给用户进程分配“不虚拟、不抽象”的硬件资源,使用户进程可以更灵活的使用硬件资源;2. 减少了虚拟硬件资源的“映射层”,提升效率 | 1. 降低了系统的一致性;2. 使系统变得更复杂 |
第二章 进程与线程
1. 三种调度联系与对比:
要做什么 | 调度发生在… | 发生频率 | 对进程状态的影响 | |
---|---|---|---|---|
高级调度(作业调度) | 按照某种规则,从后备队列中选择合适的作业将其调入内存,并为其创建进程 | 外存->内存(面向作业) | 最低 | 无->创建态->就绪态 |
中级调度(内存调度) | 按照某种规则,从挂起队列中选择合适的进程将其数据调回内存 | 外存->内存(面向进程) | 中等 | 挂起态->就绪态(阻塞挂起->阻塞态) |
低级调度(进程调度) | 按照某种规则,从就绪队列中选择一个进程为其分配处理机 | 内存->CPU | 最高 | 就绪态->运行态 |
2. 临界相关概念:
- 临界资源:指一个时间段内只允许一个进程使用的资源,各进程需要互斥地访问临界资源。
- 临界区:指访问临界资源的那段代码。因此各个进程肯定也只能互斥地进入临界区,互斥地执行这一段访问临界资源的代码。
- 内核程序的临界区:一般是用来访问某种内核数据结构的,比如进程的就绪队列(由各就绪进程的PCB组成)。处于内核程序临界区访问那些临界资源(内核数据结构)期间内,不能进行程序的调度和切换,必须让这个进程尽快执行完内核程序临界区的代码,完成对这个临界资源的访问,即尽快解除内核数据结构的锁
- 对于内核数据结构,如果被上锁后没有尽快释放,则极有可能影响操作系统内核其他的管理工作:以进程切换为例,当一个进程处于内核程序临界区,并且这个临界区是要访问就绪队列的话,在访问之前,会将就绪队列上锁,若这个进程还没有退出临界区(还没解锁)就进行进程调度(进程调度相关的程序肯定要访问就绪队列,因为要从就绪队列中挑选一个进程为它分配处理机),由于此时就绪队列还处于上锁状态,所以这种情况下无法顺利进行进程调度
- 对于普通的临界资源:如打印机,在打印机完成打印前,进程处于临界区内,临界资源不会解除。但是打印机是慢速设备,若一直不允许进程调度的话会导致CPU一直空闲(空等打印机完成)。所以若进程在访问一个普通的临界资源(在普通的临界区中),是应该要进行进程调度的,而这种临界资源不会影响操作系统内核的管理工作。
- 进入区和退出区:是负责实现互斥的代码段,它们整体的作用表现如下图
3. 进程调度和进程切换区别:调度是“选”,切换是“换”
4. 七种调度算法:
- 三种适用于早期批处理系统的调度算法对比:主要关心用户的公平性、平均周转时间、平均等待时间,但不关心响应时间,也不区分任务的紧急程度。对用户来说交互性很糟糕,适用于早期的批处理系统
算法 | 思想 | 可抢占? | 优点 | 缺点 | 考虑等待时间/运行时间? | 会导致饥饿? | 适用于 |
---|---|---|---|---|---|---|---|
FCFS | 每次调度时选择等待时间最长的作业(进程)为其服务 | 非抢占式 | 公平,实现简单 | 对短作业不利 | 考虑等待时间,不考虑运行时间 | 不会 | 有利于CPU繁忙型作业,而不利于I/O繁忙型作业 |
SJF/SPF | 每次调度时选择一个执行时间最短的作业(进程)为其服务 | 默认为非抢占式,也有SJF的抢占式(最短剩余时间优先算法SRTN) | 严格来说,抢占式的短作业/进程(最短剩余时间)优先算法的平均等待时间、平均周转时间最少。不严格来说,SJF的平均等待时间、平均周转时间最少 | 对长作业不利,可能导致饥饿;难以做到真正的短作业优先 | 不考虑等待时间,考虑运行时间 | 会 | |
HRRN | 非抢占式,调度时计算所有就绪进程的响应比3,选响应比最高的进程上处理机 | 非抢占式 | 上述两种的权衡折中,综合考虑等待时间和运行时间 | – | 考虑等待时间,考虑运行时间 | 不会 |
- 三种适用于交互式系统的调度算法对比:这三种算法更注重系统的响应时间、公平性、平衡性等指标,适用于交互式系统(包括分时操作系统、实时操作系统)。比如Unix使用的就是多级反馈队列调度算法
算法 | 思想 | 可抢占? | 优点 | 缺点 | 会导致饥饿? | 补充 |
---|---|---|---|---|---|---|
时间片轮转 | 按个进程到达就绪队列的顺序,轮流让各个进程执行一个时间片 | 抢占式 | 公平,适用于分时系统 | 频繁切换有开销,不区分优先级 | 不会 | 时间片太大或太小有何影响?4 |
优先级调度 | 每个作业/进程有各自的优先级,调度时选择优先级最高的作业/进程 | 有抢占式的,也有非抢占式的。非抢占式只需在进程主动放弃处理机时进行调度即可,抢占式除此外还需要在就绪队列变化时检查是否会发生抢占 | 区分优先级,适用于实时系统 | 可能导致饥饿 | 会 | 动态/静态优先级?5各类进程设置优先级?6如何调整优先级?7 |
多级反馈队列 | 设置多级就绪队列,各级队列优先级从高到低,时间片从小到大。新进程先进入第1级队列,按FCFS原则排队等待被分配时间片,时间片到未结束则进入下一级队列队尾,若已经在最下级的队列则重新放回本队列队尾。只有第k级队列为空时,才会为k+1级队头的进程分配时间片 | 抢占式 | 平衡优秀 | 一般不说它有缺点,不过可能导致饥饿 | 会 |
- 多级队列调度算法:
按照进程的类型设置多个就绪队列,每个就绪队列的优先级各不相同,每一次调度发生时,首先要选中一个队列,然后根据这个队列内的调度算法来选取队列内的某一个进程上处理机运行
5. 进程同步和进程互斥的概念:
- 进程异步:并发性带来了异步性,即各并发的进程以各自独立的、不可预知的速度向前推进
- 进程同步(也称为进程之间的直接制约关系):有的进程之间需要相互配合地完成工作,各进程的工作推进需要遵循一定的先后顺序
- 进程互斥(也称为进程之间的间接制约关系):并不是合作,对临界资源的访问需要互斥的进行,同一时间段只能允许一个进程访问该资源。
- 四个部分:进入区(检查是否可进入,若可则上锁)、临界区(访问临界资源的代码)、退出区(解锁)、剩余区(其余代码部分)
- 需要遵循的规则:空闲让进、忙则等待、有限等待(保证不饥饿)、让权等待(进入不了临界区的进程要释放处理机防止忙等)
6. 进程互斥的实现:
【1】无法实现“让权等待”的四种软件实现方式和三种硬件实现方式
- 软件:
算法 | 思想 | 主要问题 |
---|---|---|
单标志法 | 在进入区只做检查,不上锁(也不必上锁,因为turn的值唯一),在退出区把临界区的使用权交给另一个进程(即给另一进程解锁,给自己上锁) | 不遵循“空闲让进”原则 |
双标志先检查 | 在进入区先检查后上锁,在退出区解锁 | 不遵循“忙则等待”原则(a检查之后调度到b,b检查之后调度到a,a上锁,执行临界区代码,调度到b,b上锁,执行临界区代码 |
双标志后检查 | 在进入区先上锁后检查,在退出区解锁 | 不遵循“空闲让进”、“有限等待”原则,可能导致饥饿(a先上锁,调度到b,b上锁,调度到a,a检查,进不了临界区,调度到b,b检查也进不了临界区) |
Perterson算法 | 在进入区“主动争取-主动谦让-检查对方是否想进以及己方是否谦让” | 不遵循“让权等待”原则,会发生“忙等”(进不了临界区会一直卡在while循环,这几个算法都有这个毛病) |
- 硬件:
方法 | 思想 | 优点 | 缺点 |
---|---|---|---|
中断屏蔽方法 | 利用“开/关中断实现,即在某进程开始访问临界资源区到结束访问为止都不允许被中断,也就不能发生进程切换,因此也不可能发生两个同时访问临界区的情况 | 简单、高效 | 不适用于多处理机;只适用于操作系统内核进程,不适用于用户进程(因为开/关中断指令只能运行在内核态,这组指令如果能让用户随意使用会很危险) |
TestAndSet(TS指令/TSL指令) | TSL指令是由硬件实现的,执行的过程不允许被中断,只能一气呵成。TSL指令执行的内容是:检查资源是否被上锁,若没被上锁就上锁,返回原先的上锁情况。使用TSL指令实现互斥的算法逻辑是:循环TSL指令,若原先没被上锁,则进入临界区;若原先被上锁则一直循环。TSL指令将“上锁”和“检查”操作用硬件方式变成了一气呵成的原子操作 | 实现简单,无需像软件实现方法(检查和上锁并不一气呵成)那样严格检查是否会有逻辑漏洞;适用于多处理机环境 | 不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,从而导致忙等 |
Swap指令(XCHG指令) | 用硬件实现,执行的过程不允许被中断,只能一气呵成。逻辑和TSL差不多,Swap指令的作用就是交换两个变量的值,用Swap指令实现互斥的算法逻辑是先记录下此时临界区是否被上锁(记录在old变量上),再将上锁标记lock设置为true,最后检查old,若old为false则说明之前没有别的进程对临界区上锁,则可跳出循环,进入临界区 | 实现简单,无需像软件实现方法(检查和上锁并不一气呵成)那样严格检查是否会有逻辑漏洞;适用于多处理机环境 | 不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行Swap指令,从而导致忙等 |
- 互斥锁:一个进程在进入临界区时获得锁,在退出临界区时释放锁。每个互斥锁有一个布尔变量available,表示锁是否可用。
- 锁可用:调用acquire()函数(原子操作)获得锁
- 锁不可用:当一个进程试图获取不可用的锁时,会被阻塞,直到锁被释放
- 互斥锁的缺点:忙等待。当有一个进程在临界区中,任何其他进程在进入临界区时必须连续循环调用aquire()。当多个进程共享同一CPU时,就浪费了CPU周期。因此互斥锁通常用于多处理器系统,一个线程可以在一个处理器上等待,不影响其他线程的执行
- 自旋锁:需要连续循环忙等的互斥锁。如TSL指令、Swap指令、单标志法
【2】可以实现“让权等待”:信号量机制
信号量机制分为整型信号量和记录型信号量:
- 整型信号量:用一个整数型变量作为信号量,数值表示某种资源数
- 整型信号量与普通整型变量的区别:对信号量只能执行初始化、P、V三种操作
- 整型信号量存在的问题:不满足让权等待原则
- 记录型信号量(高频考点)
7. PCB 通常包含的内容:
- 进程描述信息:进程表示符PID、用户标识符UID
- 进程控制和管理信息:进程当前状态、进程优先级、代码运行入口地址、程序的外存地址、进入内存时间、处理机占用时间、信号量使用
- 资源分配清单:代码段指针、数据段指针、堆栈段指针、文件描述符、键盘、鼠标
- 处理机相关信息:通用寄存器值、地址寄存器值、控制寄存器值、标志寄存器值、状态字
8. 进程的各个状态及转换
9. CPU繁忙与I/O繁忙
CPU繁忙型作业是指该作业需要占用很长的CPU时间,而很少请求I/O操作,因此CPU繁忙型作业类似于长作业。FCFS利于长作业,因此也有利于CPU繁忙型作业。
I/O繁忙型是指作业执行时需要频繁请求I/O操作,即可能频繁放弃CPU。所以占用CPU的时间不会太长,一旦放弃CPU,就要重新排队等待调度,因此SJF利于短作业,也利于I/O繁忙型作业。
时间片轮转法对短作业和长作业都一样,所以没有利于谁一说
10. 可重入编码
可重入代码又称为“纯代码”,是一种允许多个进程访问的代码,因此,可重入代码是一种不允许任何进程对它进行修改的代码 。为了能修改,访问纯代码的进程,把执行中可能改变的部分拷贝到本进程的数据区,只需对该数据区中的内容进行修改,并不去改变共享的代码,这时的可共享代码即成为可重入码。
共享程序段是可能同时被多个进程使用的,因此必须可重入编码,否则无法实现共享的功能。
-
- 主模块:只负责核心功能,如进程调度、内存管理
-
- 可加载内核模块:可以动态加载新模块到内核,而无需重新编译整个内核
-
- 响应比: 响应比 = 等待时间 + 要求服务时间 要求服务时间 响应比=\dfrac{等待时间+要求服务时间}{要求服务时间} 响应比=要求服务时间等待时间+要求服务时间
-
- 时间片太大:每个进程都可以在一个时间片内完成,则时间片轮转算法退化为先来先服务调度算法,并会增大进程响应时间8;进程调度、切换是有代价的,若时间片太小,会导致进程切换过于频繁,系统会花大量时间来处理进程切换,从而导致实际用于进程执行的时间比利减少
-
- 动态/静态优先级:静态优先级:创建进程时优先级确定,之后一直不变;动态优先级:创建进程时优先级有一个初始值,之后会根据情况动态地调整。
-
- 各类进程如何设置优先级:通常系统进程优先级高于用户进程、前台进程优先级高于后台进程、操作系统更偏好I/O型进程(或称I/O繁忙型进程)而不是计算型进程(或称CPU繁忙型进程)。这是因为如果优先让I/O繁忙型进程运行,则越有可能让I/O设备更早投入工作,则资源利用率、系统吞吐量都会提升
-
- 如何调整优先级:如果采用的是动态优先级,则可以从追求公平、提升资源利用率等角度考虑:若某进程在就绪队列中等待了很长时间,则可适当提升其优先级;若某进程占用处理机运行了很长时间,则可适当降低其优先级;若发现一个进程频繁进行I/O操作,则可适当提升其优先级
为何增大进程响应时间:假如系统中有10个进程在并发执行,若时间片为1秒,则一个进程被响应可能要等9秒。即若用户在自己进程的时间片外通过键盘发出调试命令,可能需要等待9秒才能被系统响应 ↩︎