53 KiB
written by PeterAlbus,Copyright © 2021 - SHOU 1951123 Hong Wu
注:对于2021年上海海洋大学期末考试来说,打*的部分不在韩彦岭老师提供的期末复习提纲中(若一个根目录标识了*号,则所有子目录也不在复习提纲中),但阅读或许有助于加深对操作系统整体的理解。此外,有些部分课本与上课教学顺序并不一致,考虑到课堂教授顺序更符合理解顺序,某些部分可能会重新编号,与课本顺序不同。
第一章 操作系统概论
操作系统(operation system, OS)是配置在计算机硬件平台上的第一层软件,是管理整个计算机软硬件资源的系统软件。
1.1 操作系统的概念
操作系统是计算机系统中一组控制和管理计算机硬件资源和软件资源,合理地对各类作业进行调度,以方便用户使用的程序的集合。
操作系统的主要功能(五大功能):
- 处理器管理
- 存储器管理
- 设备管理
- 文件系统
- 用户接口
1.2 操作系统的发展历程
无操作系统时代→单道批处理系统→多道程序系统→分时操作系统→实时操作系统
1.2.1 无操作系统时代(1945-1955)*
程序员采用纸带或卡片记录程序,人工操作,人工I/O。计算机运行速度提高后会导致I/O速度和计算速度极其不匹配。
缺点:
- 用户独占资源
- 人工干预较多
- CPU等待人工操作
1.2.2 单道批处理系统(1955-1965)*
由监督程序依次将磁盘中的作业调入内存,待作业执行完毕后再把控制权交还给监督程序。
严格来说,它只能算作OS的前身而并非是现在人们理解的OS。
主要特征:
- 自动性
- 顺序性
- 单道性
1.3.3 多道程序系统(1965-1980)*
在该系统中,用户所提交的作业都先存放在外存上并排成一个队列,称为”后备队列“;然后,由作业调度程序按一定的算法从后备队列中选择若干个作业调入内存,使他们共享CPU和系统中的各项资源。
1.2.4 分时操作系统
分时操作系统让用户通过与计算机相连接的终端来使用计算机系统,允许多个用户同时与计算机系统进行一系列交往。(举例:linux系统的计算机可以通过SSH与多个用户同时远程连接,多个用户在不同终端输入指令)系统能快速地对用户提出的请求给予应答,使得每个用户都感到好像各自有一台独立支持自己请求服务的计算机。
允许多个联机用户同时使用一台计算机进行计算地操作系统称分时操作系统(time sharing operating system)
分时操作系统的四个特点:
- 多路性
- 独立性
- 及时性
- 交互性
目标:公平、高效
1.2.5 实时操作系统*
实时操作系统(real time operating system)是指当数据或事件产生时,能够接受并以足够快的速度处理,其处理的结果又能在规定的时间内来控制生产过程或对处理系统做出快速响应,并控制所有实时任务协调一致运行的操作系。
提供及时响应和高可靠性是其特点。
特点:
- 多路性
- 独立性
- 及时性
- 交互性
- 可靠性
1.2.6 各种操作系统类型极其简介
- 微机操作系统:文件管理,执行程序
- 网络操作系统:具备网络接口的传统操作系统
- 分布式操作系统:用于管理分布式计算机系统的操作系统
- 嵌入式操作系统:在计算机硬件网络上配备的支持应用软件的系统软件是嵌入式操作系统
1.3 操作系统的基本特征
并发性、共享型、虚拟性、异步性。
并发性是操作系统最重要的特性。
并发性和共享型是操作系统最基本的特征。
1.3.1 并发性
并发性(concurrence)是指两个或两个以上的事件或活动在同一时间间隔内发生。
(并行:两个/多个事件在同一时刻内发生)。
操作系统引入了进程来解决并发问题。
1.3.2 共享性
共享是指操作系统中的资源(包括硬件资源和软件资源)可被多个并发执行的进程共同使用,而不是被一个进程独占。
资源共享的方式:
- 互斥访问:一段时间只允许一个进程访问。这样的资源被称为临界资源。
- 同时访问:同一时间段允许多个进程访问。典型的此类资源:硬盘。
1.3.3 虚拟性
虚拟性是指擦奥做系统中的一种管理技术,它把物理上的一个实体编程逻辑上的多个对应物,或者把物理上的多个实体变成逻辑上的一个对应物的技术。
Spooling技术、窗口技术、虚拟存储器......
1.3.4 异步性
异步性也称随机性,是指多道程序环境中多个进程的执行、推进和完成时间都是随机的、交替的不可预测的。
操作系统需要考虑一部性问题使结果一致。
1.4 操作系统的功能
五大功能(同1.1):处理器管理。存储器管理。设备管理。文件系统、用户接口
- 处理器管理:引入了进程(线程)的概念,对处理机的管理可归结为对进程/线程的管理。
- 进程控制
- 进程同步
- 进程通信
- 调度
- 作业调度:从后备队列中挑选作业分配资源,建立进程,放入就绪队列
- 进程调度:从就绪队列中挑选进程分配处理机
- 存储器管理:为多道程序的运行提供良好的环境,方便用户的使用,提高存储器的利用率。
- 内存分配
- 内存保护
- 地址映射
- 内存扩充
- 设备管理:完成I/O请求,分配I/O设备,提高I/O速度
- 缓冲管理
- 数据分配
- 设备处理
- 文件管理:对用户文件和系统文件进行管理,方便用户使用,保证文件的安全性
- 文件存储空间的管理:分配外存空间
- 目录管理
- 文件的读写管理和保护
- 用户接口
- 命令接口(由一组”命令集“组成)、图形接口
- 程序接口(系统调用/高级语言库函数)
1.5 操作系统的结构设计*
1.5.1 传统的操作系统结构
- 无结构操作系统:逻辑复杂,维护困难
- 模块化操作系统:通过分解、模块化控制大型如那件复杂度
- 分层式操作系统:有序地分层
- 自底向上建立若干中间层
- 可简化设计的复杂度
- 下层为上层提供服务
1.5.2 客户、服务机模式
1.5.3 微内核操作系统
- 足够小的内核
- 基于客户/服务器模式
- 机制与策略分离
- 采用面向对象技术
第二章 操作系统接口*
操作系统(OS)向用户提供了以下两类接口
- 用户接口。支持用户与OS间进行交互
- 程序接口,也称应用程序接口API,是为程序员在编程时使用的,系统和应用程序通过这个接口可在执行中访问系统中的资源和取得OS中的服务,它也是程序能取得操作系统服务的唯一途径。
第三章 进程管理
3.1 进程的基本概念
单道程序设计:程序的执行方式是顺序执行,即必须在一个程序执行完成后,才允许另一个程序执行。
多道程序环境:允许多个程序并发执行。
3.1.1 程序的顺序执行及其特征
程序内部的顺序性:在处理器上的执行严格有序,即只有在前一个操作结束后,才能进行下一个操作。
程序外部的顺序性:完成一个任务若需要若干个程序,这些程序也按照调用次序严格有序执行。
特征:
- 顺序性
- 封闭性
- 结果的确定性
- 可再现性
3.1.2 程序的并发执行及其特征
当两个操作的执行不互相依赖,则这两个这两个操作之间两个程序可并发执行。
程序的并发执行可提高系统吞吐量。
对于并发来说,宏观上似乎同一时刻在进行多个进程,实际上同一时刻仍只能进行同一进程(微观上)。
特征:
- 间断性
- 失去封闭性:多个程序共享系统中的各种资源,会使程序的运行受到其他程序的影响
- 不可再现性:由于失去了封闭性,两个进程以不同的速度运行,可能出现很多不同的情况。
3.1.3 进程的定义及描述
1.进程的定义
- 非正式:执行中的程序/运行中的代码段
- 正式:可并发执行的程序在一个数据集合上的执行过程,是系统进行资源调度和分配的一个独立单位。
进程!=程序,程序是静态的,而进程是动态的。
2.进程与程序的关系
进程 | 程序 |
---|---|
动态 | 静态 |
并发 | 顺序 |
暂时 | 永久 |
进程与程序并非一一对应的关系。
3.进程出现的动机:支持多道编程
4.进程的特征
- 结构特征:进程包含数据集合和运行于其上的程序,它至少由程序块,数据块和进程控制块等要素组成。
- 动态性:进程是程序在数据集合上的一次执行过程。程序有其生命周期,由创建而产生,调度而执行,得不到资源而阻塞,撤销而消亡。为进程最基本的特征。
- 并发性:没有建立PCB是不能并发执行的。(建立了进程才能并发执行)是进程的重要特征,也是OS的重要特征。
- 独立性:进程实体是一个能独立运行,独立分配资源和独立接受调度的基本单位。
- 异步性:也称随机性,是指进程按照各自独立的不可预知的速度向前推进。
3.2 进程状态及其转换
3.2.1 进程状态及其转换
1.进程的三种基本状态
- 就绪(ready)状态:进程具备运行条件,等待系统分配处理器
- 执行(running)状态:进程占有处理器正在运行
- 阻塞(blocked)状态:又称为等待(wait)态或者睡眠(sleep)态。正在执行的进程由于发生某事件而无法继续执行,便放弃处理机而处于暂停状态。
2.挂起状态(被换出内存的状态)
引入挂起状态的原因:
- 终端用户请求
- 父进程请求
- 负荷调节需要
- 操作系统需要
3.2.2 进程控制块(PCB)
进程的组成:PCB、程序段、数据段、堆栈。
引入PCB的作用:使程序成为独立运行的模块,和其他程序并发执行。
PCB是实体的一部分,是OS中最重要的数据结构。
- PCB是进程存在的唯一标志。
- PCB(Process control block)常驻内存。
1.进程控制块中的信息
- 标识信息(进程描述信息)
- 进程名
- 进程标识符
- 用户名
- 现场信息(处理机状态信息)
- 通用寄存器
- 指令计数器
- 程序状态字寄存器
- 栈指针
- 进程调度信息
- 进程状态
- 进程优先级
- 运行统计信息
- 进程阻塞原因
- 进程控制和资源占有信息
- 进程调度信息
- 进程组成信息
- 族系信息
- 进程间通信信息
- 进程段/页表指针
- CPU的占有和使用信息
- 进程特权信息
- 资源清单
进程控制块的组织方式:链接方式、索引方式
3.3 进程控制
进程管理中对进程的控制是最基本的功能。其控制包括:创建进程,终止已完成进程,状态转换。
原语:计算机进程的控制通常由原语完成。所谓原语,一般是指由若干条指令组成的程序段,用来实现某个特定功能,在执行过程中不可被中断。
3.3.1 进程的创建
1.引起进程创建的事件:
- 用户登录
- 作业调度
- 提供服务
- 应用请求
2.创建过程(Create原语)
- 申请空白PCB
- 为新进程分配资源
- 初始化PCB
- 进程描述信息
- 处理机状态信息
- 初始化进程控制信息
- 将进程插入就绪队列
3.3.2 进程的终止(原3.3.3)
1.引起进程终止的事件:
- 正常结束:HALT,logoff
- 异常结束:越界、非法、I/O等
- 外界干预:管理员kill等
2.进程的终止过程:
- 检查进程状态
- 执行态->终止,且置调度标志位真
- 检测有无子孙需终止
- 归还资源给父进程或系统
- PCB队列中移出被终止进程
3.3.3 进程的阻塞与唤醒(原3.3.2)
1.引起进程阻塞与唤醒的事件
- 请求系统服务而得不到满足
- 启动某种操作(如I/O)操作
- 新的数据尚未到达
- 无新工作可做
2.进程阻塞过程(block原语)
是进程自身的一种主动行为
- 停止进程执行,保存相关信息到PCB。
- 修改PCB的相关内容,如修改进程状态为等待(阻塞)
- 加入阻塞队列
- 转入进程调度程序,调度其他进程运行
3.进程唤醒过程(wake up原语)
- 从阻塞(等待)队列取出PCB
- 修改PCB的相关信息,如进程状态修改为就绪
- 把修改后的PCB加入有关就绪进程队列
3.3.4 进程的挂起与激活
suspend-active 原语
阻塞、唤醒一般由OS实现,而挂起、激活可以由用户实现
3.4 线程(原3.7)
公平和效率的权衡是进程管理永恒的话题。
进程的缺陷:
- 一个进程在一个时间只能做一个事情
- 阻塞将使进程挂起,使整个进程都无法执行
为了解决以上问题:
线程(threads),比进程更小的能独立运行的基本单位,
人们通过线程,试图提高系统内程序并发执行的速度,从而进一步提高系统的吞吐量。
3.4.1 线程的引入
单线程结构的进程给并发程序设计带来了一系列的问题:
- 进程时空的开销大
- 进程通信的代价大
- 进程之间的并发性粒度较粗,并发度不高
- 不适合并行计算和分布并行计算的要求
- 不适合客户/服务器计算的要求
解决问题的基本思路:把进程的两项功能——“独立分配资源”和“被调度分派执行分离开来”。前者仍交由进程处理,后者则交给称为线程的实体完成。
3.4.2 线程的基本概念
1.进程与线程的比较
线程具有许多传统进程所具有的特征,所以又称为轻型进程或进程元。
在引入了线程的操作系统中,通常一个进程都拥有若干个进程,至少也有一个进程。
进程 | 线程 | |
---|---|---|
调度性 | 传统操作系统中作为独立分派、调度的基本单位。 | 引入线程的操作系统中独立分派、调度的基本单位,而进程则作为资源拥有的基本单位。 |
并发性 | 进程之间可以并发执行,但若没有引入线程,当进程阻塞时,整个进程都无法完成其他任务。 | 线程之间同样可以并发执行,进程的一个线程阻塞,其他线程仍可提供服务。 |
拥有资源 | 是系统中拥有资源的一个基本单位。 | 虽然拥有一点关键资源,但不算拥有资源的单位。共享进程的资源。 |
系统开销 | 创建或撤销进程时系统需要为之创建和回收PCB,分配或回收资源。 | 远小于进程的开销,线程的切换也仅需保存和设置少量寄存器内容。同一个线程中的进程共享地址空间,因此同步和通信也较为容易。 |
线程的状态和状态转换类似于进程,但一部分状态时没有意义的,例如线程没有挂起状态。
2.线程的属性
- 轻型实体
- 独立分派调度的基本单位
- 可并发执行
- 共享进程资源
线程可以独立调度,但不算是拥有资源的单位。
线程共享的资源:*
- 地址空间
- 全局变量
- 打开文件
- 子进程
- 信号
独享的资源:*
- 程序计数器
- 寄存器
- 栈
- 状态字
3.4.3 线程管理和线程库*
1.线程状态
每个线程:
- 线程标识符
- 一组状态参数
- 寄存器状态
- 堆栈
- 线程运行状态
- 优先级
- 线程专存存储器
线程的运行状态:执行、就绪、阻塞。
2.线程的创建和终止
初始化进程:应用程序启动时有的进程
终止:自我终止或他人强制终止
由线程库(用户空间运行/内核中运行)提供的基本线程控制原语:
- 孵化(spawn)
- 封锁(block)
- 活化(unblock)
- 结束(finish)
3.多线程操作系统中的进程
- 独立拥有资源
- 可分为多个线程
- 不是可运行的实体
3.4.4 线程的实现
1.内核级线程
- 完全在内核控件实现
- 内核空间设置线程控股之快
- 由OS进程线程调度,资源分配等
- 由OS维护现线程的信息
优点:
- 多处理器系统中,内核能同时调度同一进程中多个线程并行执行
- 阻塞线程不会阻塞进程
- 内核态线程具有很小的数据结构和堆栈,线程切换快,开销小
- 内核本身可采用多线程技术,提高系统执行速度和效率
缺点:
- 效率低
- 内核实现需要占用内存资源
- 需修改操作系统
2.用户级线程
- 在用户空间实现
- 用户空间建立线程库:一组管理线程的进程
- 用户自己写执行,系统进行调度
- 线程资源合作
- 操作系统不知道现成的存在
优点:
- 线程切换快:不需要陷入内核空间
- 应用程序特定需要选择调度算法:可选择最好的算法
- 灵活性:可在任意操作系统实现
缺点:
- 编程困难
- 多线程应用不能利用多处理机提高并行效率
- 系统调用的阻塞问题,线程受阻导致整个进程受阻
如何解决用户级线程的阻塞问题:
- 修改操作系统
- 激活受阻进程的其他线程
- 激活进程调度器
- 方法:第二次机会法
- 问题
- 仍需小幅更改操作系统
- 违反了操作系统设计的层次结构
3.组合式线程
将内核态和用户态实现结合起来
- 操作系统管理内核级线程
- 线程库管理用户态线程
- 一些用户态线程映射成内核态
4.比较
用户级现成的切换速度更快,但用户级线程系统调用不如内核级线程,同时内核级线程的时间分配更合理。
3.5 进程通信(Inter Process Communication)
进程通信,是指进程之间的信息交换,其所交换的信息量少者是一个状态或者树脂,多者则是成千上万字节。
进程间的互斥和同步交换的信息量较少,因此被称为低级通信。
信号量机制尽管适合作为同步工具,但作为通信工具有入戏缺点:
- 效率低
- 通信对用户不透明
而高级进程通信,是指用户可直接利用操作系统所提供的一组通信命令高效地传送大量数据的一种通信方式。系统实现,隐藏实现细节(即通信过程对用户是透明的)。
3.5.1 进程的通信方式
1.共享存储器系统(shared-memory system)
相互通信的进程共享某些数据结构或共享存储区,进程之间能够通过这些空间进行通信。
- 共享数据结构,需要设置公用数据结构,处理进程同步。是低效的,只适用于传递相对少量数据。
- 共享存储区,在存储器中划分出一块共享存储区,进程通过对共享存储区中的读/写实现通信。
2.消息传递系统
消息传递系统(message passing system)是当前应用最广泛的一种进程间的通信机制。该机制中,进程间的数据交换以格式化的消息(message)为单位,计算机网络中又把消息称为报文。程序员直接利用系统提供的通信命令(原语)即可传递大量数据。
-
直接通信方式
send(P,message)
,把一个消息发送给进程Preceive(Q,message)
,从进程Q接收一个消息 -
间接通信方式(信箱)
进程间发送或接收消息通过一个共享的数据结构——信箱进行。每个信箱有一个唯一的标识符。
send(A,mail)
,把一封信件(消息)传送到信箱Areceive(A,mail)
,接受信件,若无信件,则将进程置为等待状态
信箱是存放信件的存储区域,信箱可分为信箱头和信箱体。头储存容量、格式、位置指针等。体存放信件。
3.管道通信系统
管道是指用于连接一个读进程和一个写进程以实现它们之间通信的一个共享文件,又名pipe文件。
管道机制必须提供以下三个方面的协调能力
- 互斥,一个进程读/写时另一进程等待
- 同步,一个进程写入一定数据量后,应睡眠等待,读进程取走后再唤醒写入,反之亦然。
- 确定对方是否存在,确定对方存在时才能进行通信。
3.6 进程同步(原3.4)
进程同步的引入:
由于程序的异步性,可能会导致程序执行结果的不一致。
控制进程的执行以及执行顺序称为进程同步。
主要任务:对多个相关进程在执行次序上进行协调,使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。
3.6.1 进程同步的概念
多道程序环境下,并发执行的程序可能存在如下两种形式的制约关系:
-
资源共享关系(竞争关系,间接制约关系)
进程共享一套的计算机系统资源,会出现竞争资源的关系。
进程的互斥(mutual exclusion)是解决进程间竞争关系的手段,也成为间接同步。
-
相互合作关系(协作关系,直接制约关系)
进程为完成一个任务需要分工合作,因为进程的异步性,进程独立地以不可预知地速度推进,这就需要相互协作的进程在某些协调点上协调各自的工作。
进程的同步(synchronization)是解决进程间协作关系的手段,也称直接同步。
进程同步指对进程与进程之间的穿插进行控制。而互斥也是通过逐次使用互斥资源,协调了资源的使用顺序,也是间接地对进程顺序的协调。
3.6.2 临界区及其管理
1.临界资源和临界区
临界资源:一次仅允许一个进程访问的资源
临界区:进程访问临界资源的代码段
2.临界区管理
同步机制应当遵循的4个准则:
- 空闲让进
- 忙则等待:有一进程进入临界区时,其他进程等待
- 有限等待
- 让权等待:等待时应当放弃CPU
3.高级进程同步机制
1.锁(Mutex)
-
锁阻止了其他进程进入临界区
-
两个基本操作:
Lock lock(Lock lock)//等待锁达到打开状态,获得锁并锁上 { while(1) { if(lock.isfree()) { return lock; } } } void unlock(Lock lock){lock.free()};
-
四个基本要素
- 锁的初始状态要是打开状态
- 进入临界区前必须获得锁
- 出临界区时必须打开锁
- 如果别人持有锁则必须等待
2.睡眠与唤醒
sleep()
原语wake up()
原语
wake up由其他进程执行。
3.6.3 信号量及PV操作
1965年,E.W.Dijkstra提出了一种卓有成效的进程同步工具:信号量(semaphore)机制。
在信号量机制中,有检测(Probern,P,检测,荷兰语)和归还(Verhogen,V,增量,荷兰语)两个重要的操作。
- P操作(wait,down):表示同步进程发出的检测信号量操作,检测是否能够使用临界资源,如果不能使用则等待正在使用的进程归还临界资源
- V操作(signal,up):将临界资源释放
PV操作都是原子操作。
信号量的类型:
- 整型信号量
- 记录型信号量
- AND型信号量
- 信号量集
1.整形信号量
设S为一个需要初始化的整形变量,对S的访问仅能通过两个标准的原子操作P(S)和V(S)。
S的初值可为0或1
void P(int S)
{
while(S<=0){}
S=S-1;
}
void V(int S)
{
S=S+1;
}
如果S的值为1,表示有一个临界资源可供使用,P(S)检测通过后,S值被减为0。
如果S值为0,表示没有临界资源,P(S)检测不能通过,进程等待。
由于在等待过程没有放弃CPU控制权,违背了"让权等待"的原则。
记录型信号量解决了这一问题。
2.记录型信号量
让不能进入临界区的进程“让权等待”,进入阻塞队列等待。
设S为一个记录型数据结构,S的定义如下:
#define A 1000
typedef struct semaphore
{
int value;
PCB L[A];//阻塞队列
}Semaphore;
相应的,PV操作可描述为:
void P(Semaphore S)
{
S.value-=1;
if(S.value<0) block(S.L);//将调用P的进程阻塞,并放入阻塞队列
}
void V(Semaphore S)
{
S.value+=1;
if(S.value<=0) wakeup(S.L);//从阻塞队列唤醒一个在等待的进程
}
3.AND型信号量
上述的进程互斥问题都仅仅针对共享一个临界资源而言。而当进程需要获得两个或更多的临界资源才能完成任务时,有可能由于进程语句顺序不当而造成死锁状态,
AND型信号量便是为了解决此类问题。
解决思路:将进程所需要的资源一次性分配。
AND型信号量可定义为:
void P(S1,S2,...,Sn)
{
if(S1>1 && S2>1 && ... && Sn>1)
{
for(int i=0;i<n;i++)
{
Si-=1;
}
}
else
{
将进程置于等待队列中等待条件满足;
}
}
void V(S1,S2,...,Sn)
{
for(int i=0;i<n;i++)
{
Si+=1;
唤醒符合条件的线程;
}
}
AND型信号量能够避免死锁,但使并发进程变为先后执行,进程之间相互等待,使得系统整体性能降低。
4.信号量集
用于解决进程一次申请多个同类资源的问题。
信号量集的定义:
S1、S2、...、Sn
表示分别由n类临界资源信号量t1、t2、...、tn
表示每类临界资源的下限值d1、d2、...、dn
分别表示进程需要的每类临界资源个数
void P(S1,t1,d1,...,Sn,tn,dn)
{
if(S1>t1 && ... && Sn>tn)
{
for(int i=0;i<=n;i++)
{
Si-=di;
}
}
else
{
将当前进程插入Si的等待队列,Si是第一个不满足Si>ti的信号量,程序计数器设为P操作的开始;
}
}
void V(S1,d1,...,Sn,dn)
{
for(int i=0;i<=n;i++)
{
Si+=di;
唤醒Si等待队列的所有进程;
}
}
三种特例:
P(S,d,d)
:只有一个信号量S,但允许每次申请d个资源,资源小于d时不分配
P(S,1,1)
:此时信号量集以及蜕变为一般的记录型信号量
P(S,1,0)
:特殊且有用的信号量操作,当S>=1时允许多个进程进入特定区,但当S为0后阻止任何进程进入,相当于一个可控开关。
5.信号量的应用
- 实现进程互斥
- 描述前趋关系
常见问题:生产者-消费者、哲学家进餐问题、读者-写者问题。
考试时要会利用信号量解决实际问题。
使用信号量时注意:
- PV(wait和signal)必须成对出现。
- 用于实现互斥的PV必须成对出现在一个程序中,但对资源信号量的PV可能成对出现在不同的程序中。
- 要注意P操作的顺序,防止进程死锁。
3.6.4 管程*
引入管程的原因:为了避免凡是要使用临界资源的进程都自备同步操作P和V,将同步操作的机制和临界资源结合到一起,形成一种新的同步工具,管程(monitors)。
目的是避免PV过多以及使用不当引起死锁。
1.管程的定义
一个数据结构和能够为并发进程所执行的在该数据结构上的一组操作。
2.管程的特性
- 模块化
- 抽象数据类型
- 信息封装
- 任意时刻,在管程中只能由一个进程
3.7 死锁(原3.6)
3.7.1 死锁的定义
多道程序中,多个程序并发执行可能引发一种危险——死锁。
死锁,是多个进程在运行过程中争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。
资源:进程运行需要的事物。
3.7.2 产生死锁的原因
进程需要以一种合理的顺序来访问资源
产生死锁的原因:
- 竞争资源引起死锁
- 进程间推进次序不当
产生死锁必须满足4个条件:
- 互斥条件:某资源在一个时间内只能由一个进程占用
- 持有等待:线程在请求新的资源时,已经获得的资源不释放而是继续持有
- 不能抢占:不能强迫进程放弃资源
- 环路等待
3.7.3 处理死锁的方法
处理死锁的方法可归结为:
- 不予理睬:忽略问题的存在
- 此种策略在如下情况下合理:
- 死锁出现的概率很低
- 预防死锁的代价很大
- UNIX和windows都采用此方法
- 是方便和正确性的一种折中
- 此种策略在如下情况下合理:
- 静态预防:消除死锁的4个必要条件的任意一个
- 消除资源独占条件
- 一些设备可以被共享
- 但不是所有设备都可以被共享
- 消除持有等待条件
- 进程启动时请求所有资源
- 缺点:资源浪费、可能无法得知所需的所有资源
- 消除非抢占条件
- 允许抢占CPU(信息保存到进程控制表)/内存(内存导出到硬盘)
- 局限性:有些资源不可被抢占:如锁、打印机
- 消除环路等待条件
- 指定需要资源的顺序
- 或增加资源,最小化死锁的概率
- 消除资源独占条件
- 动态避免:仔细地资源分配
- 死锁检测、解除死锁:成对地解决方法,在死锁发生后采取措施纠正
3.7.4 死锁检测和修复*
注意资源的占有和资源需求。
资源分配图以及检测:
- 有向图检测
- 矩阵检测
死锁的恢复:
- 剥夺资源
- 杀死进程
3.7.5 死锁的动态避免(银行家算法)
Dijkstra在1965年提出了银行家算法,源于银行家发放贷款时采取的控制方法。
- 事先声明所需的最大资源(但实际并不获得最大资源)
- 在之后进程请求资源时
- 若分配资源后仍处于安全状态,满足要求
- 否则阻塞进程
银行家算法的数据结构:
-
可利用资源向量Available
例:
Available={3,3,2}
A B C 3 3 2 其中的每个元素代表一类可利用的资源数目
Available[j]=k
代表系统现有Rj
类资源k
个 -
最大需求矩阵Max
例:
Max={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}}
进程\资源 A B C P0 7 5 3 P1 3 2 2 P2 9 0 2 P3 2 2 2 P4 4 3 3 是一个n*m矩阵,表示系统中n个进程的每一个进程对m类资源的最大需求。
-
分配矩阵Allocation
也是一个n*m矩阵,表示当前每一类资源已经分配给进程的资源数
-
需求矩阵Need
同样是一个n*m矩阵,用以表示每一个进程尚需的各类资源数
Need[i][j]=Max[i][j]-Allocation[i][j]
银行家算法流程:
- 对于请求向量Request进行检测,若请求的资源大于需求资源Need,则拒绝
- 若请求的资源大于可用资源Available,拒绝,没有足够资源分配,需要等待
- 试探性分配资源并进行安全性检测,若分配后状态安全,则进行分配,否则拒绝
安全性算法(简要自然语言描述):
若能找到一个序列,系统的剩余资源能按次序完成(一个进程完成后,拥有的全部资源会归还)每个进程的请求,则当前状态安全。
考试要求:要会使用银行家算法对Request进行分析。
第四章 处理机调度
处理机是计算机系统中的重要资源,在多道程序环境下,进程数目>处理机。系统需要按照一定方法动态地分配给就绪队列。处理机利用率和系统性能很大程序取决于处理机调度。
处理机调度是操作系统设计的中心问题之一。
- WHAT:按什么分配
- WHEN:何时分配CPU
- HOW:如何分配CPU
处理机调度:指在多道程序环境中将处理机分配给进程。
4.1 处理机调度的层次
作业是用户在一次解题或一个事务处理过程中要求计算机系统所作工作的集合,包括用户程序、所需的数据及命令等。
作业的状态:后备、运行、完成。
4.1.1 高级调度
高级调度也称为作业调度、长程调度或接纳调度。
主要任务是为作业分配内存、资源,放入就绪队列。
每次作业调度时,需决定:
-
接纳多少个作业
取决于多道程序度,即允许多少个作业同时在内存中运行
- 作业太多:服务质量下降
- 作业太少:资源利用率低
-
接纳哪些作业
取决于作业调度算法:
- 先来先服务
- 短作业优先
- 作业优先权调度
- 响应比调度
4.1.2 低级调度
低级调度也称为进程调度或短程调度
主要任务是按某种策略和方法选取一个就绪进程,分配处理机
低级调度分为抢占式和非抢占式两种。
-
非抢占式:当前进程不会被优先级更高的进程抢占
引起进程调度的因素
- 正在执行的进程执行完毕,或因发生某事件不能继续执行。
- 执行中的进程因I/O暂停
- 进程执行了某种原语操作,如
wait
/block
优点:算法简单,系统开销小
缺点:紧急任务不能及时响应;短进程等待长进程
-
抢占式
若有某个更为重要或紧迫的进程进入就绪队列,则暂停当前进程,将处理机分配给这个更为重要或紧迫的进程。
抢占式调度主要有以下原则
- 优先权原则
- 短进程优先原则
- 时间片原则(分配的时间片用完后停止执行)
优点:适用于时间要求严格的实时系统
缺点:调度算法复杂,系统开销大
低级调度的时间尺度往往是毫秒级的,由于频繁使用因此要求在实现时做到高效。
4.1.3 中级调度
中级调度也称为中程调度
引入目的:提高内存利用率和系统吞吐量
主要任务:按照给定的原则和策略,交换内存和外存
4.1.4 处理机调度的目标(原4.3.1)
- 对于I/O密集型程序,极小化平均响应时间
- 平均化做每项工作的时间
- 对于计算密集型程序,极大化系统吞吐量
- 单位时间内完成尽可能多的程序
- 对于平衡性程序,响应时间和周转时间达到平衡
4.1.5 不同系统的调度目标(原4.3.1)
- 批处理系统
- 系统吞吐率:最大化单位时间的工作量
- 周转时间:最小化任务提交到结束之前的时间
- CPU利用率:保证CPU始终在繁忙工作状态
- 交互式系统
- 快速响应需求
- 满足用户期望
- 实时系统
- 截止时间内满足需求
- 避免丢失数据
- 提供性能可预测性
4.2 调度队列模型及调度准则*
4.2.1 调度队列模型
- 仅有进程调度的调度队列模型
- 具有高级和低级调度的调度队列形式(批处理系统)
- 同时具有三级调度的调度队列模型
4.2.2 选择调度方式和算法的若干准则
1.面向用户的准则
- 周转时间短(周转时间:完成时间-到达时间,带权:周转时间/服务时间)
- 响应时间快(交互性作业)
- 截止时间的保证(特别是对于实时系统)
- 优先权准测
2.面向系统的准则
- 吞吐量高(特别是对于批处理系统)
- 处理机利用率好
- 各类资源的平衡利用
4.3 调度算法
4.3.1 先来先服务
先来先服务(First come, First serve, FCFS)是最简单的非抢占式调度算法,它是指按照作业或进程进入系统的先后次序进行调度。
先进入系统者先调度,即启动等待时间最长的进程。既可用于作业调度,也可用于进程调度。
优缺点:
- 有利于长作业(进程),而不利于短作业(进程)
- 有利于CPU繁忙型进程(作业),而不利于I/O繁忙型进程(作业)
- 用于批处理系统,不适用于分时系统
4.3.2 短作业(进程)优先调度算法
短作业(进程)优先调度算法(short job first,SJF/short process first,SPF)是指以运行时间长短进行调度,启动运行时间最短的作业(进程)。
优缺点:
- 能够降低平均周转时间和平均带权周转时间
- 对长作业不利,长作业长期不被调度引发饥饿
- 没有考虑作业的紧迫程度
- 运行时间仅能估算,实际会有变动
4.3.3 高优先权调度算法
为了照顾紧迫作业,使之在进入系统后便获得优先处理,引入了最高优先权优先(first priority first, FPF)算法。
分为抢占式(会立即结束当前进程)和非抢占式。
都会把处理机分配给最高优先权的进程,当有更高优先权的进程到达时,抢占式算法将立即停止当前进程的执行,处理机分配给优先权最高的进程,非抢占式算法将不会比较优先级,首先将当前进程执行完毕。
确定进程优先权的依据有以下三个方面:
- 进程类型
- 进程对资源需求
- 用户要求
优先权的类型:
- 静态优先权:在创建进程时确定
- 系统开销小
- 不够精确
- 动态优先权
- 随着进程的推进/等待时间的增加而改变
- 可规定就绪队列中的进程随等待时间增长,优先权提高
- 在抢占式FPF中,也可规定执行中的进程随执行时间增长,优先权降低
4.3.4 高响应比优先调度算法
是FCFS和SJF的结合
高响应比优先调度算法(Highest Response Ratio First, HRF)的调度策略是使响应比最高的作业优先启动。
优先权=响应时间(等待时间+服务时间)/服务时间
等待时间相同的作业,要求服务时间越短,优先权更高
服务时间想通过的作业,等待时间越航,优先权越高
优先权随等待时间增加而提高
是一种折衷,既照顾了短作业,又考虑了到达的先后次序
缺点:要进行响应比计算,增加了系统开销
4.3.5 简单的时间片轮转算法
时间片轮转(Round Robin, RR)是指系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时给队首分配一个时间片。时间片用完时加入队尾。
缺点:紧迫任务响应时间慢
4.3.6 多级反馈队列调度算法
是目前公认的一种较好的进程调度算法。
设置多个就绪队列,并为各个队列赋予不同的优先级
- 第一个队列优先级最高,之后依次降低
- 第一个队列分配的时间片最短,之后依次加长
- 第一个队列分配的时间片用完后,置入第二个队列,以此类推
多级反馈队列调度算法具有较好的性能,能很好地满足各种类型用户的需要。
4.4 实时调度
先前的调度算法关注平均化的分析,而对于实时系统,必须保证在截止时间前完成任务(例:视频输入,物理控制系统)
4.4.1 实时调度的基本条件
- 提供必要的调度信息
- 就绪时间
- 开始/完成截止时间
- 处理时间
- 资源要求
- 优先级
- 系统处理能力强
- 具有快速切换机制
4.4.2 常用的几种实时调度算法
1.最早截止时间优先(EDF)
总是运行最早结束的作业
2.最低松弛度优先(LLF)
松弛度:A需在200ms前完成,运行需100ms,当前10ms,则A的松弛度为200-100-10=90ms
4.5 进程调度的时机
- 当一个进程运行完毕,或由于某种错误而终止运行
- 当一个进程在运行中处于等待状态(阻塞)
- 分时系统中时间片到
- 有一个优先级更高的进程就绪
- 进程执行了某种原语
第五章 存储管理
5.1 存储器
5.1.1 存储器的层次结构
实际情况的内存架构:
- CPU寄存器:低容量、高速度、高价格
- 高速缓存
- 主存(内存):中容量、中速度、中价格
- 内存的大小是衡量计算机性能的一个非常重要的指标
- 辅存(外存):大容量、低速度、低成本
不同层次的存储介质,均有操作系统进行统一管理,存储管理主要负责内存、高速缓存的管理,外存的管理则交由设备和文件管理负责。
计算机中的内存也称为物理内存,其地址从最低开始到最高上界,按照顺序编号。内存中的地址称为物理地址。
而在操作系统中,存储管理功能负责为进程分配和回收内存,实现内存空间在时间和空间上的复用。
5.1.2 程序的装入和链接*
- 用户用高级语言编写的源程序,需要经过编译、链接和装入后,才能被处理器运行。
程序装入内存前,装入模块中给出的程序地址为程序的逻辑地址,一个用户的所有装入模块的逻辑地址集合称为该作业的逻辑地址空间。
用户作业被装入内存后,进程物理地址的总体构成了物理地址空间。
为保证用户作业的正确运行,必须把用户作业的逻辑地址转化为物理地址,这一过程称为地址变换或重定位。
- 编译是将用户用高级语言编写的源程序转化为目标模块
- 链接将用户需要的所有目标模块链接在一起,形成一个可执行模块,即装入模块
- 静态链接:链接过程在程序装入内存前完成,形成整个程序的逻辑地址空间
- 装入时动态链接
- 便于模块修改和更新
- 便于目标模块的共享
- 运行时动态链接
- 不运行的模块,不需要链接
- 装入将装入模块放入内存
- 绝对装入方式:对程序员要求很高,适合用于实时操作系统和嵌入式操作系统
- 静态重定位装入方式
- 动态重定位装入方式:可以在程序运行时重新定位程序在内存中的地址,以便于虚拟存储器等功能
5.1.3 存储器管理的两个目标
- 地址独立:程序发出的地址与物理主存地址无关
- 地址保护:一个进程不能访问另一个进程的地址空间
5.2 连续存储空间管理
连续存储空间,是指为一个用户程序分配一个连续的内存空间
可进一步划分为:
- 单一连续分配
- 最早出现,应用于单道编程
- 固定分区分配
- 应用于多道编程
- 动态分区分配
- 应用于多道编程
- 动态分区重定位
5.2.1 单一连续分配
-
是最简单的存储管理方式,只用于单用户、单任务的系统中。
-
内存分为系统区和用户区
- 系统区仅提供给操作系统使用
- 用户区提供给用户使用
-
达到了地址独立
-
达到了地址保护(整个系统只有一个用户程序)
-
问题
- 将整个程序加载到内存空间
- 浪费资源
5.2.2 固定分区分配
- 多道编程中最简单的内存管理方式
- 将内存划分为几个固定的区域,可同时装入多个作业/任务
- 程序被加载到固定的分区
- 分区大小
- 大小相等:缺乏灵活性
- 大小不等:多个较小分区,适量中等分区以及少量大分区
- 分配到分区的选择
- 每个分区一个进程队列,每个队列进入固定分区
- 单一输入队列,新进程可以进入任意分区
- 固定分区分配的地址变换也有静态重定位方式和动态重定位方式
- 地址变换借助于下限寄存器和上限寄存器
- 进程的逻辑地址+下限寄存器中的基址为物理地址
- 若物理地址落入上下限寄存器地址中则有效,否则访问越界,拒绝分配分区
- 缺点:
- 内存利用率不高(内存碎片)
- 划分分区大小困难
- 需要预先知道进程大小
5.2.3 动态分区分配
-
根据作业的实际需要,动态地为其分配内存空间
- 为了完成分配和回收分区,需要构建对分区信息描述地数据结构,并完成分区分配算法与回收方法
-
数据结构
- 空闲分区表:包括分区号、分区始址,分区大小
- 空闲分区链:空闲分区最常用地组织形式,所有地空闲分区通过前向和后向指针串在一起组成双向空闲分区链
-
分区分配算法
-
首次适应法
- 空闲分区链按照地址递增的顺序组织
- 每次分配内存时,遍历分区链,找到满足大小分区时分割一部分给程序
- 找不到则分配失败
缺点:大空闲分区被分割、每次查找都从链首开始,增加了查找的开销
-
循环首次适应法
- 空闲分区链按照地址递增的顺序组织
- 每次分配内存时,从空闲分区链上上次为作业分配分区后的位置开始查找
克服了空闲空间分布不均的问题,但碎片空间问题仍没有得到解决
-
最佳适应算法
- 空闲分区链按照分区大小递增的顺序组织
- 从分区链中挑选一个满足进程要求的最小分区进行分配
是一种较优的分区分配算法,但剩余的空闲分区很小,这一部分很小的碎片,难以再次利用
-
最坏适应算法
- 空闲分区链按照分区大小递减的顺序进行组织
- 从分区链中挑选一个满足作业要求的最大分区
系统会缺乏较大的空闲分区
-
快速适应算法
- 空闲分区根据容量大小进行分类,单独设立空闲分区链
- 内存中设一张管理索引表,每一个表对应了空闲分区类型
- 分配时根据大小从对应索引表找到对应空闲分区链的起始指针,开始查找分配
该算法查找效率高,对大的作业不会产生内存碎片
缺点是回收分区困难,算法复杂,系统开销大
-
-
分区分配和回收操作
-
分区分配:首先根据分配算法中查找所需大小的分区。分区分配成功后会将分配区的首地址返回给分配过程的调用者。
-
分区回收:作业完成时会释放内存,系统需要回收,回收的内存进入空闲分区链才能再次分配。
根据分区的首地址,有四种不同的情况:
- 上邻空闲区:合并,修改大小
- 下邻空闲区:合并,修改大小、首地址
- 上下邻空闲区:合并,修改大小
- 不邻接:建立一新表项插入空闲链的适当位置
-
-
存在的问题
- 难以增长进程空间(如栈,数据等)
解决方案:为增长的栈和数据段分配空间
5.2.4 可重定位分区分配
动态重定位的引入:连续分配方式中,总量大于作业大小的多个小分区不能容纳作业。
通过作业移动将小分区拼接成大分区,作业的移动需要重定位。
5.2.5 对换
对换:把内存中暂时不能运行的进程或者暂时不用的程序和数据调出到外存上,以便腾出足够的内存空间
整体对换:进程对换
部分对换:分页对换
为实现进程对换,系统须实现三方面功能:
- 对换空间的管理
- 进程的换出
- 进程的换入
外存
- 文件区:注重空间利用率,一般采用离散存储方式
- 对换区:注重速度,采用连续分配方式
换出
- 选择被换出进程:考虑进程状态、优先级、驻留时间
- 换出过程:若为共享段,必须计数-1后为0(没有进程需要)才换出,否则不换出。修改PCB。
换入
- 选择换入进程:考虑进程就绪、优先级、换出时间
- 申请内存
- 换入
连续分配方式的问题:
- 很难增长地址空间
- 不能运行大于物理内存的程序
- 外部碎片
如何解决以上问题?分页。
5.3 分页存储管理
5.3.1 分页存储管理的基本思想
- 将物理内存分配成固定大小的块(或页框)
- 固定单元易于分配
- 任何空闲物理页可以存储任何逻辑页
- 将逻辑空间分成相同大小的页
- 每个逻辑页可以存在物理内存上或导出到磁盘上
- 进程通过逻辑地址访问内存
- 页面大小不能太大(导致碎片)也不能太小(页表过长,效率低),一般是512B~8K
5.3.2 分页系统中的地址结构
- 页面号
- 页内偏移量
通过页表实现逻辑页面和物理块之间的映射关系
处理器可以通过页表的一个有效/无效位知道逻辑页面是否在物理内存中
页面可以有不同的保护方式(可读、可写、可执行),这些信息也保存在页表中
1.页表
- 页表是分页系统的关键组成组件
- 是一个硬件数据结构,实现逻辑页面和物理块之间的映射关系
- 页表内容:
- 是否存在物理内存中的标志位、
- 物理页面号
- 修改位:加载后是否被修改过
- 访问位:页面被读/写
- 保护位
2.页面翻译过程
块内偏移=页内偏移
物理地址=块号*块长+块内偏移
3.地址变换机构
基本任务:实现从逻辑地址到物理地址的转换
借助页表完成,页表大多驻留内存
每个进程对应一个页表,未执行时其信息放入PCB中,执行时将页表的首地址装入页表寄存器。
系统只设置一个页表寄存器,存放页表在内存的首地址和页表长度
分页系统存在的问题:页表的尺寸可能很大
解决方案:使用二级/多级页表
5.3.3 两级和多级页表
一级页表存放二级页面的信息,......
最后一级存放对应的物理地址
地址的转化:
一级->二级->地址+偏移
使用多级页表会增加内存的访问次数
5.3.4 快表
翻译快表,缩写为TLB(Translation Look-Aside Buffer),用于加快地址翻译的过程。
- 加快了内存访问速度
- 缓存了从虚拟页面到物理页面的映射
具有快表的地址变换过程:先查询快表,若该页不在快表中,则再查询页表,并把该页的映射写入快表,快表若已满,则换出很久未查询的映射。
分页系统的缺陷:
- 共享困难:页面中只要有一行地址不能共享,整个页面就不能共享
- 每个进程占用一个虚拟地址空间,可能发生碰撞
解决方案:分段。
5.4 分段存储管理
5.4.1 分段存储管理的引入
为了满足下列一系列需要
- 方便编程
- 分段共享
- 分段保护
- 动态链接
- 动态增长
5.4.2 分段系统的基本原理
-
分段系统把一个程序按照逻辑单元分成多个程序段
-
每一段使用自己单独的虚地址空间
-
依旧是离散的存储方式
-
注意:并不是所有虚拟地址都有效
- 有效意味着该区域是进程虚拟地址空间的一部分
- 无效意味着虚拟地址是非法的
物理地址=基址+段内偏移
-
保护:不同的段可以有不同的保护
-
使用段表储存分段信息
分页 | 分段 |
---|---|
提高内存利用率 | 满足用户需要 |
一个线性地址空间 | 多个线性地址空间 |
整个地址空间可以超过内存尺寸 | 整个地址空间可以超过内存尺寸 |
程序和数据不可单独保护 | 可以实现单独保护程序数据 |
尺寸不易变化 | 尺寸容易变化 |
不可以共享程序 | 可以共享程序 |
如何结合两者优点:段页式内存管理
- 将程序分为多个逻辑段
- 每个段里又进行分页
段页式地址管理的地址变换机构:
5.5 虚拟存储器管理
5.5.1 虚拟存储器的概念
计算机系统的内存容量是有限的,而传统存储器管理中,如果一个作业要运行,作业的全部信息必须装入内存。这限制了运行作业的大小以及数量。通过研究发现,进程执行时并非同时需要作业的全部信息,可以将这些暂时不使用的信息调出内存。
将外存作为内存的补充,从逻辑上扩充内存,是虚拟存储管理的基本思想
程序和数据的访问具有如下特点:
- 顺序性
- 局限性
- 多次性
- 独立性
虚拟存储器的定义:是指具有请求调入功能和置换功能,能够从逻辑上对内存空间进行扩展,允许用户的逻辑地址空间大于物理内存地址空间的存储管理系统。
- 虚拟存储器中,一般将硬盘作为外存,因此,硬盘也被称为对换设备
- 虚拟存储器的基础是内存的离散管理,实现的方式为请求分页式虚拟存储器管理或请求分段式虚拟存储器管理
- 请求分页式虚拟存储器管理
- 以页为单位置换
- 需硬件支持
- 请求分页的页表机构
- 缺页中断机构
- 地址变化机构
- 需实现请求分页的软件
- 用于实现请求调页的软件
- 实现页面置换的软件
- 请求分段式虚拟存储器管理
- 以段为单位置换
- 需硬件支持
- 请求分段的段表机构
- 缺段中断机构
- 地址变化机构
- 需实现请求分段的软件
- 用于实现请求调段的软件
- 实现段面置换的软件
- 虚拟存储器的特征
- 多次型:最重要的特征
- 对换性
- 虚拟性