基础知识

操作系统

操作系统(Operation System, OS
)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”三的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行。

* 操作系统是计算机系统资源的管理者:
* 处理机管理
* 存储器管理
* 设备管理
* 文件管理
* 操作系统是用户与计算机硬件系统之间的接口,同时也是计算机硬件和其他软件的接口:
* 命令接口
* 程序接口

* 功能:
* 管理计算机系统的硬件、软件及数据资源;
* 控制程序运行;
* 改善人机界面;
* 为其他应用软件提供支持,让计算机系统所有资源最大限度地发挥作用;
* 提供各种形式的用户界面,使用户有一个好的工作环境;
* 为其他软件的开发提供必要的服务和相应的接口等。
* 特征:
* 并发:两个或者多个事件在同一时间间隔内发生;
* 共享:系统中的资源可供内存中多个并发执行的进程共同使用;
* 虚拟:把一个物理上的实体变为若干个逻辑上的对应物;
* 异步:在多道程序环境下,允许多个程序并发执行,但因资源有限,进程的执行不是一贯到底,而是走走停停,以不可预知的速度向前推送,这就是进程的异步性。
基本概念

*
互斥:进程之间访问临界资源时相互排斥的现象;

临界资源:一次仅允许一个进程使用的资源,如 打印机。
临界区:每个进程中访问临界资源的那段代码。

* 并发:同一时间段有几个程序都处于已经启动到运行完毕之间,并且这几个程序都在同一个处理机上运行,并发的两种关系是同步和互斥;
* 并行:
单处理器中进程被交替执行,表现出一种并发的外部特征;在多处理器中,进程可以交替执行,还能重叠执行,实现并行处理,并行就是同时发生的多个并发事件,具有并发的含义,但并发不一定是并行,也就是说事件之间不一定要同一时刻发生;
* 同步:进程之间存在依赖关系,一个进程结束的输出作为另一个进程的输入。具有同步关系的一组并发进程之间发送的信息称为消息或者事件;
* 异步:和同步相对,同步是顺序执行,而异步是彼此独立,在等待某个事件的过程中继续做自己的事,不要等待这一事件完成后再工作。
线程是实现异步的一个方式,异步是让调用方法的主线程不需要同步等待另一个线程的完成,从而让主线程干其他事情。
*
多线程:多线程是进程中并发运行的一段代码,能够实现线程之间的切换执行;

异步和多线程:不是同等关系,异步是目的,多线程只是实现异步的一个手段,实现异步可以采用多线程技术或者交给其他进程来处理。

发展历程

* 手工阶段
* 单道批处理系统
* 多道批处理系统
* 分时操作系统
* 实时操作系统
*
网络操作系统和分布式操作系统

网络操作系统和分布式操作系统的不同之处在于:
在分布式操作系统中,若干台计算机相互协同完成同一任务;
而在网络操作系统中,每台计算机都是相互独立的,它们并不能相互协同完成同一任务。

CPU的工作状态

大多数计算机系统将CPU执行状态分为目态与管态。
管态就是 supervisor(管理者) mode翻译来的。
那么目态呢,其实是object(目标) mode翻译来的。

*
管态:supervisor(管理者) mode又叫特权态、系统态或者核心态。CPU在管态下可以执行指令系统的全集。

如果程序处于管态,则该程序就可以访问计算机的任何资源,即 它的资源访问权限不受限制。

通常,操作系统在管态下运行。

*
目态:object(目标)
mode又叫常态或用户态。机器处于目态时,程序只能执行非特权指令,不能直接使用系统资源,也不能改变CPU的工作状态,并且只能访问这个用户程序自己的存储空间。

科普:为什么叫object mode呢?
通常CPU执行两种不同性质的程序:一种是操作系统内核程序;另一种是用户自编程序或系统外层的应用程序。
对操作系统而言,这两种程序的作用不同,前者是后者的管理者,因此“管理程序”要执行一些特权指令,而“被管理程序”出于安全考虑不能执行这些指令。
因为管理者需要管理它,它就是管理者的管理目标。所以就叫object mode。

* 目态(用户态)→管态(核心态)
* 系统调用:这是用户态进程主动要求切换到核心态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。
系统调用机制的核心是使用了操作系统为用户开放的一个中断来实现。
* 异常:当CPU在执行用户态程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了核心态,如 缺页异常。
*
I/O设备的中断:当I/O设备完成用户请求操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令,转而去执行与中断信号对应的处理程序
,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到核心态的切换。

例如,硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中,执行后续的操作。

其中,系统调用可以认为是用户进程主动发起的,异常和外部设备中断则是被动的。

管理功能

* 处理机管理:
* 进程控制:
在传统多道程序环境中,要是作业运行,必须先为它创建一个或多个进程,并为之分配必要的资源。当进程运行结束后,立即撤销该进程,以便能及时回收该进程所占用的各类资源。
* 进程同步:为多个进程(含线程)的运行进行协调。
* 进程互斥方式:进程(线程)在对临界资源进行访问时,应采用互斥方式。
* 进程同步方式:在相互合作去完成共同任务的诸进程(线程)间,由同步机构对它们的执行次序加以协调。
* 进程通信:
在多道程序环境下,为了加速应用进程的运行,应在系统中建立多个进程,并且再为一个进程建立若干个线程,由这些进程(线程)相互合作去完成一个共同的任务,而在这些进程(线程)之间又往往需要交换信息。
* 调度:在后备队列上等待的每个作业或者进程,通常都需要调度才能执行,调度的任务,即 将处理机分配给它。
* 存储器管理:
* 内存分配:采用静态和动态两种方式实现内存分配数据结构,以记录内存使用情况,按照一定算法分配,怼不再需要的内存进行回收。
* 内存保护:确保每道用户程序都只在自己的内存空间运行,彼此互不干扰。
*
地址映射:
编译后的程序的地址分为逻辑地址和物理地址,多道程序环境中,每道程序不可能都从“0”地址开始,要保证程序运行,则须将逻辑地址转换成内存空间中的物理地址。

动态重定位:在程序执行过程中,每当访问指令或数据时,将要访问的程序或数据的逻辑地址转换成物理地址。

实现方法:
在系统中增加一个重定位寄存器,用来装入程序在内存中的起始地址,程序执行时,真正访问的内存地址是相对地址于重定向寄存器中的地址相加之和,从而实现动态重定位。

* 内存扩充:从逻辑上去扩充内存容量,使用户所感受到的内存容量比实际容量大得多,或者让更多的程序能并发执行。
* 设备管理:
* 缓冲管理:缓冲区机制能够有效缓解CPU运行的高速性和I/O低速性的矛盾。
* 设备分配:设置设备控制表、控制器控制表等数据结构,能够了解指定设备当前是否可用,是否忙碌,以及该设备被分配出去,系统是否还安全。
* 设备处理程序:
实现CPU和设备管理器之间的通信,由CPU向设备控制器发出I/O命令,要求它完成指定的I/O操作,反之由CPU接收从控制器发来的中断请求,并给与迅速的响应和相应的处理。
* 文件管理:
* 文件存储空间的管理:由文件系统对诸多文件及文件的存储空间实施统一的管理,对每个文件分配必要的外存空间,提高外存的利用率和文件系统的执行速度。
* 目录管理:相当于文件的索引,建立目录项(文件名、文件属性、文件在磁盘中的物理位置等),方便用户查询检索。
* 文件的读/写管理和保护:防止未经批准的用户存取文件、防止冒名顶替存取文件、防止以不正确的方式使用文件。
进程与线程

对于操作系统来说,一个任务就是一个进程(Process)
,比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为
线程(Thread)。

类比:
进程=工厂
线程=工厂里各个流水线

进程

进程可以认为是程序执行时的一个实例。进程是系统进行资源分配的独立实体,且每个进程拥有独立的地址空间。(即 资源的分配和调度的一个独立单元)
进程控制块(Process Control Block, PCB):保存运行期间进程的数据,PCB是进程存在的唯一标志。

* 进程=程序+数据+PCB
* 一个进程无法直接访问另一个进程的变量和数据结构,如果希望让一个进程访问另一个进程的资源,需要使用进程间通信,比如:管道、文件、套接字等。
进程的五种基本状态及其转换:


* 创建状态:
进程正在被创建,尚未转到就绪状态,创建进程需要申请一个空白的PCB,并向PCB写一些控制和管理进程的信息,然后由系统分配资源,将进程转入就绪状态。
* 就绪状态:进程已处于准备执行的状态,获得了除处理机以外的一切所需资源。
* 执行状态:进程在处理机上运行。在单处理机环境下,每一时刻最多只有一个进程运行。
* 阻塞状态:进程正在等待某一事件而暂停运行,如等待某资源变为可用(不包括处理机)或等待输入输出I/O完成,即使处理机空闲,该进程也不能运行。
* 结束状态:
进程正从系统中消失,这可能是进程正常结束或其他原因中断退出运行,当进程需要结束运行时,系统首先必须置该进程为结束状态,然后再进一步处理资源释放和回收。
注意:后备队列在外存中,而就绪队列在内存中。

进程同步与互斥

PV操作是一种实现进程互斥与同步的有效方法。PV操作与信号量的处理相关,P表示通过(pass)的意思,V表示释放(荷兰语v开头)的意思。

在操作系统中,信号量S是一整数。
S大于或等于零,代表可供并发进程使用的资源实体数;
在S小于零时,S表示正在等待使用资源实体的进程数。
建立一个信号量必须说明此信号量所代表的意义并且赋初值。
除赋初值外,信号量仅能通过PV操作来访问。

* 信号量S(semaphore)代表“资源数”
* P操作的主要动作是:通过(pass)(即 使用资源)
*
S减1;

类比:“占用了一个资源”

*
若S减1后仍大于或等于0,则进程继续执行;

类比:“若占用一个资源后,还有多余的资源或者刚好用完资源,那么就代表该进程有资源可以利用,进程也就可以继续执行”

*
若S减1后小于0,则该进程被阻塞后放入等待该信号量的等待队列中,然后转进程调度。

类比:“若占用一个资源后,还欠别人资源,那么就代表该进程根本就没有资源可以用了,如果再用就要欠债了,所以等待”

* V操作的主要动作是:释放(荷兰语v开头)(即 释放资源)
*
S加1;

类比:“资源占用完了,物归原主,释放资源”

*
若相加后结果大于0,则进程继续执行;

类比:“若释放资源后,资源数大于0,就代表库存里还有资源可以给你利用,那就继续执行”

*
若相加后结果小于或等于0,则从该信号的等待队列中释放一个等待进程,然后再返回原进程继续执行或转进程调度。

类比:“若释放资源后,资源数还是欠别人的或者为0,就代表库存里没有资源可以利用了,所以等待”

注意:PV操作对于每一个进程来说,都只能进行一次,而且必须成对使用。

进程通信

根据交换信息量的多少和效率的高低,进程通信分为如下低级通信和高级通信。

*
低级通信:只能传递状态和整数值(控制信息)。

由于进程的互斥和同步,需要在进程间交换一定的信息,故不少学者将它们也归为进程通信。

* 特点:传送信息量小,效率低,每次通信传递的信息量固定,若传递较多信息则需要进行多次通信。
* 编程复杂:用户直接实现通信的细节,容易出错。
* 高级通信:提高信号通信的效率,传递大量数据,减轻程序编制的复杂度。
提供三种方式:
* 共享内存模式
* 消息传递模式
* 共享文件模式
共享内存模式

在通信进程之间存在一块可直接访问的共享空间,通过对这片共享空间进行写/读操作,实现进程之间的信息交换。

在对共享空间进行写/读操作时,需要同步互斥工具(如 P操作、V操作),对共享空间的写/读进行控制。

类比:
进程=物品
共享空间=钱
用钱进行交换,而不用物物交换

消息传递模式

在消息传递模式中,进程间的数据交换是以格式化的消息(Message)为单位的。
进程通过系统提供的发送消息和接收消息两个原语进行数据交换。


若通信进程之间不存在可直接访问的共享空间,则必须利用操作系统提供的信息传递方法实现进程通信。

可分为直接和间接两种通信方式:

* 直接:将消息发送给接收进程,并将它挂在接收进程的信息缓冲队列中,接收进程从消息缓冲队列中取得消息。
*
间接:将消息发送给某个中间实体(信箱),接受进程从中间实体中取得消息,又称为信箱通信方式。

