并发
共享
虚拟
异步
并发和共享是两个最基本的特征,二者互为存在条件。
并发:指两个或多个事件在同一时间间隔内发生。这些事件宏观上是同时发生的,但微观上是交替发生的。
并行:指两个或多个事件在同一时间同时发生。
操作系统的并发性是指计算机系统中同时存在着多个运行着的程序。
共享:即资源共享,是指系统中的资源可供内存中多个并发执行的进程共同使用。
虚拟:是指把一个物理上的实体变为若干个逻辑上的对应物。物理实体是实际存在的,而逻辑上的对应物是用户感受到的。
空分复用技术(如虚拟存储器技术)
时分复用技术(如虚拟处理机)
没有并发性,就谈不上虚拟性。
异步:是指在多道程序环境下,允许多个程序并发执行,但由于资源有限,进程的执行不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。
只有系统拥有并发性,才可能导致异步性。
缺点:用户独占全机,人机速度矛盾导致资源利用率极低。
引入脱机输入/输出技术(用磁带完成),并监督程序负责控制作业的输入、输出。
优点:缓解了一定程度的人机速度矛盾,资源利用率有所提升。
缺点:内存中仅能有一道程序运行。CPU有大量的时间是在空闲等待I/O完成。资源利用率依然很低。
优点:多道程序并发执行,共享计算机资源。资源利用率大幅提升,CPU和其他资源保持“忙碌”状态,系统吞吐量增大。
缺点:用户响应时间长,没有人机交互功能。
分时操作系统:计算机以时间片为单位轮流为各个用户/作业服务,各个用户可以通过终端与计算机进行交互。
优点:用户请求可以被即时响应,解决了人机交互问题。允许多个用户同时使用一台计算机,并且用户对计算机的操作相互独立,感受不到别人存在。
缺点:不能优先处理一些紧急任务。操作系统对各个用户/作业都是完全公平的,循环地为每个用户/作业服务一个时间片,不区分任务的紧急性。
优点:能够优先响应一些紧急任务,某些紧急任务不需要时间片排队。
在实时系统控制下,计算机系统接收到外部信号后及时进行处理,并且要在严格的时限内处理完事件。
特点:及时性、可靠性
指令:CPU能识别、执行的最基本命令。
内核:是计算机上配置的底层软件,是操作系统最基本最核心的部分。
分类:大内核、微内核。
定义 | 优点 | 缺点 | |
---|---|---|---|
大内核 | 将操作系统的主要功能模块都作为系统内核,运行在核心态 | 高性能 | 内核代码庞大,结构混乱,难以维护 |
微内核 | 只把最基本的功能保留在内核 | 内核功能少,结构清晰,方便维护 | 需要频繁的在核心态和用户态之间切换,性能低 |
中断可以使CPU从用户态切换为核心态,使操作系统获得计算机的控制权。
程序:就是一个指令序列
进程实体(进程映像):PCB(进程存在的唯一标志)、程序段、数据段。
进程:是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
按照进程状态将PCB分为多个队列
操作系统持有指向各个队列的指针
按照进程状态不同,建立几张索引表
操作系统持有指向各个索引表的指针
用原语实现进程控制。
原语采用“关中段指令”和“开中段指令”实现。
原语是一种特殊的程序。
注:阻塞和唤醒必须成对出现。
两个进程对共享空间的访问必须是互斥的。
1、管道只能采用半双工 通信,某一时间段内只能实现单向的传输。
2、各进程要互斥地访问管道。
3、数据以字符流的形式写入管道,当管道写满时,写进程的write()系统调用将被阻塞,等待读进程将数据取走。当读进程将数据全部取走后,管道变空,此时读进程的read()系统调用将被阻塞。
4、如果没写满,就不允许读。如果没读空,就不允许写。
5、数据一旦被读出,就从管道中被抛弃,这就意味着读进程最多只能有一个,否则可能会有读错数据的情况。
进程间的数据交换以格式化的消息为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。
线程是一个基本的CPU执行单元,也是程序执行流的最小单位。
内核级线程才是处理机分配的单位。
内容:多个用户级线程映射到一个内核级线程。每个用户进程只对应一个内核级线程。
优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高。
缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。
内容:一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。
优点:当一个线程被阻塞后,别的线程还可以继续运行,并发能力强。多线程可在多核处理机上并行执行。
缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。
内容:n用户级线程映射到m个内核级线程(n>=m)。每个用户进程对应m个内核级线程。
克服了多对一模型并发度不高的缺点,又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。
内容:按一定的原则从外存上处于后备队列的作业中挑选一个(或多个)作业,给它们分配内存等必要资源,并建立相应的进程(PCB),以使他(们)获得竞争处理机的权利。
高级调度是辅存(外存)与内存之间的调度。每个作业只调入一次,调出一次。作业调入时会建立相应的PCB,作业调出时才撤销PCB。
高级调度主要是指调入问题,因为只有调入的时机需要操作系统来确定,但调出的时机必然是作业运行结束才调出。
引入虚拟存储技术后,可将暂时不能运行的进程调至外存等待。等它重新具备了运行条件且内存又稍有空闲时,再重新调入内存。
目的是为了提高内存利用率和系统吞吐量。
暂时调到外存等待的进程状态为挂起状态。值得注意的是,PCB并不会一起调到外存,而是会常驻内存。PCB中会记录进程数据在外存中存放的位置,进程状态等信息,操作系统通过内存中的PCB来保持对各个进程的监控、管理。被挂起的进程PCB会被放到挂起队列中。
内容:按照某种方法和策略从就绪队列中选取一个进程,将处理机分配给它。
进程调度是操作系统中最基本的一种调度。发生频率最高。
进程在操作系统内核程序临界区中不能进行调度与切换。
内核程序临界区:一般是用来访问某种内核数据结构的,比如进程的就绪队列。
非剥夺调度方式,又称非抢占方式。即,只允许进程主动放弃处理机。在运行过程中即便有更紧迫的任务到达,当前进程依然会继续使用处理机,直到该进程终止或主动要求进入阻塞态。
剥夺调度方式,又称抢占方式。当一个进程正在处理机上执行时,如果有一个更重要或更紧迫的进程需要使用处理机,则立即暂停正在执行的进程,将处理机分配给更重要更紧迫的那个进程。
狭义的进程调度:指的是从就绪队列中选中一个要运行的进程。
广义的进程调度:包含了选择一个进程和进程切换两个步骤。
进程切换:指一个进程让出处理机,由另一个进程占用处理机的过程。
进程切换的过程主要完成了:
1、对原来运行进程各种数据的保存
2、对新的进程各种数据的恢复
CPU利用率:CPU“忙碌”的时间占总时间的比例
利用率=忙碌时间/总时间
系统吞吐量:单位时间内完成作业的数量
系统吞吐量=总共完成了多少道程序/总共花了多少时间
周转时间:指从作业被提交给系统开始,到作业完成为止的这段时间间隔。
包括:
(作业)周转时间=作业完成时间-作业提交时间
平均周转时间=各作业周转时间之和/作业数
带权周转时间=作业周转时间/作业实际运行时间=(作业完成时间-作业提交时间)/作业实际运行的时间
平均带权周转时间=各作业带权周转时间之和/作业数
等待时间:指进程/作业处于等待处理机状态时间之和,等待时间越长,用户满意度越低。
进程:等待时间就是指进程建立后等待被服务的时间之和,在等待I/O完成的期间其实进程也是在被服务的,所以不计入等待时间。
作业:不仅要考虑建立进程后的等待时间,还要加上作业在外存后备队列中等待的时间
等待时间=周转时间-运行时间-(I/O操作的时间)
响应时间:指从用户提交请求到首次产生响应所用的时间。
先来先服务(FCFS) | |
---|---|
算法思想 | 从“公平”的角度考虑 |
算法规则 | 按照作业/进程到达的先后顺序进行服务 |
用于作业/进程调度 | 用于作业调度:考虑哪个作业先后到达后备队列; 用于进程调度:考虑哪个进程先后到达就绪队列 |
是否可抢占 | 非抢占式算法 |
优缺点 | 优点:公平、算法实现简单 缺点:排在长作业(进程)后面的短作业需要等待很长时间,带权周转时间很大,对短作业来说用户体验不好。即,FCFS算法对长作业有利,对短作业不利 |
是否会导致饥饿 | 不会 |
短作业优先(SJF) | |
---|---|
算法思想 | 追求最少的平均等待时间,最少的平均周转时间、最少的平均带权周转时间 |
算法规则 | 最短的作业/进程优先得到服务 |
用于作业/进程调度 | 几颗用于作业调度,也可用于进程调度。用于进程调度时成为“短进程优先(SPF)算法” |
是否可抢占 | SJF和SPF是非抢占式算法。但是也有抢占式版本——最短剩余时间优先算法(SRTN) |
优缺点 | 优点:“最短的”平均等待时间、平均周转时间 缺点:不公平。对短作业有利,对长作业不利。可能产生饥饿现象。另外,作业/进程的运行时间是由用户提高的,并不一定真实,不一定能做到真正的短作业优先 |
是否会导致饥饿 | 会。如果源源不断地有短作业/进程到来,可能使长作业/进程长时间得不到服务,产生“饥饿”现象。如果一直得不到服务,则称为“饿死” |
高响应比优先(HRRN) | |
---|---|
算法思想 | 要综合考虑作业/进程的等待时间和要求服务的时间 |
算法规则 | 在每次调度时先计算各个作业/进程的响应比,选择响应比最高的作业/进程为其服务 响应比=(等待时间+要求服务时间)/要求服务时间 |
用于作业/进程调度 | 既可用于作业调度,也可用于进程调度 |
是否可抢占 | 非抢占式算法。因此只有当前运行的作业/进程主动放弃处理机时,才需要调度,才需要计算响应比 |
优缺点 | 综合考虑了等待时间和运行时间(要求服务时间) 等待时间相同时,要求服务时间短的优先(SJF的优点) 要求服务时间相同时,等待时间长的优先(FCFS的优点) 对于长作业来说,随着等待时间越来越久,其响应比也会越来越大,从而避免了长作业饥饿的问题 |
是否会导致饥饿 | 不会 |
时间片轮转调度算法(RR) | |
---|---|
算法思想 | 公平地、轮流地为各个进程服务,让每个进程在一定时间间隔内都可以得到响应 |
算法规则 | 按照各进程到达就绪队列的顺序,轮流让各个进程执行一个时间片。若进程未在一个时间片内执行完,则剥夺处理机,将进程重新放到就绪队列队尾重新排队 |
用于作业/进程调度 | 用于进程调度 |
是否可抢占 | SJF和SPF是非抢占式算法。但是也有抢占式版本——最短剩余时间优先算法(SRTN) |
优缺点 | 优点:公平;响应快,适用于分时操作系统 缺点:由于高频率的进程切换因此有一定的开销;不区分任务的紧急程度 |
是否会导致饥饿 | 不会 |
优先级调度算法 | |
---|---|
算法思想 | 随着计算机的发展,特别是实时操作系统的出现,越来越多的应用场景需要根据任务的紧急程度来决定处理顺序 |
算法规则 | 调度时选择优先级最高的作业/进程 |
用于作业/进程调度 | 既可用于作业调度,也可用于进程调度。甚至,还会用于在之后会学习的I/O调度中 |
是否可抢占 | 抢占式、非抢占式都有。做题时的区别在于:非抢占式只需在进程主动放弃处理机时进行调度即可,而抢占式还需在就绪队列变化时,检查是否会发生抢占。 |
优缺点 | 优点:用优先级区分紧急程度、重要程度,适用于实时操作系统。可灵活地调整对各种作业/进程的偏好程度。 缺点:若源源不断地有高优先级进程到来,则可能导致饥饿 |
是否会导致饥饿 | 会 |
高响应比优先(HRRN) | |
---|---|
算法思想 | 对其他算法的折中权衡 |
算法规则 | 1. 设置多级就绪队列,各级队列优先级从高到低,时间片从小到大 2.新进程到达时先进入第1级队列,按FCFS原 则排队等待被分配时间片,若用完时间片进程还未结束,则进程进入下一-级队列队尾。如果此时已经是在最下级的队列,则重新放回该队列队尾 3. 只有第k级队列为空时,才会为k+1级队头的进程分配时间片 |
用于作业/进程调度 | 用于进程调度 |
是否可抢占 | 抢占式的算法。在k级队列的进程运行过程中,若更上级的队列(1~k-1级)中进入了一个新进程,则由于新进程处于优先级更高的队列中,因此新进程会抢占处理机,原来运行的进程放回k级队列队尾。 |
优缺点 | 对各类型进程相对公平(FCFS的优点) ; 每个新到达的进程都可以很快就得到响应(RR的优点) ; 短进程只用较少的时间就可完成(SPF的优点) ; 不必实现估计进程的运行时间( 避免用户作假) ; 可灵活地调整对各类进程的偏好程度,比如CPU密集型进程、I/O密集型进程 (拓展:可以将因I/0而阻塞的进程重新放回原队列,这样I/O型进程就可以保持较高优先级) |
是否会导致饥饿 | 会 |
并发性带来了异步性,有时候需要通过进程同步解决这种异步问题。
有的进程之间需要相互配合地完成工作,各进程的工作推进需要遵循一定的先后顺序。
对临界资源的访问,需要互斥的进行。即同一时间段内只能允许一个进程访问该资源。
算法思想:两个进程在访问完临界区 后会把使用临界区的权限转交给另一个进程。也就是说每个进程进入临界区的权限只能被另一个进程赋予。
主要问题:违背了“空闲让进”原则。
算法思想:设置一个布尔型数组flag[],数组中各个元素用来标记各进程想进入临界区的意愿,比如“flag[0] = ture"意味着0号进程PO现在想要进入临界区。每个进程在进入临界区之前先检查当前有没有别的进程想进入临界区,如果没有,则把自身对应的标志flag[i]设true,之后开始访问临界区。
主要问题:违反“忙则等待”原则。进入区的“检查”和“上锁”两个处理不是一气呵成的。“检查”后,“上锁”前可能发生进程切换。
算法思想:双标志先检查法的改版。前一个算法的问题是先“检查”后“上锁",但是这两个操作又无法一气呵成,因此导致了两个进程同时进入临界区的问题。因此,人们又想到先“上锁"后"检查”的方法,来避免.上述问题。
主要问题:解决了“忙则等待”的问题,但又违背了“空闲让进”和“有限等待”原则,会因各进程都长期无法访问临界资源而产生“饥饿”现象。
算法思想:双标志后检查法中,两个进程都争着想进入临界区,但是谁也不让谁,最后谁都无法进入临界区。Gary L. Peterson想到了一种方法,如果双方都争着想进入临界区,那可以让进程尝试“孔融让梨”,主动让对方先使用临界区。
主要问题:未遵循让权等待的原则。
利用“开/关中断指令”实现。
优点:简单、高效
缺点:不适用于多处理机;只适用于操作系统内核进程,不适用于用户进程
用硬件实现,执行过程不允许被中断,只能一气呵成。
优点:实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞;适用于多处理机环境。
缺点:不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,从而导致忙等。
用硬件实现,执行过程不允许被中断,只能一气呵成。
优点:实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞;适用于多处理机环境。
缺点:不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行Swap指令,从而导致忙等。
wait、signal原语常简称为P、V操作
用一个整数型的变量作为信号量,用来表示系统中某种资源的数量。
存在“忙等”问题。
用记录型数据结构表示的信号量。
P操作中,一定先S.value–,之后可能需要执行block原语。
V操作中,一定先S.value++,之后可能需要执行wakeup原语。
遵循了“让权等待”原则。
注:对不同的临界资源需要设置不同的互斥信号量。
组成:
基本特征:
死锁:各进程互相等待对方手里的资源,导致各进程都阻塞,无法向前推进的现象。
饥饿:由于长期得不到想要的资源,某进程无法向前推进的现象。比如:在短进程优先(SPF) 算法中,若有源源不断的短进程到来,则长进程将一直 得不到处理机,从而发生长进程“饥饿”。
死循环:某进程执行过程中一直跳不出某个循环的现象。有时是因为程序逻辑bug导致的,有时是程序员故意设计的。
区别 | |
---|---|
死锁 | 死锁一定是“循环等待对方手里的资源”导致的,因此如果有死锁现象,那至少有两个或两个以上的进程同时发生死锁。另外,发生死锁的进程一定处于阻塞态。 |
饥饿 | 可能只有一个进程发生饥饿。发生饥饿的进程既可能是阻塞态(如长期得不到需要的I/O设备),也可能是就绪态(长期得不到处理机) |
死循环 | 可能只有一个进程发生死循环。死循环的进程可以上处理机运行(可以是运行态),只不过无法像期待的那样顺利推进。死锁和饥饿问题是由于操作系统分配资源的策略不合理导致的,而死循环是由代码逻辑的错误导致的。死锁和饥饿是管理者(操作系统)的问题,死循环是被管理者的问题。 |
注:发生死锁时一定有循环等待,但是发生循环等待时未必死锁(循环等待是死锁的必要不充分条件)
当对不可剥夺资源的不合理分配,可能导致死锁。
内容:如果把只能互斥使用的资源改造成允许共享使用,则系统不会进入死锁状态。
缺点:并不是所有的资源都可以改造成可共享使用的资源。并且为了系统安全,很多地方还必须保护这种互斥性。因此,很多时候都无法破坏互斥条件。
内容:
缺点:
内容:可以采用静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不让它投入运行。一旦投入运行后,这些资源就一直归它所有,该进程就不会再请求别的任何资源了。
缺点:有些资源可能只需要用很短的时间,因此如果进程的整个运行期间都一直保持着所有资源,就会造成严重的资源浪费,资源利用率极低。另外,该策略也有可能导致某些进程饥饿。
内容:采用顺序资源分配法。首先给系统中的资源编号,规定每个进程必须按编号递增的顺序请求资源,同类资源(即编号相同的资源)一次申请完。
原理分析:一个进程只有已占有小编号的资源时,才有资格申请更大编号的资源。按此规则,已持有大编号资源的进程不可能逆向地回来申请小编号的资源,从而就不会产生循环等待的现象。
缺点:
安全序列:指如果系统按照这种序列分配资源,则每个进程都能顺序完成。只要能找出一个安全序列,系统就是安全状态。
如果系统处于安全状态,就一定不会发生死锁。如果系统进入不安全状态,就可能发生死锁。
在资源分配之前预先判断此次分配是否会导致系统进入不安全状态,以此决定是否答应资源的分配请求。
银行家算法步骤:
安全性算法步骤:
检查当前的剩余可用资源是否能满足某个进程的最大需求,如果可以,就把该进程加入安全序列,并把该进程持有的资源全部回收。
不断重复上述过程,看最终是否能让所有进程都加入安全序列。
数据结构:资源分配图
算法:
1)在资源分配图中,找出既不阻塞又不是孤点的进程Pi (即找出一-条有向边与它相连,且该有向边对应资源的申请数量小于等于系统中已有空闲资源数量。如下图中,R1没有空闲资源,R2有一个空闲资源。若所有的连接该进程的边均满足上述条件,则这个进程能继续运行直至完成,然后释放它所占有的所有资源)。消去它所有的请求边和分配变,使之称为孤立的结点。在下图中,P1是满足这一条件的进程结点,于是将P1的所有边消去。
2)进程Pi所释放的资源,可以唤醒某些因等待这些资源而阻塞的进程,原来的阻塞进程可能变为非阻塞进程。在下图中,P2 就满足这样的条件。根据1)中的方法进行一系列简化后,若能消去途中所有的边,则称该图是可完全简化的。
死锁定理:如果某时刻系统的资源分配图是不可完全简化的,那么此时系统死锁。
内存是用于存放数据的硬件。程序执行前需要先放到内存中才能被CPU处理。
绝对装入:在编译时,如果知道程序将放到内存中的哪个位置,编译程序将产生绝对地址的目标代码。装入程序按照装入模块中的地址,将程序和数据装入内存。(只适用于单道程序环境)
静态重定位:又称可重定位装入。编译、链接后的装入模块的地址都是从0开始的,指令中使用的地址、数据存放的地址都是相对于起始地址而言的逻辑地址。可根据内存的当前情况,将装入模块装入到内存的适当位置。装入时对地址进行“重定位”,将逻辑地址变换为物理地址(地址变换是在装入时一次完成的)。
动态重定位:又称动态运行时装入。编译、链接后的装入模块的地址都是从0开始的。装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,而是把地址转换推迟到程序真正要执行时才进行。因此装入内存后所有的地址依然是逻辑地址。这种方式需要一个重定位寄存器的支持。(允许程序在内存中发生移动)
静态链接:在程序运行之前,先将各目标模块及它们所需的库函数连接成一个完整的可执行文件(装入模块)之后不再拆开。
装入时动态链接:将各目标模块装入内存时,边装入边链接的链接方式。
运行时动态链接:在程序执行中需要该目标模块时,才对它进行链接。其优点是便于修改和更新,便于实现对目标模块的共享。
1、操作系统负责内存空间的分配与回收
2、操作系统需要提供某种技术从逻辑上对内存 空间进行扩充
3、操作系统需要提供地址转换功能,负责程序的逻辑地址与物理地址的转换
4、操作系统需要提供内存保护功能。保证各进程在各自存储空间内运行,互不干扰。
重定位寄存器:放的是起始物理地址。
界地址寄存器:放的是最大逻辑地址。
必须由程序员声明覆盖结构,操作系统完成自动覆盖。
缺点:对用户不透明,增加了用户编程负担。
设计思想:内存空间紧张时,系统将内存中某些进程暂时换出(挂起)外存,把外存中某些已具备运行条件的进程换入内存。
磁盘分为文件区和交换区,换出的进程放在对换区。
覆盖时在同一个程序或进程中的。
交换时在不同进程(或作业)之间的。
连续分配:指用户进程分配的必须是一个连续的内存空间。
内存分为系统区和用户区。
系统区通常位于内存的低地址部分,用于存放操作系统相关数据;
用户区用于存放用户进程相关数据。内存中只能有一道用户程序,用户程序独占整个用户区空间。
优点:实现简单;无外部碎片;可以采用覆盖技术扩充内存;不一定需要采取内存保护。
缺点:只能用于单用户、单任务的操作系统中;有内部碎片;存储器利用率极低。
使用分区说明表来实现对各个分区的分配与回收。每个表包括对应分区的大小,起始地址,状态。
优点:实现简单,无外部碎片。
缺点:a.当用户程序太大时,可能所有分区都不能满足需求,此时不得不采用覆盖技术来解决,但这又会降低性能;b.会产生内部碎片,内存利用率低。
不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态的建立分区。
数据结构:空闲分区表/空闲分区链
动态分区没有内部碎片,但有外部碎片。
紧凑技术
算法思想:每次都从低地址开始查找,找到第一个能满足大小的空闲分区。
实现:空闲分区以地址递增的次序排列。每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。
算法思想:由于动态分区分配是一种连续分配方式,为各进程分配的空间必须是连续的–整片区域。因此为了保证当“大进程”到来时能有连续的大片空间,可以尽可能多地留下大片的空闲区,即,优先使用更小的空闲区。
实现:空闲分区按容量递增次序链接。每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。
缺点:每次都选择最小的分区进行分配,会留下越来越多的、很小的、难以利用的内存块。因此这种方法会产生很多外部碎片。
又称最大适应算法( Largest Fit)
算法思想:为了解决最佳适应算法的问题–即留下太多难以利用的小碎片,可以在每次分配时优先使用最大的连续空闲区,这样分配后剩余的空闲区就不会太小,更方便使用。
实现:空闲分区按容量递减次序链接。每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。
缺点:每次都选最大的分区进行分配,虽然可以让分配后留下的空闲区更大,更可用,但是这种方式会导致较大的连续空闲区被迅速用完。如果之后有“大进程”到达,就没有内存分区可用了。
算法思想:首次适应算法每次都从链头开始查找的。这可能会导致低地址部分出现很多小的空闲分区,而每次分配查找时,都要经过这些分区,因此也增加了查找的开销。如果每次都从上次查找结束的位置开始检索,就能解决上述问题。
实现:空闲分区以地址递增的顺序排列(可排成一个循环链表)。每次分配内存时从上次查找结束的位置开始查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。
首次适应算法每次都要从头查找,每次都需要检索低地址的小分区。但是这种规则也决定了当低地址部分有更小的分区可以满足需求时,
会更有可能用到低地址部分的小分区,也会更有可能把高地址部分的大分区保留”下来(最佳适应算法的优点)
邻近适应算法的规则可能会导致无论低地址、高地址部分的空闲分区都有相同的概率被使用,也就导致了高地址部分的大分区更可能被使
用,划分为小分区,最后导致无大分区可用(最大适应算法的缺点)
思想:把内存分为一个个相等的小分区,再按照分区大小把进程拆分成一个个小部分。
每个分区就是一个页框/页帧/内存块/物理块。每个页框有一个编号,即”页框号“,页框号从0开始。
将用户进程的地址空间也分为与页框大小相等的一个个区域,称为“页”或“页面”。每个页面也有一个编号,即“页号”,页号也是从0开始。
页号=逻辑地址/页面长度
页内偏移量=逻辑地址%页面长度
页表项由”页号“(隐含)和”块号“组成。
页表记录进程页面和实际存放的内存块之间的对应关系
时间局部性:如果执行了程序中的某条指令,那么不久后这条指令很有可能再次执行;如果某个数据被访问过,不久之后该数据很可能再次被访问。( 因为程序中存在大量的循环)
空间局部性:一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也很有可能被访问。(因为很多数据在内存中都是连续存放的)
快表,又称联想寄存器(TLB) ,是一种访问速度比内存快很多的高速缓冲存储器,用来存放当前访问的若干页表项,以加速地址变换的过程。与此对应,内存中的页表常称为慢表。
为离散分配的页表再建立一张页表,称为页目录表,或称外层页表,或称顶层页表。
多级页表中,各级页表的大小不能超过一个页面。若两级页表不够,可以分更多级。
多级页表的访存次数——N级页表访问一个逻辑地址需要N+1次访存。
进程的地址空间:按照程序自身的逻辑关系划分为若干个段,每个段都有一一个段名( 在低级语言中,程序员使用段名来编程),每段从0开始编址
内存分配规则:以段为单位进行分配,每个段在内存中占据连续空间,但各段之间可以不相邻。
分段系统的逻辑地址结构:由段号和段内地址所组成。
段表记录了该段在内存中的起始位置(基址)和段的长度。
页是信息的物理单位。分页的主要目的是为了实现离散分配,提高内存利用率。分页仅仅是系统管理上的需要,完全是系统行为,对用户是不可见的。
段是信息的逻辑单位。分段的主要目的是更好地满足用户需求。一个段通常包含着一组属于一个逻辑模块的信息。分段对用户是可见的,用户编程时需要显式地给出段名。
页的大小固定且由系统决定。段的长度却不固定,决定于用户编写的程序。
分页的用户进程地址空间是一维的,程序员只需给出一个记忆符即可表示一个地址。
分段的用户进程地址空间是二维的,程序员在标识一个地址时,既要给出段名,也要给出段内地址。
分段比分页更容易实现信息的共享和保护。
不能被修改的代码称为纯代码或可重入代码(不属于临界资源),这样的代码是可以共享的。可修改的代码是不能共享的(比如,有一个代码段中有很多变量,各进程并发地同时访问可能造成数据不一致)
分页(单级页表)、分段访问一个逻辑地址都需要两次访存,分段存储中也可以引入快表机构。
优点 | 缺点 | |
---|---|---|
分页管理 | 内存空间利用率高,不会产生外部碎片,只会有少量的页内碎片 | 不方便按照逻辑模块实现信息的共享和保护 |
分段管理 | 很方便按照逻辑模块实现信息的共享和保护 | 如果段长过大,为其分配很大的连续空间会很不方便。另外,段式管理会产生外部碎片 |
段页式系统的逻辑地址结构:由段号、页号和页内地址所组成。
引入快表后仅需一次访存。
基于局部性原理,在程序装入时,可以将程序中很快会用到的部分装入内存,暂时用不到的部分留在外存,就可以让程序开始执行。在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序。若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存。在操作系统的管理下,在用户看来似乎有一个比实际内存大得多的内存,这就是虚拟内存。
特征:
在请求分页系统中,每当要访问的页面不在内存时,便产生-一个缺页中断,然后由操作系统的缺页中断处理程序处理中断。此时缺页的进程阻塞,放入阻塞队列,调页完成后再将其唤醒,放回就绪队列。如果内存中有空闲块,则为进程分配一个空闲块,将所缺页面装入该块,并修改页表中相应的页表项。如果内存中没有空闲块,则由页面置换算法选择一个页面淘汰,若该页面在内存期间被修改过,则要将其写回外存。未修改过的页面不用写回外存。
缺页中断属于内中断。
内容:每次选择淘汰的页面将是以后永远不使用,或者在最长时间内不再被访问的页面。
内容:每次选择淘汰的页面是最早进入内存的页面
实现方法:把调入内存的页面根据调入的先后顺序排成一一个队列,需要换出页面时选择队头页面即可。队列的最大长度取决于系统为进程分配了多少个内存块。
Belady异常:当为进程分配的物理块数增大时,缺页次数不减反增的异常现象。
内容:每次淘汰的页面是最近最久未使用的页面
实现方法:赋予每个页面对应的页表项中,用访问字段记录该页面自上次被访问以来所经历的时间t。当需要淘汰一个页面时,选择现有页面中t值最大的,即最近最久未使用的页面。
内容:最佳置换算法性能最好,但无法实现;先进先出置换算法实现简单,但算法性能差;最近最久未使用置换算法性能好,是最接近OPT算法性能的,但是实现起来需要专门的硬件支持,算法开销大。时钟置换算法是一-种性能和开销较均衡的算法,又称CLOCK算法,或最近未用算法(NRU,Not Recently Used)。
实现方法:为每个页面设置一个访问位,再将内存中的页面都通过链接指针链接成一个循环队列。当某页被访问时,其访问位置为1。当需要淘汰一个页面时,只需检查页的访问位。如果是0,就选择该页换出;如果是1,则将它置为0,暂不换出,继续检查下一个页面,若第一轮扫描中所有页面都是1,则将这些页面的访问位依次置为0后,再进行第二轮扫描(第二轮扫描中一定会有访问位为0的页面,因此简单的CLOCK算法选择一个淘汰页面最多会经过两轮扫描)。
简单的时钟置换算法仅考虑到一个页面最近是否被访问过。事实上,如果被淘汰的页面没有被修改过,就不需要执行I/0操作写回外存。只有被淘汰的页面被修改过时,才需要写回外存。
因此,除了考虑一个页面最近有没有被访问过之外,操作系统还应考虑页面有没有被修改过。在其他条件都相同时,应优先淘汰没有修改过的页面,避免I/O操作。这就是改进型的时钟置换算法的思想。
修改位=0,表示页面没有被修改过;修改位=1,表示页面被修改过。
为方便讨论,用(访问位,修改位)的形式表示各页面状态。如(1, 1)表示一个页面近期被访问过,且被修改过。
算法规则:将所有可能被置换的页面排成一个循环队列
第一轮:从当前位置开始扫描到第-一个(0, 0)的帧用于替换。本轮扫描不修改任何标志位
第二轮:若第一轮扫描失败,则重新扫描,查找第- -一个(0, 1)的帧用于替换。本轮将所有扫描过的帧访问位设为0
第三轮:若第二轮扫描失败,则重新扫描,查找第-一个(0,0) 的帧用于替换。本轮扫描不修改任何标志位
第四轮:若第三轮扫描失败,则重新扫描,查找第一个(0, 1)的帧用于替换。
由于第二轮已将所有帧的访问位设为0,因此经过第三轮、第四轮扫描一定会有一个帧被选中,因此改进型CLOCK置换算法选择–个淘汰页面最多会进行四轮扫描。
驻留集:指请求分页存储管理中给进程分配的物理块的集合。
固定分配:操作系统为每个进程分配一组固定数目的物理块,在进程运行期间不再改变。即,驻留集大小不变
可变分配:先为每个进程分配一定数目的物理块,在进程运行期间,可根据情况做适当的增加或减少。即,驻留集大小可变
局部置换:发生缺页时只能选进程自己的物理块进行置换。
全局置换:可以将操作系统保留的空闲物理块分配给缺页进程,也可以将别的进程持有的物理块置换到外存,再分配给缺页进程。
固定分配局部置换:系统为每个进程分配一定数量的物理块,在整个运行期间都不改变。若进程在运行中发生缺页,则只能从该进程在内存中的页面中选出一页换出,然后再调入需要的页面。这种策略的缺点是:很难在刚开始就确定应为每个进程分配多少个物理块才算合理。( 采用这种策略的系统可以根据进程大小、优先级、或是根据程序员给出的参数来确定为一个进程分配的内存块数)
可变分配全局置换:刚开始会为每个进程分配一定数量的物理块。操作系统会保持一个空闲物理块队列。当某进程发生缺页时,从空闲物理块中取出一块分配给该进程;若已无空闲物理块,则可选择一个未锁定的页面换出外存,再将该物理块分配给缺页的进程。采用这种策略时,只要某进程发生缺页,都将获得新的物理块,仅当空闲物理块用完时,系统才选择一个未锁定的页面调出。被选择调出的页可能是系统中任何一个进程中的页,因此这个被选中的进程拥有的物理块会减少,缺页率会增加。
可变分配局部置换:刚开始会为每个进程分配一定数量的物理块。当某进程发生缺页时,只允许从该进程自己的物理块中选出一个进行换出外存。如果进程在运行中频繁地缺页,系统会为该进程多分配几个物理块,直至该进程缺页率趋势适当程度;反之,如果进程在运行中缺页率特别低,则可适当减少分配给该进程的物理块。
可变分配全局置换:只要缺页就给分配新物理块。
可变分配局部置换:要根据发生缺页的频率来动态的增加或减少进程的物理块。
刚刚换出的页面马上又要换入内存,刚刚换入的页面马上又要换出外存,这种频繁的页面调度行为称为抖动,或颠簸。产生抖动的主要原因是进程频繁访问的页面数目高于可用的物理块数(分配给进程的物理块不够)
工作集:指在某段时间间隔里,进程实际访问页面的集合。
驻留集不能小于工作集的大小,否则进程运行过程将频繁缺页。
文件内内部的数据就是一系列二进制流或字符流组成。又称“流式文件”。
由一组相似的记录 组成,又称“记录式文件”。每条记录由若干给数据项组成。
文件中的记录一个接一个地顺序排列(逻辑上),记录可以是定长的或可变长的。各个记录在物理上可以顺序存储或链式存储。
索引表本身是定长记录的顺序文件。因此可以快.速找到第i个记录对应的索引项。可将关键字作为索引号内容,若按关键字顺序排列,则还可以支持按照关键字折半查找每当要增加/删除–个记录时,需要对索引表进行修改。由于索引文件有很快的检索速度,因此主要用于对信息处理的及时性要求比较高的场合。
索引顺序文件是索引文件和顺序文件思想的结合。索引顺序文件中,同样会为文件建立一张索引表,但不同的是:并不是每个记录对应一个索引表项,而是一组记录对应一个索引表项。
实现了“按名存取”,但不允许文件重名。
分为主文件目录(MFD)和用户文件目录(UFD)。
用户(或用户进程)要访问某个文件时要用文件路径名标识文件,文件路径名是个字符串。各级目录之间用“/”隔开。从根目录出发的路径称为绝对路径。
树形目录结构可以很方便地对文件进行分类,层次结构清晰,也能够更有效地进行文件的管理和保护。但是,树形结构不便于实现文件的共享。为此,提出了“无环图目录结构”。
可以用不同的文件名指向同一个文件,甚至可以指向同一个目录(共享同一目录下的所有内容)。 需要为每个共享结点设置一个共享计数器,用于记录此时有多少个地方在共享该结点。用户提出删除结点的请求时,只是删除该用户的FCB、并使共享计数器减1,并不会直接删除共享结点。只有共享计数器减为0时,才删除结点。
注意:共享文件不同于复制文件。在共享文件中,由于各用户指向的是同一个文件,因此只要其中一个用户修改了文件数据,那么所有用户都可以看到文件数据的变化。
磁盘块的大小与内存块、页面的大小相同。
每个文件在磁盘上占有一组连续的块。
优点:支持顺序访问和直接访问(即随机访问) ;连续分配的文件在顺序访问时速度最快
缺点:不方便文件拓展;存储空间利用率低,会产生磁盘碎片
链接分配采取离散分配的方式,可以为文件分配离散的磁盘块。分为隐式链接和显式链接两种。
隐式链接:除文件的最后-一个盘块之外,每个盘块中都存有指向下一一个盘块的指针。文件目录包括文件第一块的指针和最后-块的指针。
优点:很方便文件拓展,不会有碎片问题,外存利用率高。
缺点:只支持顺序访问,不支持随机访问,查找效率低,指向下一个盘块的指针也需要耗费少量的存储空间。
显式链接:把用于链接文件各物理块的指针显式地存放在一张表中,即文件分配表(FAT, FileAllocation Table)。一个磁盘只会建立一张文件分配表。开机时文件分配表放入内存,并常驻内存。
优点:很方便文件拓展,不会有碎片问题,外存利用率高,并且支持随机访问。相比于隐式链接来说,地址转换时不需要访问磁盘,因此文件的访问效率更高。
缺点:文件分配表的需要占用一定的存储空间。
索引分配允许文件离散地分配在各个磁盘块中,系统会为每个文件建立一张索引表, 索引表中记录了文件的各个逻辑块对应的物理块(索引表的功能类似于内存管理中的页表——建立逻辑页面到物理页之间的映射关系)。索引表存放的磁盘块称为索引块。文件数据存放的磁盘块称为数据块。
①链接方案:如果索引表太大,一个索引块装不下,那么可以将多个索引块链接起来。
②多层索引:建立多层索引(原理类似于多级页表)。使第一层索引块指向第二层的索引块。还可根据文件大小的要求再建立第三层、第四层索引块。
③混合索引:多种索引分配方式的结合。例如,一个文件的顶级索引表中,既包含直接地址索引(直接指向数据块),又包含一级间接索引(指向单层索引表)、还包含两级间接索引(指向两层索引表)。
为文件设置-一个“口令”(如: abc112233) ,用户请求访问该文件时必须提供“口令”。
优点:保存口令的空间开销不多,验证口令的时间开销也很小。
缺点:正确的“口令”存放在系统内部,不够安全。
使用某个“密码”对文件进行加密,在访问文件时需要提供正确的“密码”才能对文件进行正确的解密。
优点:保密性强,不需要在系统中存储“密码”
缺点:编码/译码,或者说加密/解密要花费一定时间
在每个文件的FCB ( 或索引结点)中增加一个访问控制列表(Access-Control List, ACL),该表中记录了各个用户可以对该文件执行哪些操作。
活动头磁盘
固定头磁盘
可换盘磁片
固定盘磁片
寻找时间(寻道时间) Ts:在读/写数据前,将磁头移动到指定磁道所花的时间。
①启动磁头臂是需要时间的。假设耗时为s;
②移动磁头也是需要时间的。假设磁头匀速移动,每跨越一个磁道耗时为m,总共需要跨越n条磁道。则:
寻道时间Ts=s+ m*n
延迟时间Tp:通过旋转磁盘,使磁头定位到目标扇区所需要的时间。设磁盘转速为r (单位: 转/秒,或转/分),则:
平均所需的延迟时间T。= (1/2)*(1/r)= 1/2r
传输时间T;:从磁盘读出或向磁盘写入数据所经历的时间,假设磁盘转速为r,此次读/写的字节数为b,每个磁道上的字节数为N。则:
传输时间T[= (1/r) * (b/N) = b/(rN)
SSTF算法会优先处理的磁道是与当前磁头最近的磁道。可以保证每次的寻道时间最短,但是并不能保证总的寻道时间最短。(其实就是贪心算法的思想,只是选择眼前最优,但是总体未必最优)
优点:性能较好,平均寻道时间短
缺点:可能产生“饥饿”现象
SSTF算法会产生饥饿的原因在于:磁头有可能在一个小区域内来回来去地移动。为了防止这个问题,可以规定,只有磁头移动到最外侧磁道的时候才能往内移动,移动到最内侧磁道的时候才能往外移动。这就是扫描算法(SCAN) 的思想。由于磁头移动的方式很像电梯,因此也叫电梯算法。
优点:性能较好,平均寻道时间较短,不会产生饥饿现象
缺点:
①只有到达最边上的磁道时才能改变磁头移动方向,事实上,处理了184号磁道的访问请求之后就不需要再往右移动磁头了。
②SCAN算法对于各个位置磁道的响应频率不平均(如:假设此时磁头正在往右移动,且刚处理过90号磁道,那么下次处理90号磁道的请求就需要等磁头移动很长一段距离; 而响应了184号磁道的请求之后,很快又可以再次响应184号磁道的请求了)
扫描算法(SCAN) 中,只有到达最边上的磁道时才能改变磁头移动方向,事实上,处理了184号磁道的访问请求之后就不需要再往右移动磁头了。LOOK调度算法就是为了解决这个问题,如果在磁头移动方向上已经没有别的请求,就可以立即改变磁头移动方向。(边移动边察, 因此叫LOOK )
优点:比起SCAN算法来,不需要每次都移动到最外侧或最内侧才改变磁头方向,使寻道时间进一步缩短
SCAN算法对于各个位置磁道的响应频率不平均,而C-SCAN算法就是为了解决这个问题。规定只有磁头朝某个特定方向移动时才处理磁道访问请求,而返回时直接快速移动至起始端而不处理任何请求。
优点:比起SCAN来,对于各个位置磁道的响应频率很平均。
缺点:只有到达最边上的磁道时才能改变磁头移动方向,事实上,处理了184号磁道的访问请求之后就不需要再往右移动磁头了;并且,磁头返回时其实只需要返回到18号磁道即可,不需要返回到最边缘的磁道。另外,比起SCAN算法来,平均寻道时间更长。
C-SCAN算法的主要缺点是只有到达最边上的磁道时才能改变磁头移动方向,并且磁头返回时不一定需要返回到最边缘的磁道上。C-LOOK 算法就是为了解决这个问题。如果磁头移动的方向上已经没有磁道访问请求了,就可以立即让磁头返回,并且磁头只需要返回到有磁道访问请求的位置即可。
优点:比起C-SCAN算法来,不需要每次都移动到最外侧或最内侧才改变磁头方向,使寻道时间进一步缩短
自举程序
坏块链、扇区备用
按使用特性分类:
按传输速率分类:
按信息交换的单位分类: