下载地址
需求分析:
通过模拟操作系统的实现,加深对操作系统工作原理理解,进一步了解操作系统的实现方法,并可练习合作完成系统的团队精神和提高程序设计能力。该操作系统是模拟一个采用多道程序设计方法的单用户操作系统,该操作系统包括进程管理、存储管理、文件管理。
本实验所使用的编程语言是JAVA,开发工具是IDEA,运行的操作系统是Windows10。
一.功能实现
计算机操作系统模拟实现
进程管理模拟:实现操作系统进程管理功能,进程并发执行。
文件管理模拟:实现文件系统的管理的功能。
内存管理模拟:实现内存的三种请求分页算法 设备管理模拟:实现设备的分配回收等。
以及公交车演示系统和银行家算法系统。
二.功能模块设计
常见进程管理模拟
进程管理部分主要模拟了三种算法
1、 先来先服务算法(FCFS)
先来先服务(FCFS)总是把当前处于就绪队列之首的那个进程调度到运行状态。也就说,它只考虑进程进入就绪队列的先后,而不考虑它的下一个CPU周期的长短及其他因素。
2、 短进程优先算法(SPF)
SPF的意思是短进程优先(Short Process First)。意思也很清楚,就是让短的进程先运行,
3、 高响应比优先调度算法(HRRN)
HRRN为每个作业引入动态优先权,使作业的优先级随着等待时间的增加而以速率a提高:优先权 =(等待时间+要求服务时间)/要求服务时间= 响应时间要求服务时间。
2.4常见内存管理模拟
内存模拟部分主要模拟了请求分页的三种算法
1、先进先出算法(FIFO)
这是最早出现的置换算法,该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最长的页面换出,该算法实现简单。
2、最近最久未使用(LRU)
最近最久未使用的置换算法,是根据页面调入内存后的使用情况却决策的,由于无法预测个页面将来的使用情况,只能根据“最近的过去”作为“最近的将来”的近似,因此,最近最久未使用(LRU)算法是选择最近的最久未使用的页面予以淘汰。
3、最佳置换算法(OPT)
最佳置换算法是可以说的一种理想的页面置换算法,其所淘汰的页面是将来不会被使用的或者是在最长的未来不会被使用的页面。采用最佳置换算法,可以获得最小的缺页率。
三.实验内容
将操作系统的实验进行合成,组成界面,用于实现操作系统的四大功能的模拟,分别进行进程管理、进程同步、虚拟内存管理,银行家算法以及设备管理(磁盘调度)。各模块的详细设计内容如下:
进程管理:代码中 生产者 和 消费者 所做的工作 用过程Producer和Consumer描述,并通过创建线程的方法创建3个生产者线程和1个消费者线程,具体创建方法:CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);其中第3个参数就是指定该线程所做的工作为过程Producer;
虚拟内存: 请求分页系统建立在基本分页系统基础之上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能。请求分页是目前最常用的一种实现虚拟存储器的方法。在请求分页系统中,只要求将当前需要的一部分页面装入内存,便可以启动作业运行。在作业执行过程中,当所要访问的页面不在内存时,再通过调页功能将其调入,同时还可以通过置换功能将暂时不用的页面换出到外存上,以便腾出内存空间。为了实现请求分页,系统必须提供一定的硬件支持。除了需要一定容量的内存及外存的计算机系统,还需要有页表机制、缺页中断机构和地址变换机构。
设备管理: 设备管理模拟计算机系统的外围设备的系统结构,可以创建2个通道、3个控制器和四个外设(键盘、鼠标、显示器、打印机),键盘和鼠标使用一个控制器。
2、 设备管理有添加和删除设备的功能,同时完成控制器的维护功能。
3、 设备管理还包括设备的分配和回收。使学生掌握外围设备的体系结构和管理方法。成功分配的时候,用户进程使用设备,否则将被阻塞到一个级别的控制表上,等待被唤醒。
设备分配必须满足设备的独立性要求。为了实现设备独立性,要求在驱动程序之上设计一层设备无关软件,其主要功能可分为执行所有设备的公有操作,主要包括:(a)独占设备的分配与回收;(b)将逻辑设备名映射为物理设备,进一步可以找到相应物理设备的驱动程序。
进程同步: 分析计算机系统中对资源的分配与释放过程:计算机系统中的每个进程都可以消费或生产某类资源。当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。而当某个进程释放资源时,则它就相当一个生产者。定义生产者消费者问题中的各数据结构,并初始化信号量。创建生产者与消费者进程,利用信号量实现生产者与消费者之间的同步与互斥;最后编程实现
主页面截图:
1.进程演示系统
进程调度模拟(多级反馈队列):无论是在批处理系统还是分时系统中,用户进程数一般都多于处理机数, 这将导致它们互相争夺处理机。另外,系统进程也同样需要使用处理机。这就要求进程调度程序按一定的策略,动态地把处理机分配给处于就绪队列中的某一个进程,以使之执行。因此,我们需要用到一些调度方式来解决进程互相争夺资源,使得每个进程都很好的使用的处理机。
多级反馈队列调度算法 就是一种CPU处理机调度算法,是目前公认的较好的一种进程调度算法,它能较好的满足各类进程的需要,UNIX操作系统采取的便是这种调度算法。多级反馈队列调度算法既能使高优先级的作业得到响应又能使短作业(进程)迅速完成。具体实现如下:
应设置多个就绪队列,并为各个队列赋予不同的优先级。 第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n队列中便采取按时间片轮转的方式运行。仅当第一队列空闲时,调度程序才调度第二队列中的进程运行; 仅当第1~(i-1) 队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。
需求分析和设计
采用多级反馈队列调度算法进行进程调度的模拟。
每个进程对应一个 PCB。在 PCB 中包括进程标识符 pid、进程的状态标识 status、进程优先级 priority、表示进程生命周期的数据项 life(在实际系统中不包括该项)。
创建进程时即创建一个 PCB,各个进程的 pid 都是唯一的,pid 是在 1 到 100 范围内的一个整数。
可以创建一个下标为 1 到 100 的布尔数组,“假”表示下标对应的进程标识号是空闲的,“真”表示下标对应的进程标识号已分配给某个进程。
进程状态 status 的取值为“就绪 ready”或“运行 run”,刚创建时,状态为“ready”。被进程调度程序选中后变为“run”。
进程优先级 priority 是 0(最低) 到 49(最高) 范围内的一个随机整数。
进程生命周期 life 是 1 到 5 范围内的一个随机整数。初始化时,创建 50 个就绪队列,各就绪队列的进程优先级 priority 分别是 0 到 49。
为了模拟用户动态提交任务的过程,要求动态创建进程。进入进程调度循环后,每次按 ctrl+f 即动态创建一个进程,然后将该 PCB 插入就绪队列中。
在进程调度循环中,每次选择优先级大的就绪进程来执行。将其状态从就绪变为运行,通过延时一段时间来模拟该进程执行一个时间片 的过程,然后优先级减半,生命周期减一。
如果将该运行进程的生命周期不为 0,则重新把它变为就绪状态,插入就绪队列中;否则该进程执行完成,撤消其 PCB。以上为一次进程调度循环。
设计图形用户界面 GUI,在窗口中显示该进程和其他所有进程的 PCB 内容。
实验截图演示:
2.公交车模拟系统
用两个进程来模拟汽车司机与售票员之间的协同关系:一方面只有售票员把车门关好了司机才能关门,因此,售票员关好车门应通知司机开车;另一方面,只有当汽车已经停下,售票员才能开门上下客,故司机停车后应通知售票员。汽车当前正在始发站停车上客,试设必要的信号量并赋初值,写出它们的同步过程。
实验思路:
建立两个线程driver表示汽车司机,conductor表示售票员,两个线程同时进行。信号变量bus和seller分别代表汽车和售票员。初始值分别为0和1。线程driver中将bus=0,seller=1;线程seller中将bus=1,seller=0。在t从0到10000时间内两个进程交替执行,从而模拟司机与售票员的协同关系。
在公共汽车上,司机和售票员的工作流程如图所示。
为保证乘客的安全,司机和售票员应 密切配合协调工作。
请用信号量来实现司机与售票员之间的同步。
司机 启动车辆 正常行车 到站停车
售票员 关车门 售票 开车门
司机和售票员工作流程图:
在这个问题中没有资源的抢夺,所以无互斥信号量。
司机和售票员是同步关系,司机需要接收门是否关好的信号量,而售票员需要接收车是否到站的信号量。
活动顺序:关车门->启动车辆->售票->到站停车->开车门
初始状态为:停车且门未关。
流程:售票员给司机关门的信号,司机收到后开始正常行驶车辆,到站时由司机给售票员停车的信号。
实验演示截图:
3.银行家算法系统模拟
实验目的:
1.银行家算法是一种最有代表性的避免死锁的算法。
2.在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性;
3.若分配不会导致系统进入不安全状态,则分配,否则等待。
4…通过编写一个模拟动态资源分配的银行家算法程序,帮助学生进一步深入理解死锁、产生死锁的必要条件、安全状态等重要概念,并掌握避免死锁的具体实施方法。
银行家算法中的数据结构
1)可利用资源向量Available
是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。
2)最大需求矩阵Max
这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
3)分配矩阵Allocation
这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。
4)需求矩阵Need。
这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
Need[i,j]=Max[i,j]-Allocation[i,j]
银行家算法
设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:
(1)如果Requesti[j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布最大值。
(2)如果Requesti[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,Pi须等待。
(3)系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:
Available[j]=Available[j]-Requesti[j];
Allocation[i,j]=Allocation[i,j]+Requesti[j];
Need[i,j]=Need[i,j]-Requesti[j];
系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
安全性算法
1)设置两个向量:
工作向量Work: 它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work=Available;
工作向量Finish: 它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]=false; 当有足够资源分配给进程时, 再令Finish[i]=true。
2)从进程集合中找到一个能满足下述条件的进程:
Finish[i]=false;
Need[i,j]≤Work[j];若找到,执行 (3),否则,执行 (4)
3)当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work[j]=Work[i]+Allocation[i,j];
Finish[i]=true;
go to step 2;
4)如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态;
算法流程图:
实验演示截图:
实验小结:
1.银行家算法是一种用来避免操作系统死锁出现的有效算法。
2.死锁:是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
3.死锁的发生必须具备以下四个必要条件:
1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不抢占条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)循环等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
4.避免死锁算法中最有代表性的算法就是Dijkstra E.W 于1968年提出的银行家算法,银行家算法是避免死锁的一种重要方法,防止死锁的机构只能确保上述四个条件之一不出现,则系统就不会发生死锁。
5.为实现银行家算法,系统必须设置若干数据结构,同时要解释银行家算法,必须先解释操作系统安全状态和不安全状态。
6.安全序列:是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。7.安全状态:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。
8.安全状态一定是没有死锁发生。不安全状态:不存在一个安全序列。不安全状态不一定导致死锁。
4.设备管理系统模拟
独占设备的分配、回收等主要算法的原理:
为了提高操作系统的可适应性和可扩展性,现代操作系统中都毫无例外地实现了设备独立性,又叫做设备无关性。设备独立性的含义是:应用程序独立于具体使用的物理设备。
为了实现独占设备的分配,系统设置数据表格的方式也不相同,在实验中只要设计合理即可。这里仅仅是一种方案,采用设备类表和设备表。
(1) 数据结构
操作系统设置“设备分配表”,用来记录计算机系统所配置的独占设备类型、台数以及分配情况。设备分配表可由“设备类表”和“设备表”两部分组成。
(2) 设备分配
1) 当进程申请某类设备时,系统先查“设备类表”。
2) 如果该类设备的现存台数可以满足申请要求,则从该类设备的“设备表”始址开始依次查该类设备在设备表中的登记项,找出“未分配”的设备分配给进程。
3) 分配后要修改设备类表中的现存台数,把分配给进程的设备标志改为“已分配”且填上占用设备的进程名。
4) 然后,把设备的绝对号与相对号的对应关系通知用户,以便用户在分配到的设备上装上存储介质。
(3) 设备回收
当进程执行结束撤离时应归还所占设备,系统根据进程名查设备表,找出进程占用设备的登记栏,把标志修改为“未分配”,清除进程名。同时把回收的设备台数加到设备类表中的现存台数中。
2、 程序流程图。
1)申请设备
2)删除设备
3)释放设备
4 )添加设备
实验演示截图:
5.虚拟内存管理系统模拟
- 一次性
作业必须一次性全部装入内存后,方能开始运行。这会导致两种情况发生:
当作业很大,不能全部被装入内存时,将使该作业无法运行;
当大量作业要求运行时,由于内存不足以容纳所有作业,只能使少数作业先运行,导致多道程序度的下降。 - 驻留性
作业被装入内存后,就一直驻留在内存中,其任何部分都不会被换出,直至作业运行结束。运行中的进程,会因等待I/O而被阻塞,可能处于长期等待状态。
由以上分析可知,许多在程序运行中不用或暂时不用的程序(数据)占据了大量的内存空间,而一些需要运行的作业又无法装入运行,显然浪费了宝贵的内存资源。
局部性原理
时间局部性是通过将近来使用的指令和数据保存到高速缓存存储器中,并使用高速缓存的层次结构实现。空间局部性通常是使用较大的高速缓存,并将预取机制集成到高速缓存控制逻辑中实现。虚拟内存技术实际上就是建立了 “内存一外存”的两级存储器的结构,利用局部性原理实现髙速缓存。
1.原理
请求调入
置换
局部性原理
时间局部性:如果程序中的某条指令一旦执行,不久以后该指令可能再次执行;如果某数据被访问过,不久以后该数据可能再次被访问。产生时间局部性的典型原因,是由于在程序中存在着大量的循环操作。
空间局部性:一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能集中在一定的范围之内,这是因为指令通常是顺序存放、顺序执行的,数据也一般是以向量、数组、表等形式簇聚存储的
基于局部性原理,在程序装入时,可以将程序的一部分装入内存,而将其余部分留在外存,就可以启动程序执行。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。另一方面,操作系统将内存中暂时不使用的内容换出到外存上,从而腾出空间存放将要调入内存的信息。这样,系统好像为用户提供了一个比实际内存大得多的存储器,称为虚拟存储器。
之所以将其称为虚拟存储器,是因为这种存储器实际上并不存在,只是由于系统提供了部分装入、请求调入和置换功能后(对用户完全透明),给用户的感觉是好像存在一个比实际物理内存大得多的存储器。虚拟存储器的大小由计算机的地址结构决定,并非是内存和外存的简单相加。
虚拟存储器有以下三个主要特征:
多次性,是指无需在作业运行时一次性地全部装入内存,而是允许被分成多次调入内存运行。
对换性,是指无需在作业运行时一直常驻内存,而是允许在作业的运行过程中,进行换进和换出。
虚拟性,是指从逻辑上扩充内存的容量,使用户所看到的内存容量,远大于实际的内存容量。
2.物质基础
一定容量的内存和外存。
页表机制(或段表机制),作为主要的数据结构。
中断机构,当用户程序要访问的部分尚未调入内存,则产生中断。
地址变换机构,逻辑地址到物理地址的变换。
3.实现方法(分页,分段,段页式)
3.1请求分页存储管理方式
请求分页系统建立在基本分页系统基础之上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能。请求分 页是目前最常用的一种实现虚拟存储器的方法。
在请求分页系统中,只要求将当前需要的一部分页面装入内存,便可以启动作业运行。在作业执行过程中,当所要访问的页 面不在内存时,再通过调页功能将其调入,同时还可以通过置换功能将暂时不用的页面换出到外存上,以便腾出内存空间。
为了实现请求分页,系统必须提供一定的硬件支持。除了需要一定容量的内存及外存的计算机系统,还需要有页表机制、缺页中断机构和地址变换机构。
页表机制
请求分页系统的页表机制不同于基本分页系统,请求分页系统在一个作业运行之前不要求全部一次性调入内存,因此在作业 的运行过程中,必然会出现要访问的页面不在内存的情况,如何发现和处理这种情况是请求分页系统必须解决的两个基本问题。为此,在请求页表项中增加了四个字段,如图3-24所示。
请求分页系统中的页表项增加的四个字段说明如下:
状态位P:用于指示该页是否已调入内存,供程序访问时参考。
访问字段A:用于记录本页在一段时间内被访问的次数,或记录本页最近己有多长时间未被访问,供置换算法换出页面时参考。
修改位M:标识该页在调入内存后是否被修改过。
外存地址:用于指出该页在外存上的地址,通常是物理块号,供调入该页时参考。
缺页中断机构
在请求分页系统中,每当所要访问的页面不在内存时,便产生一个缺页中断,请求操作系统将所缺的页调入内存。此时应将缺页的进程阻塞(调页完成唤醒),如果内存中有空闲块,则分配一个块,将要调入的页装入该块,并修改页表中相应页表项,若此时内存中没有空闲块,则要淘汰某页(若被淘汰页在内存期间被修改过,则要将其写回外存)。
缺页中断作为中断同样要经历,诸如保护CPU环境、分析中断原因、转入缺页中断处理程序、恢复CPU环境等几个步骤。但与一般的中断相比,它有以下两个明显的区别:
在指令执行期间产生和处理中断信号,而非一条指令执行完后,属于内部中断。
一条指令在执行期间,可能产生多次缺页中断。
地址变换机构
请求分页系统中的地址变换机构,是在分页系统地址变换机构的基础上,为实现虚拟内存,又增加了某些功能而形成的。
先按比例为进程分配物理块,当高优先级进程发生缺页时,允许它从低优先级进程处获得物理块
若找到要访问的页,便修改页表项中的访问位(写指令则还须重置修改位),然后利用页表项中给出的物理块号和页内地址形成物理地址。
若未找到该页的页表项,应到内存中去查找页表,再对比页表项中的状态位P,看该页是否已调入内存,未调入则产生缺页中断,请求从外存把该页调入内存。
页面置换算法
最佳置换算法
将来最长时间不会使用
仅具有理论意义
最佳(Optimal, OPT)置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。
最佳置换算法可以用来评价其他算法。假定系统为某进程分配了三个物理块,并考虑有以下页面号引用串:
7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0,
进程运行时,先将7, 0, 1三个页面依次装入内存。进程要访问页面2时,产生缺页中断,根据最佳置换算法,选择第18次访问才需调入的页面7予以淘汰。然后,访问页面0时,因为已在内存中所以不必产生缺页中断。访问页面3时又会根据最佳置换算法将页面1淘汰……依此类推,如图3-26所示。从图中可以看出釆用最佳置换算法时的情况。
可以看到,发生缺页中断的次数为9,页面置换的次数为6。
先进先出算法
选择调入主存时间最长的页面予以淘汰
优先淘汰最早进入内存的页面,亦即在内存中驻留时间最久的页面。该算法实现简单,只需把调入内存的页面根据先后次序链接成队列,设置一个指针总指向最早的页面。但该算法与进程实际运行时的规律不适应,因为在进程中,有的页面经常被访问。
最近最久未使用置换算法
选择最近一段时间内最长时间没有被访问过的页面予以淘汰
实现
1.基于寄存器的方法
配置一个n位寄存器,在进程访问页面的时候最左置1
每过一段时间则计数器右移1位
最小数值的寄存器即最近最久未使用的页面
2.基于栈的方法
栈顶存放最近使用过的页面
选择最近最长时间未访问过的页面予以淘汰,它认为过去一段时间内未访问过的页面,在最近的将来可能也不会被访问。该算法为每个页面设置一个访问字段,来记录页面自上次被访问以来所经历的时间,淘汰页面时选择现有页面中值最大的予以淘汰。
再对上面的实例釆用LRU算法进行页面置换,如图3-29所示。进程第一次对页面2访问时,将最近最久未被访问的页面7置换出去。然后访问页面3时,将最近最久未使用的页面1换出。
在图3-29中,前5次置换的情况与最佳置换算法相同,但两种算法并无必然联系。实际上,LRU算法根据各页以前的情况,是“向前看”的,而最佳置换算法则根据各页以后的使用情况,是“向后看”的。
LRU性能较好,但需要寄存器和栈的硬件支持。LRU是堆栈类的算法。理论上可以证明,堆栈类算法不可能出现Belady异常。FIFO算法基于队列实现,不是堆栈类算法。
时钟置换算法
将页面设置成循环队列
首次调入内存,置访问位置1
被访问置访问位置1
缺页中断的时候
访问为0则淘汰
不为0则置为0
接上次判定界面位置
改进:访问位和修改位分开考虑
有四种情况
先寻找访问位和修改位都为0的页面淘汰
没有则再寻找访问页为0,修改位为1的淘汰,并将访问位设置为0
没有重复一操作
LRU算法的性能接近于OPT,但是实现起来比较困难,且开销大;FIFO算法实现简单,但性能差。所以操作系统的设计者尝试了很多算法,试图用比较小的开销接近LRU的性能,这类算法都是CLOCK算法的变体
简单的CLOCK算法是给每一帧关联一个附加位,称为使用位。当某一页首次装入主存时,该帧的使用位设置为1;当该页随后再被访问到时,它的使用位也被置为1。对于页替换算法,用于替换的候选帧集合看做一个循环缓冲区,并且有一个指针与之相关联。当某一页被替换时,该指针被设置成指向缓冲区中的下一帧。当需要替换一页时,操作系统扫描缓冲区,以查找使用位被置为0的一帧。每当遇到一个使用位为1的帧时,操作系统就将该位重新置为0;如果在这个过程开始时,缓冲区中所有帧的使用位均为0,则选择遇到的第一个帧替换;如果所有帧的使用位均为1,则指针在缓冲区中完整地循环一周,把所有使用位都置为0,并且停留在最初的位置上,替换该帧中的页。由于该算法循环地检查各页面的情况,故称为CLOCK算法,又称为最近未用(Not Recently Used, NRU)算法。
CLOCK算法的性能比较接近LRU,而通过增加使用的位数目,可以使得CLOCK算法更加高效。在使用位的基础上再增加一个修改位,则得到改进型的CLOCK置换算法。这样,每一帧都处于以下四种情况之一:
1.最近未被访问,也未被修改(u=0, m=0)。
2.最近被访问,但未被修改(u=1, m=0)。
3.最近未被访问,但被修改(u=0, m=1)。
4.最近被访问,被修改(u=1, m=1)。
算法执行如下操作步骤:
1.从指针的当前位置开始,扫描帧缓冲区。在这次扫描过程中,对使用位不做任何修改。选择遇到的第一个帧(u=0, m=0)用于替换。
2.如果第1)步失败,则重新扫描,查找(u=0, m=1)的帧。选择遇到的第一个这样的帧用于替换。在这个扫描过程中,对每个跳过的帧,把它的使用位设置成0。
3.如果第2)步失败,指针将回到它的最初位置,并且集合中所有帧的使用位均为0。重复第1步,并且如果有必要,重复第2步。这样将可以找到供替换的帧。
改进型的CLOCK算法优于简单CLOCK算法之处在于替换时首选没有变化的页。由于修改过的页在被替换之前必须写回,因而这样做会节省时间。
4.5.其他置换算法
5.性能分析
1.有效访问时间
访问存储器所需时间的平均值
在快表中,则需要访问一次主存
不在内存,则要缺页中断时间
缺页中断时间
缺页中断时间
界面传送时间
进程重新执行时间
仅考虑页面传送时间
影响缺页率的因素
分配给进程的物理块数
页面本身大小
程序编制方法
页面置换算法
3.2请求分段存储管理方式
请求调段
分段置换
支持结构
段表
段号、段长和段基址:其定义同分段存储管理
存取方式:标识该分段的存取方式:读、写、执行
访问字段:记录该段在一段时间内被访问的次数
修改位:表示该段调入内存后是否被修改过
存在位:表示该段是否在主存中
增补位:指出该段在运行过程中,是否允许动态增长
外存地址:指出该段在外存上的地址
缺段中断机构
类似缺页中断
内存管理
段的置换
有空间则直接调入
没有就检查空闲区之后是否满足
再不符合则淘汰若干段
地址变换机构
动态地址变换
分段共享
实现
为了实现分段共享,可在系统中设置一张共享段表,所有共享分段都在其中占有一表项
增加共享进程计数
存取控制字段
共享段在不同进程中有不同的段号分配
对于第一个请求使用该段的进程,系统为该共享段分配一个内存区,在将共享段调入
同时将该区的始地址填入请求进程的段表
在共享段表中增加一项,填写有关数据将count置1
填入相关的数据结构回收
释放该进程段,将count减一
如果变为0则需要系统回收共享段的物理内存及有关表项
分段保护越界保护
用段表长度与逻辑地址中的段号比较
段长与逻辑地址中的段内位移比较
存取方式检查
本段的访问方式
环保护结构
低编号环具有高优先权原则
一个程序可以访问在相同的环或者较低环中的数据
一个程序可以调用驻留在相同环或较高环中的服务
4.页面分配策略
页面分配策略:驻留集大小、调入页面的时机以及从何处调入页面驻留集大小
对于分页式的虚拟内存,在准备执行时,不需要也不可能把一个进程的所有页都读取到主存,因此,操作系统必须决定读取多少页。也就是说,给特定的进程分配多大的主存空间,这需要考虑以下几点:
1.分配给一个进程的存储量越小,在任何时候驻留在主存中的进程数就越多,从而可以提高处理机的时间利用效率。
2.如果一个进程在主存中的页数过少,尽管有局部性原理,页错误率仍然会相对较高。
3.如桌页数过多,由于局部性原理,给特定的进程分配更多的主存空间对该进程的错误率没有明显的影响。
基于这些因素,现代操作系统通常釆用三种策略:
1.固定分配局部置换。它为每个进程分配一定数目的物理块,在整个运行期间都不改变。若进程在运行中发生缺页,则只能从该进程在内存中的页面中选出一页换出,然后再调入需要的页面。实现这种策略难以确定为每个进程应分配的物理块数目:太少会频繁出现缺页中断,太多又会使CPU和其他资源利用率下降。
2.可变分配全局置换。这是最易于实现的物理块分配和置换策略,为系统中的每个进程分配一定数目的物理块,操作系统自身也保持一个空闲物理块队列。当某进程发生缺页时,系统从空闲物理块队列中取出一个物理块分配给该进程,并将欲调入的页装入其中。
3.可变分配局部置换。它为每个进程分配一定数目的物理块,当某进程发生缺页时,只允许从该进程在内存的页面中选出一页换出,这样就不会影响其他进程的运行。如果进程在运行中频繁地缺页,系统再为该进程分配若干物理块,直至该进程缺页率趋于适当程度; 反之,若进程在运行中缺页率特别低,则可适当减少分配给该进程的物理块。
调入页面的时机
为确定系统将进程运行时所缺的页面调入内存的时机,可釆取以下两种调页策略:
1.预调页策略。根据局部性原理,一次调入若干个相邻的页可能会比一次调入一页更高效。但如果调入的一批页面中大多数都未被访问,则又是低效的。所以就需要釆用以预测为基础的预调页策略,将预计在不久之后便会被访问的页面预先调入内存。但目前预调页的成功率仅约50%。故这种策略主要用于进程的首次调入时,由程序员指出应该先调入哪些页。
2.请求调页策略。进程在运行中需要访问的页面不在内存而提出请求,由系统将所需页面调入内存。由这种策略调入的页一定会被访问,且这种策略比较易于实现,故在目前的虚拟存储器中大多釆用此策略。它的缺点在于每次只调入一页,调入调出页面数多时会花费过多的I/O开销。
从何处调入页面
请求分页系统中的外存分为两部分:用于存放文件的文件区和用于存放对换页面的对换区。对换区通常是釆用连续分配方式,而文件区釆用离散分配方式,故对换区的磁盘I/O速度比文件区的更快。这样从何处调入页面有三种情况:
1.系统拥有足够的对换区空间:可以全部从对换区调入所需页面,以提髙调页速度。为此,在进程运行前,需将与该进程有关的文件从文件区复制到对换区。
2.系统缺少足够的对换区空间:凡不会被修改的文件都直接从文件区调入;而当换出这些页面时,由于它们未被修改而不必再将它们换出。但对于那些可能被修改的部分,在将它们换出时须调到对换区,以后需要时再从对换区调入。
3.UNIX方式:与进程有关的文件都放在文件区,故未运行过的页面,都应从文件区调入。曾经运行过但又被换出的页面,由于是被放在对换区,因此下次调入时应从对换区调入。进程请求的共享页面若被其他进程调入内存,则无需再从对换区调入。
5.工作集
工作集(或驻留集)是指在某段时间间隔内,进程要访问的页面集合。经常被使用的页面需要在工作集中,而长期不被使用的页面要从工作集中被丢弃。为了防止系统出现抖动现象,需要选择合适的工作集大小。
工作集模型的原理是:让操作系统跟踪每个进程的工作集,并为进程分配大于其工作集的物理块。如果还有空闲物理块,则可以再调一个进程到内存以增加多道程序数。如果所有工作集之和增加以至于超过了可用物理块的总数,那么操作系统会暂停一个进程,将其页面调出并且将其物理块分配给其他进程,防止出现抖动现象。
正确选择工作集的大小,对存储器的利用率和系统吞吐量的提嵩,都将产生重要影响。
6.抖动
页面抖动(颠簸)
在页面置换过程中的一种最糟糕的情形是,刚刚换出的页面马上又要换入主存,刚刚换入的页面马上就要换出主存,这种频繁的页面调度行为称为抖动,或颠簸。如果一个进程在换页上用的时间多于执行时间,那么这个进程就在颠簸。
频繁的发生缺页中断(抖动),其主要原因是某个进程频繁访问的页面数目高于可用的物理页帧数目。虚拟内存技术可以在内存中保留更多的进程以提髙系统效率。在稳定状态,几乎主存的所有空间都被进程块占据,处理机和操作系统可以直接访问到尽可能多的进程。但如果管理不当,处理机的大部分时间都将用于交换块,即请求调入页面的操作,而不是执行进程的指令,这就会大大降低系统效率。
实验演示截图:
四、报告总结
本次课程设计要求是将以前的四个实验进行合成,至于做一个完整的操作系统模拟是比较困难,因为做课程设计的同时还有好几个课程要考试,因此做这个实验的时候已经花费了不少精力,也熬了不少个通宵了,但是对于本次实验的结果,我还是非常满意的。
从实验中,进一步加深了对操作系统的内部运做情况的了解,使自己真正懂得了什么叫做操作系统,以及操作系统在计算机中的重要地位,可以说,一个好的操作系统能够最优化的调用系统资源,对各个作业进行最佳的调度,缩短作业的周转时间和等待时间,并且让CPU等硬件资源的利用率达到最佳,从而使计算机的性能达到最佳状态。
同时,还对各模块之间的衔接个功能的独立性有了更新的认识,只有各个模块、部分的充分连接,才能使整体达到最佳。本次课程设计就是对进程管理、作业调度、页面替换、和磁盘调度这四大模块的模拟。
不仅如此,通过实验和课程设计,还进一步锻炼了自己的编程能力,增强了实践和动手能力,使自己的编程能力和逻辑思考能力有了较大的进步。