类比:
甲给乙写信
直接:甲直接把信交给乙
间接:甲通过邮差把信交给乙

共享文件模式

共享文件:用于连接一个发送进程和一个接收进程,以实现它们之间通信的文件,就是共享文件,又名pipe(管道)文件。
向管道提供输入的发送进程,以字节流形式将大量的数据送入管道;
而接收管道输出的接收进程,则从管道中接收数据。


为了协调双方的通信,管道机制必须提供互斥、同步和确定对方存在三方面的协调能力。

线程

对线程最基本的理解就是“轻量级进程”,它是一个基本的CPU执行单元,也是程序执行流的最小单元,由线程ID、程序计数器、寄存器集合和堆栈组成。(即
CPU调度的基本单元)
线程控制块(Thread Control Block, TCB):保存运行期间线程的数据,TCB是线程存在的唯一标志。

* 线程属于进程是进程的一个实体,是被系统独立和分配的基本单位。
* 线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可以与同属一个进程的其他线程共享进程所拥有的全部资源。
* 一个进程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。
区别

* 进程是资源分配和调度的一个独立单元;
而线程是CPU调度的基本单元。
* 同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包括一个线程。
* 进程的创建调用fork或者vfork,而线程的创建调用pthread_create;
进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束。
* 线程是轻量级的进程,它的创建和销毁所需要的时间比进程小很多,所有操作系统中的执行功能都是创建线程去完成的。
* 线程中执行时一半都要进行同步和互斥,因为它们共享同一进程的所有资源。
* 线程有自己的私有属性TCB、线程id、寄存器、硬件上下文;
而进程也有自己的私有属性进程控制块PCB,
这些私有属性是不被共享的,用来表示一个进程或一个线程的标志。
处理机调度

* 高级调度:(作业调度)根据某种算法,把外存上处于后备队列中那些作业调入内存。
* 中级调度:(内存调度)将那些暂时不能运行的进程调至外存等待,把进程状态改为就绪驻外存状态或挂机状态。
* 低级调度:(进程调度)按照某种算法从就绪队列(内存)中选取一个进程,将处理机分配给它。
调度算法

调度算法是根据系统的资源分配策略所规定的资源分配算法。
有的调度算法适用于作业调度,有的适用于进程调度,有的两种都适用。

* 周转时间=等待时间+执行时间
先来先服务调度(FCFS)

先来先服务调度(First Come First Service, FCFS):按照作业/进程进入系统的先后次序进行调度,先进入系统者先调度,即 启动
等待时间最长的作业/进程。

* 适用性:作业调度、进程调度。
* 优点:
* 算法简单
* 对长作业/进程有利(短的要等好久)
*
有利于CPU繁忙型作业/进程

CPU繁忙意味着是长作业,不需要频繁的输入输出

* 缺点:
* 效率低
*
对短作业/进程不利

因为短作业执行时间很短,若令它等待较长时间,则带权周转时间会很高。

*
不利于I/O繁忙型作业进程

I/O繁忙意味着不停地中断完成,是短作业

短作业优先调度(SJF)

短作业优先调度(Shortest Job First, SJF):该算法每次从后备队列/就绪队列中选择一个估计时间最短的作业/进程,将资源分配给它。

* 适用性:作业调度、进程调度。
* 优点:
* 平均等待时间和平均周转时间最少
* 缺点:
* 对长作业/进程不利(可能导致长作业/进程长期不被调度,发生“饥饿”现象)
* 不能保证紧迫性作业/进程会被及时处理
*
由于作业/进程的长短只是根据客户说提供的估计执行时间而定的,而用户有可能会有意或无意地缩短气作业的估计运行时间,致使该算法不一定能真正做到短作业优先调度。
优先级调度

优先级调度:该算法每次从后备队列/就绪队列中选择优先级最高的一个作业/进程,将资源分配给它。

* 适用性:作业调度、进程调度。
根据新的更高优先级进程能否抢占正在执行的进程,可将该调度分为:

* 非抢占式优先级调度算法:
当有进程正在处理机上运行时,即使有更高优先级的进程进入就绪队列,也需等待当前进程运行完成,等待主动让出处理机后,才把处理机分配给高优先级的进程。
* 抢占式优先权调度算法:

当有进程正在处理机上运行时,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。
高响应比优先调度(HRRN)

高响应比优先调度(Highest Response Ratio Next,
HRRN):该算法是对FCFS调度算法和SJF调度算法的一种综合平衡,同时考虑每个作业的等待时间和估计的运行时间。

在每次进行作业调度时,先计算后备作业队列中每个作业的响应比,从中选出响应比最高的作业投入运行。

响应比=作业周转时间/作业执行时间=(等待时间+要求服务时间)/要求服务时间

* 适用性:主要用于作业调度
* 优点:
* 等待时间相同的作业,要求服务的时间越短,其优先权越高,此时对短作业有利;
* 等待时间相同的作业,等待时间越长,其优先权越高,此时等同于先来先服务调度算法;
* 对于长作业,优先权随等待时间的增加而提高,其等待时间足够长时,其优先权便可提升到很高,从而也可获得处理机,此时对长作业有利,克服了饥饿状态。
* 缺点:
* 要进行响应比计算,增加了系统开销。
时间片轮转调度

该算法将所有就绪进程按到达的先后次序排成一个队列,每次调度时,把处理机分配给队首进程,并令其执行一个时间片;
当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便停止该进程的执行,并将其放到就绪队列尾;
然后,再把处理机分配给就绪队列中新的队首。

* 适用性:主要用于分时系统中进程调度
多级反馈队列调度

该算法是时间片轮转调度算法和优先级调度算法的综合和发展,通过动态调整进程优先级和时间片大小,可以兼顾多方面的系统目标。

设置多个就绪队列,并赋予不同优先级,优先级越高,时间片越小
,进程在进入待调度的队列等待时,首先进入优先级最高的Q1等待,一个时间片结束后,若进程没有运行完,则转入低一级的就绪队列队尾,仅当高优先级队列中无就绪进程才开始调度低一级的就绪队列中的进程(若此刻有进程进入了高优先级队列中,那么要先转去调用高优先级队列)。

* 例子:
假设系统中有3个反馈队列Q1,Q2,Q3,时间片分别为2,4,8。
设有3个作业J1,J2,J3分别在时间 0 ,1,3时刻到达。而它们所需要的CPU时间分别是3,2,1个时间片。
* 时刻0 J1到达。于是进入到队列1 , 运行1个时间片 , 时间片还未到,此时J2到达。
* 时刻1 J2到达。 由于同一队列采用先来先服务,于是J2等待。
J1在运行了1个时间片后,已经完成了在Q1中的2个时间片的限制,于是J1置于Q2等待被调度。当前处理机分配给J2。
* 时刻2 J1进入Q2等待调度,J2获得CPU开始运行。
* 时刻3 J3到达,由于同一队列采用先来先服务,故J3在Q1等待调度,J1也在Q2等待调度。
* 时刻4 J2处理完成,由于J3,J1都在等待调度,但是J3所在的队列比J1所在的队列的优先级要高,于是J3被调度,J1继续在Q2等待。
* 时刻5 J3经过1个时间片,完成。
*
时刻6 由于Q1已经空闲,于是开始调度Q2中的作业,则J1得到处理器开始运行。J1再经过一个时间片,完成了任务。于是整个调度过程结束。

从上面的例子看,在多级反馈队列中,后进的作业不一定慢完成。

死锁

死锁是指多个进程因竞争临界资源而造成的一种僵局(互相等待),若无外力作用,这些进程都无法向前推进。

* 产生死锁的根本原因是系统能够提供的资源个数比要求该资源的进程数要少。
* 产生死锁的基本原因:
*
资源竞争

例子:
A有纸,B有笔
A:你不给我笔,我就写不完作业
B:你不给我纸,我就写不了作业
彼此僵持不下。。

*
进程推进顺序非法

例子:
A要前进2步,到桌子前,再后退2步,结果顺序非法:
A先后退,就永远到不了桌子前,触发不了,死锁

* 产生是死锁的必要条件:
* 互斥条件:涉及的资源是非共享的,即 一次只有一个进程使用。如果有另一个进程申请该资源,那么申请进程必须等待,直到该资源被释放。
* 不剥夺条件(非抢占):进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即 只能由获得该资源的进程自己来释放。
* 占有并等待(部分分配):进程每次申请它所需要的一部分资源。在等待一新资源的同时,进程继续占用已分配到的资源。
*
环路条件(循环等待):存在一种进程循环链,链中每一个进程已获得的资源同时被链中下一个资源所请求。

注意:这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立;
反之,只要上述条件之一不满足,就不会发生死锁。

处理策略

预防死锁

预防死锁:通过设置一些限制条件,破坏死锁的一些必要条件,让死锁无法发生。

避免死锁

避免死锁:在动态分配资源的过程中,用一些算法(如 银行家算法)防止系统进入不安全状态,避免死锁的发生。

银行家算法

Dijkstra E W于1968年提出银行家算法。之所以称为银行家算法,是因为该算法可用于银行系统。

新进程进入系统时,它必须说明各类资源类型的实例的最大需求量,这一数量不能超过系统各类资源的总数。

当进程申请一组资源时,该算法需要检查申请者怼各类资源的最大需求量,如果系统现存的各类资源的数量可以满足当前它怼各类资源的最大需求量时,就满足当前的申请;否则,进程必须等待,直到其他进程释放足够的资源为止。
换言之,仅当申请者可以在一定时间内无条件地归还它所申请的全部资源时,才能把资源分配给它。

死锁的检测及解除

死锁的检测及解除:在死锁发生前不做任何操作,只是检测当前是否发生死锁,若发生死锁,则采取一些措施(如 资源剥夺法、撤销进程法、进程回退法)来解除死锁。

主存管理

分区存储管理

在分区存储管理中,程序的地址空间是一维线性的,因为指令或操作数地址只要给出一个信息量即可决定。

分区存储管理中常用的分配策略有:首次适应算法、循环首次适应算法、最佳适应算法和最坏适应算法。

首次适应算法

首次适应算法:按地址从小到大排序,分配第一个符合条件的分区。

* 优点:
* 保留高地址部分的大空闲区,有利于后来的大型作业分配。
* 缺点:
* 低地址部分被不断划分,留下许多难以利用的小空闲区;
* 每次分配时都要从低地址部分开始查找,增加查找时的系统开销。
循环首次适应算法

循环首次适应算法:在首次适应算法的基础上,从上次查找结束的位置开始查找,分配第一个符合的分区。

* 优点:
* 使内存中的空闲分区分布更均匀,减少了查找时的系统开销。
* 缺点:
* 缺乏大的空闲区,可能导致不能装入大型作业。
最佳适应算法

最佳适应算法:是按空间从小到大排序,分配第一个符合条件的分区。

* 优点:
* 每次分配的空闲区都是最合适的
* 缺点:
* 在内存中留下许多难以利用的小空闲区
最坏适应算法

最坏适应算法:是按地址从大到小排序,分配第一个符合条件的分区。

* 优点:
* 产生碎片的几率最小,对中小型作业有利。
* 缺点:
* 缺乏大的空闲区,对大型作业不利。
页式存储管理

在页式存储管理中,程序的地址空间是一维线性的,因为指令或操作数地址只要给出一个信息量即可决定。

理解:页式存储管理只用给出一个逻辑地址就行,因为页的大小是固定的,逻辑地址÷页的大小=页号...余 偏移量,所以是地址空间一维的,只用一个逻辑地址。

页面置换算法

在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断。
当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做
页面置换算法。

抖动(颠簸):是指在页面置换过程中,刚刚调出的页面马上又要调入内存,刚刚调入的页面马上又要调出,发生频繁的页面调度行为。

* 缺页中断率=成功访问次数/总访问次数
* 最佳置换算法(OPTimal replacement, OPT
):将以后永不使用的或者在最长时间内不会被访问的页面调出,但由于人们无法预知进程在内存下的若干页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。
*
先进先出置换算法(First In First Out, FIFO):将最早进入内存的页面调出。

该算法会产生Belady异常,即 发生缺页时,如果对一个进程未分配它所要求的全部页面,有时分配页数↑,缺页率反而↑
的异常现象。(先进先出,结果进来了一个需要的页,也出去了一个需要的页)

* 最近最久未使用置换算法(Least Recently Used, LRU
):是将最近最长时间未访问的页面调出。该算法为每个页面设置一个访问字段,记录页面上次被访问以来所经历的时间,调出页面时选择时间最长的页面。
* 最不经常使用置换算法(Least Frequently Used ,LFU):将最近应用次数最少的页淘汰。
*
时钟置换算法(CLOCK):也称为最近未用算法(NRU
),该算法是为每个页面设置一个使用位,需要替换页面时,循环检查各个页面,将使用位为1的页面重置为0(使用时再置为1),直到遇到第一个使用位为0的页面,将其调出。
如果在每个页面再增加一个修改位,则得到改进型的CLOCK置换算法,类似的,需要替换页面时,将使用位和修改位都为0的页面调出。

段式存储管理

段式存储管理的用户地址是二维的、按段划分的。

理解:段式存储管理必须给出(段号,偏移量),因为段的大小不固定,必须给出这两个,所以是二维的。

在这样的系统中作业的地址空间由若干逻辑分段组成,每个分段有自己的名字,对于一个分段而言,它是一个连续的地址区。

* 由于标识某一程序地址时,要同时给出段名和段内地址,因此地址空间是二维
的(实际上,为了实现方便,在第一次访问某段时,操作系统就用唯一的段号来代替该段的段名)。
* 程序地址的一般形式由(s,w)组成,这里s是段号,w是段内位移。
段号 段内位移
s w
分页和分段的异同

* 相同点:
* 分页和分段都采用离散分配(也就是不连续的分配地址,类似于链表)的方式
* 都要通过地址映射机构来实现地址变换
* 不同点:
* 从功能上看,
页是信息的物理单位,分页是为实现离散分配方式,以消除内存的外零头,提高内存利用率,是为了满足系统管理的需要;
而段是信息的逻辑单位,它含有一组意义相对完整的信息,是为了满足用户的需要。
* 页的大小是由系统确定且固定不变的;
而段的长度不固定,取决于用户编写的程序。
* 分页的作业地址空间是一维的;
而分段的作业地址空间是二维的。
段页式存储管理

段页式存储管理的用户地址也是二维的、按段划分的。只是在段中再划分成若干大小相等的页。

理解:段页式存储管理也必须给出(段号,偏移量),虽然段的大小不固定,但是段内页号和页内偏移可以根据偏移量算出来,所以还是二维的。

*
地址结构就由段号、段内页号、页内位移三部分组成。

注意:不要看三部分就是三维的了,其实用户使用的部分也是二维的。

段号 段内页号 页内位移
*
用户使用的仍是段号和段内相对地址,
由地址变换机构自动将段内相对地址的高几位解释为段内页号,将剩余的低位解释为页内位移。

*
用户地址空间的最小单位不是段而是页,而主存按页的大小划分,按页装入。

这样,一个段可以装入到若干个不连续的主存块内,段的大小不再受主存可用区的限制了。

虚拟存储器

虚拟存储器:是指具有请求调入功能和置换功能,并能从逻辑上对内存容量加以扩充的一种存储器系统。

* 局部性原理:是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储单元都趋于聚集在一个较小的连续区域中。
*
时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。

程序循环、堆栈等是产生时间局部性的原因。

* 空间局部性(Spatial Locality):在最近的将来将用到的信息很可能与正在使用的信息在空间地址上是临近的。
*
顺序局部性(Order
Locality):在典型程序中,除转移类指令外,大部分指令是顺序进行的。顺序执行和非顺序执行的比例大致是5:1。此外,对大型数组访问也是顺序的。

指令的顺序执行、数组的连续存放等是产生顺序局部性的原因。

虚拟存储器基于局部性原理,在程序装入时,可以只将程序的一部分装入内存,就可以启动程序执行。
在执行过程中,当所访问的信息不在内存中时,由操作系统将所需内容调入内存,使程序继续执行;
同时,操作系统将内存中暂时不用的内容调出到外存。

这样,系统就好像为用户提供了一个比实际内存大得多的存储器,称为虚拟存储器。

* 特征:
* 离散性:
是指内存分配时采用离散分配的方式。若采用连续分配方式,需要将作业装入到连续的内存区域,这样需要连续地一次性申请一部分内存空间,无法实现虚拟存储功能,只有采用离散分配方式,才能为它申请内存空间,以避免浪费内存空间。
* 多次性:作业无需在运行时一次性全部装入内存,而是可以分成多次调入内存。
* 对换性:作业运行时无需常驻内存,可以进行调入调出。
* 虚拟性:从逻辑上扩充了内存的容量,使用户所感觉到的内存容量远大于实际容量。
文件系统

文件分配

文件分配对应于文件的物理结构,是指如何为文件分配磁盘块(外存)。

常用的磁盘空间分配方法有三种:

* 连续分配:要求每个文件在磁盘上占有一组连续的块。
* 链接分配:采取离散分配的方式,分为隐式链接分配和显式链接分配。
* 隐式链接分配:每个文件对应一个磁盘块的链表,磁盘块任意分布,除最后一个盘块外,每一个盘块都有指向下一个盘块的指针(类似于数据结构中的链表)。
* 显式链接分配:
把用于链接文件各物理块的指针提取出来,显示地存放在内存里的一张链接表中,该表整个磁盘仅设置一张,由于分配给文件的所有盘块号都放在该表中,故称该表为文件分配表(FAT)。
* 索引分配:把每个文件的所有盘块号集中在一起构成索引块(表)。
磁盘调度算法

* 先来先服务算法(First Come First Service, FCFS):根据进程请求访问磁盘的先后顺序进行调度。
*
最短寻找时间优先算法(Shortest Seek Time First, SSTF):选择处理的磁道是与当前磁头所在磁道距离最近的磁道,使每次的寻找时间最短。

该算法会产生“饥饿”现象。

*
扫描算法(SCAN):也叫电梯算法,在磁头当前移动方向上选择与当前磁头所在距离最近的请求作为下一次服务的对象。

实际上是在SSTF算法的基础上规定了磁头运动的方向。

*
循环扫描算法(Cyclic SCAN, C-SCAN):在SCAN算法的基础上规定磁头单向移动来提供服务,到达磁盘端点返回时,直接快速返回起始端。

若磁头移动到最远端的请求后,即刻返回,而不是到达端点再返回,则将改进后的SCAN算法和C-SCAN算法称为LOOK算法和C-LOOK算法。

I/O管理

I/O控制方式

*
程序I/O方式:
计算机从外部设备读取数据到存储器,每次读取一个字的数据。对读入的每个字,CPU需要对外设状态进行循环检查,直到确定该字已经在I/O控制器的数据寄存器中。

该方式适用于早期的无中断计算机系统中。
CPU和I/O设备只能串行工作,导致CPU的利用率相当低。

*
中断驱动I/O控制方式:允许I/O设备主动打断CPU的运行并请求服务,从而使CPU在对I/O控制器发送命令后可以做其他工作。

该方法普遍用于现代的计算机系统中。
由于数据中每个字在存储器与I/O控制器之间 的传输都必须经过CPU,仍然会小号CPU较多的时间。

*
DMA I/O控制方式:在I/O设备和内存之间开辟直接的数据交换通路,数据的基本单位是数据块,所传送的数据是从设备直接送入内存;
或者相反,仅在传送数据块的开始和结束时需要CPU干预,数据传送是在DMA控制器的控制下完成的。

该方法适用于I/O设备为块设备时和主机进行数据交换。

块设备是I/O设备中的一类,是将信息存储在固定大小的块中,每个块都有自己的地址,还可以在设备的任意位置读取一定长度的数据,例如硬盘,U盘,SD卡等。

直接内存存取(Direct Memory Access, DMA
)是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于CPU的大量中断负载。
否则,CPU需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU对于其他的工作来说就无法使用。

*
I/O通道控制方式:是DMA方式的发展,只在一组数据的传输开始和结束时需要CPU干预,可以实现CPU、通道和I/O设备三者的并行操作。

该方式适用于设备与主机进行数据交换是一组数据块的情况,使用该方法要求系统必须配置相应的通道及通道控制器。

缓冲区

引入缓冲区的目的是什么?

* 缓和CPU与I/O设备间速度不匹配的矛盾;
* 减少对CPU的中断频率,放宽对CPU中断响应时间的限制;
* 解决基本数据单元大小(即 数据粒度)不匹配的问题;
* 提高CPU和I/O设备之间的并行性。