LRU算法 与CLOCK算法
操作系统页面置换算法(opt,lru,fifo,clock)实现

操作系统页⾯置换算法(opt,lru,fifo,clock )实现选择调出页⾯的算法就称为页⾯置换算法。
好的页⾯置换算法应有较低的页⾯更换频率,也就是说,应将以后不会再访问或者以后较长时间内不会再访问的页⾯先调出。
常见的置换算法有以下四种(以下来⾃操作系统课本)。
1. 最佳置换算法(OPT)最佳(Optimal, OPT)置换算法所选择的被淘汰页⾯将是以后永不使⽤的,或者是在最长时间内不再被访问的页⾯,这样可以保证获得最低的缺页率。
但由于⼈们⽬前⽆法预知进程在内存下的若千页⾯中哪个是未来最长时间内不再被访问的,因⽽该算法⽆法实现。
最佳置换算法可以⽤来评价其他算法。
假定系统为某进程分配了三个物理块,并考虑有以下页⾯号引⽤串: 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1进程运⾏时,先将7, 0, 1三个页⾯依次装⼊内存。
进程要访问页⾯2时,产⽣缺页中断,根据最佳置换算法,选择第18次访问才需调⼊的页⾯7予以淘汰。
然后,访问页⾯0时,因为已在内存中所以不必产⽣缺页中断。
访问页⾯3时⼜会根据最佳置换算法将页⾯1淘汰……依此类推,如图3-26所⽰。
从图中可以看出⾤⽤最佳置换算法时的情况。
可以看到,发⽣缺页中断的次数为9,页⾯置换的次数为6。
图3-26 利⽤最佳置换算法时的置换图2. 先进先出(FIFO)页⾯置换算法优先淘汰最早进⼊内存的页⾯,亦即在内存中驻留时间最久的页⾯。
该算法实现简单,只需把调⼊内存的页⾯根据先后次序链接成队列,设置⼀个指针总指向最早的页⾯。
但该算法与进程实际运⾏时的规律不适应,因为在进程中,有的页⾯经常被访问。
图3-27 利⽤FIFO 置换算法时的置换图这⾥仍⽤上⾯的实例,⾤⽤FIFO 算法进⾏页⾯置换。
进程访问页⾯2时,把最早进⼊内存的页⾯7换出。
然后访问页⾯3时,再把2, 0, 1中最先进⼊内存的页换出。
【精品】页面置换算法实验报告

【精品】页面置换算法实验报告一、实验目的了解操作系统中的页面置换算法,并实现FIFO、LRU和Clock算法。
二、实验原理页面置换算法是操作系统中用到的一种算法,其作用是在内存不够用时,选择牺牲已经在内存中的一些页,腾出更多的空间给新的内容。
本次实验主要实现了FIFO、LRU和Clock算法。
1、FIFO算法FIFO算法是最简单的页面置换算法,它采用先进先出的原则,即最先进入内存的页面应该最早被替换出去。
该算法的实现非常简单,只需要维护一个队列即可。
当需要置换页面时,选择队列的第一个页面进行替换即可。
2、LRU算法LRU算法是Least Recently Used的缩写,即最近最少使用算法。
该算法的核心思想是选择最久没有被使用的页面进行替换。
为了实现该算法,需要维护记录页面使用时间的链表、栈或队列等结构。
3、Clock算法Clock算法也叫做二次机会算法,是一种改良的FIFO算法。
它是基于FIFO算法的思想,并且每个页面都设置了一个使用位(use bit),用于记录该页面是否被使用过。
当需要置换一个页面时,检查该页面的使用位,如果该页面的使用位为1,则将该页面的使用位设置为0并移到队列的末尾,表示该页面有“二次机会”继续待在内存中;如果该页面的使用位为0,则选择该页面进行替换。
三、实验过程本次实验采用Python语言实现页面置换算法,并使用样例进行测试。
1、FIFO算法实现FIFO算法的实现非常简单,只需要用一个队列来维护已经在内存中的页面,当需要置换页面时,选择队列的第一个元素即可。
代码如下:```pythonfrom collections import dequeclass FIFO:def __init__(self, frame_num):self.frame_num = frame_numself.frames = deque(maxlen=frame_num)def access(self, page):if page in self.frames:return Falseif len(self.frames) >= self.frame_num:self.frames.popleft()self.frames.append(page)return True```2、LRU算法实现LRU算法的实现需要维护一个记录页面使用时间的链表或队列。
clock替换算法

Clock 替换算法(也称为时钟置换算法)是一种用于虚拟内存管理的页面替换策略。
它的目的是在需要为新页面在内存中分配空间时选择合适的页面进行替换。
Clock 算法是LRU(最近最少使用)算法的一种近似实现,通常用于操作系统的页面置换。
Clock 算法的命名来源于它的数据结构类似于一个时钟,页面按顺序排列成一个圆形队列。
Clock 算法采用以下方法进行操作:
1. 它维护一个指针,指向有序队列中的一个页面,该指针初次指向第一个页面。
2. 当需要替换某个页面时,算法检查当前指针所指向的页面。
3. 如果该页面的访问位(accessed bit)为 0,则选择该页面进行替换。
4. 如果访问位为 1,则将访问位设置为 0,并将指针移动到下一个页面。
5. 重复步骤 2-4,直到找到一个访问位为 0 的页面。
在这个过程中,访问位表示页面自上次访问以来是否被访问过。
如果页面被访问,其访问位将设置为 1;否则,访问位保持为 0。
Clock 算法使用这个信息来尝试近似 LRU 策略——即选择最近最少使用的页面进行替换。
通过这种方法,Clock 算法可以在较低的开销下实现合适的页面替换。
值得注意的是,虽然 Clock 算法尝试近似 LRU 策略,但它并不能完全等同于 LRU。
Clock 算法可能会产生较差的近似结果,尤其是在页面访问模式较为复杂时。
然而,由于其相对较低的实现成本,Clock 算法在许多操作系统中被用作默认的页面替换策略。
常用的页面调度算法

常用的页面调度算法一、引言在计算机科学中,页面调度算法是操作系统中的一种重要机制,用于管理计算机内存中的页面。
页面调度算法的目标是尽可能地提高内存的利用率,减少页面置换的次数,从而提高系统的性能和响应速度。
常用的页面调度算法有先进先出(FIFO)、最近最久未使用(LRU)和时钟(Clock)算法等。
本文将介绍这些常用的页面调度算法,并分析它们的优缺点及适用场景。
二、先进先出(FIFO)算法先进先出算法是最简单的页面调度算法之一。
它的原理是将最早进入内存的页面置换出去,即先进先出。
当内存空间不足时,操作系统将最早进入内存的页面替换出去,腾出空间给新的页面。
这种算法简单易实现,但是它没有考虑页面的使用频率和重要性,可能导致常用的页面被频繁替换,影响系统的性能。
三、最近最久未使用(LRU)算法最近最久未使用算法是一种常用的页面调度算法。
它的原理是根据页面的使用情况来进行页面置换。
当需要替换页面时,操作系统选择最近最久未使用的页面进行置换。
这种算法考虑了页面的使用频率,可以有效地提高内存的利用率。
然而,LRU算法的实现比较复杂,需要维护一个页面访问的时间戳列表,当页面被访问时,需要更新时间戳列表,这会带来额外的开销。
四、时钟(Clock)算法时钟算法是一种简化的页面调度算法,它是基于LRU算法的改进。
时钟算法使用一个循环链表来保存内存中的页面,并维护一个指针指向当前页面。
当需要替换页面时,时钟算法从当前页面开始顺时针扫描链表,找到一个未被访问的页面进行置换。
如果当前页面已被访问,则将访问位清零,并将指针指向下一个页面。
这种算法简化了LRU算法的实现,并且可以在O(1)的时间内完成页面置换操作。
五、比较和总结先进先出算法简单易实现,但没有考虑页面的使用频率和重要性;最近最久未使用算法考虑了页面的使用频率,可以提高内存的利用率,但实现较复杂;时钟算法是一种简化的LRU算法,可以在O(1)的时间内完成页面置换操作。
实验四操作系统存储管理实验报告

实验四操作系统存储管理实验报告一、实验目的本次实验的主要目的是深入理解操作系统中存储管理的基本原理和方法,通过实际操作和观察,掌握内存分配与回收、页面置换算法等关键概念,并能够分析和解决存储管理中可能出现的问题。
二、实验环境本次实验在装有 Windows 操作系统的计算机上进行,使用了 Visual Studio 等编程工具和相关的调试环境。
三、实验内容(一)内存分配与回收算法实现1、首次适应算法首次适应算法从内存的起始位置开始查找,找到第一个能够满足需求的空闲分区进行分配。
在实现过程中,我们通过建立一个空闲分区链表来管理内存空间,每次分配时从表头开始查找。
2、最佳适应算法最佳适应算法会选择能够满足需求且大小最小的空闲分区进行分配。
为了实现该算法,在空闲分区链表中,分区按照大小从小到大的顺序排列,这样在查找时能够快速找到最合适的分区。
3、最坏适应算法最坏适应算法则选择最大的空闲分区进行分配。
同样通过对空闲分区链表的排序和查找来实现。
(二)页面置换算法模拟1、先进先出(FIFO)页面置换算法FIFO 算法按照页面进入内存的先后顺序进行置换,即先进入内存的页面先被置换出去。
在模拟过程中,使用一个队列来记录页面的进入顺序。
2、最近最久未使用(LRU)页面置换算法LRU 算法根据页面最近被使用的时间来决定置换顺序,最近最久未使用的页面将被置换。
通过为每个页面设置一个时间戳来记录其最近使用的时间,从而实现置换策略。
3、时钟(Clock)页面置换算法Clock 算法使用一个环形链表来模拟内存中的页面,通过指针的移动和页面的访问标志来决定置换页面。
四、实验步骤(一)内存分配与回收算法的实现步骤1、初始化内存空间,创建空闲分区链表,并为每个分区设置起始地址、大小和状态等信息。
2、对于首次适应算法,从链表表头开始遍历,找到第一个大小满足需求的空闲分区,进行分配,并修改分区的状态和大小。
3、对于最佳适应算法,在遍历链表时,选择大小最接近需求的空闲分区进行分配,并对链表进行相应的调整。
LRU算法-与CLOCK算法

实验报告课程名称操作系统实验项目名______LRU算法模拟班级与班级代码实验室名称(或课室)专业任课教师学号:姓名:实验日期:2012 年 5 月20 日制姓名实验报告成绩评语:指导教师(签名)年月日说明:指导教师评分后,学年论文交院(系)办公室保存。
实验八LRU算法模拟一、实验目的(1)模拟实现LRU算法。
(2)模拟实现Clock算法。
(3)比较分析LRU算法、Clock算法。
二、实验内容(1)算法实现。
(2)拟定测试数据对算法的正确性进行测试。
(3)对比分析LRU算法和Clock算法各自的优缺点。
三、实验环境硬件要求:P4 2.0G 1G内存60G硬盘以上电脑软件要求:C、C++编程环境,Java编程环境四、实验步骤1.LRU算法(1)预备知识最近最久未使用(LRU)的页面置换算法,是根据页面调入内存后的使用情况进行决策的。
由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。
该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t ,当须淘汰一个页面时,选择现有页面中其t 值最大的,即最近最久未使用的页面予以淘汰。
(2)LRU 的实现(需要“堆栈”支持)可利用一个特殊的栈来保存当前使用的各个页面的页面号。
每当进程访问某页面时,便将该页面的页面号从栈中移出,将它压入栈顶。
因此,栈顶始终是最新被访问页面的编号,而栈底则是最近最久未使用页面的页面号。
假定现有一进程所访问的页面序列为:4,7,0,7,1,0,1,2,1,2,6随着进程的访问,栈中页面号的变化情况如图所示。
在访问页面6时发生了缺页,此时页面4是最近最久未被访问的页,应将它置换出去。
(2)具体的操作代码及其结果如下:#include<stdio.h> #include<iostream>#define num 204771012126#define max 65535typedef struct PB{int page;//当前页面号int seq_num;//对于页面最近一次被访问的序列号int fg;}Pb;int k;int seek(int seq[],int i,Pb a[],int k);int test1(int seq_i,int Pn,Pb a[]);int test2(Pb a[],int Pn);int LRU(int seq[],int i,int Pn,Pb pb[]);//页块中的页面的最近最久未使用位置int seek(int seq[],int i,Pb a[],int k){int flag=0;for(int j=i-1;j>=0;j--){if(a[k].page==seq[j]){flag=1;return j;break;}}if(flag==0)return -1;}//检测当前页面在不在内存中,如果在内存中,返回所在页块号;如果不在,返回-1int test1(int seq_i,int Pn,Pb a[]){int flag=0;for(int j=0;j<Pn;j++){if(a[j].page==seq_i){flag=1;return j;break;}}if(flag==0)return -1;}//检测有没有空页块,如果有空页块,返回页块号;如果没有,返回-1int test2(Pb a[],int Pn){int flag=0;for(int j=0;j<Pn;j++){if(a[j].page==-1){flag=1;return j;break;}}if(flag==0)return -1;}int LRU(int seq[],int i,int Pn,Pb pb[]) {int temp[20];int j;for(k=0;k<Pn;k++){temp[k]=seek(seq,i,pb,k);pb[k].fg=seek(seq,i,pb,k);}for(k=1;k<Pn;k++){int lastX=1;int tem;for(j=0;j<Pn-k;j++){if(temp[j]>temp[j+1]){tem=temp[j];temp[j]=temp[j+1];temp[j+1]=tem;lastX=0;}}if(lastX==1) break;}for(k=0;k<Pn;k++){if(pb[k].fg==temp[0]){printf("%d ",pb[k].page);return k;break;}}}void PCB(){Pb pb[10];//最多只允许0-9共10个页块号int Pn;int an=0;int seq[100];int i;float ar;printf("请输入页块数Pn:\n");scanf("%d",&Pn);printf("请输入%d位长的页面访问序列seq[%d]:\n",num,num); for(i=0;i<num;i++){scanf("%d",&seq[i]);}for(i=0;i<10;i++){pb[i].page=-1;pb[i].seq_num=-1;pb[i].fg=max;}printf("淘汰页面号依次为:\n");for(i=0;i<num;i++){//做20次int a,b;a=test1(seq[i],Pn,pb);b=test2(pb,Pn);if(a==-1){//不在内存中if(b!=-1){//没满pb[b].page=seq[i];pb[b].seq_num=i;an++;}else{//满了k=LRU(seq,i,Pn,pb);pb[k].page=seq[i];pb[k].seq_num=i;an++;}}}ar=(float)an/(float)num;printf("\n缺页次数为:%d\n缺页率为%f\n",an,ar);}void main(){PCB();}(2)运行调试,输出结果:程序完成后,进行调试编译,在弹出的框中输入页块数Pn,回车,然后输入20位长的页面访问序列seq[20],回车,实验结果将显示出该组数据的淘汰页面号、缺页次数和缺页率。
页面置换算法实验报告
页面置换算法实验报告页面置换算法实验报告一、引言在计算机操作系统中,页面置换算法是一种重要的内存管理策略。
当物理内存不足以容纳所有需要运行的进程时,操作系统需要根据一定的算法将部分页面从内存中换出,以便为新的页面腾出空间。
本实验旨在通过实际操作,对比不同的页面置换算法在不同场景下的性能表现。
二、实验背景在计算机系统中,每个进程都有自己的虚拟内存空间,而物理内存空间是有限的。
当进程需要访问某个页面时,如果该页面不在物理内存中,就会发生缺页中断,操作系统需要根据页面置换算法选择一个页面将其换出,然后将需要访问的页面换入。
常见的页面置换算法有先进先出(FIFO)、最近最久未使用(LRU)、时钟(Clock)等。
三、实验目的本实验旨在通过模拟不同的页面置换算法,比较它们在不同情况下的缺页率和效率。
通过实验结果,评估各个算法在不同场景下的优劣,为实际系统的内存管理提供参考。
四、实验设计与方法本实验选择了三种常见的页面置换算法进行比较:FIFO、LRU和Clock。
我们使用C++编程语言模拟了一个简单的内存管理系统,并通过产生不同的访存序列来模拟不同的场景。
实验中,我们设置了不同的物理内存大小,访存序列长度和页面大小,以模拟不同的系统环境。
五、实验结果与分析在实验中,我们分别测试了FIFO、LRU和Clock算法在不同的系统环境下的表现。
通过统计不同算法的缺页率和运行时间,得出以下结论:1. FIFO算法FIFO算法是最简单的页面置换算法,它按照页面进入内存的顺序进行置换。
实验结果表明,FIFO算法在缺页率方面表现一般,特别是在访存序列具有局部性的情况下,其性能明显下降。
这是因为FIFO算法无法区分不同页面的重要性,可能会将经常使用的页面换出,导致缺页率升高。
2. LRU算法LRU算法是一种基于页面访问时间的置换算法,它认为最近被访问的页面很可能在未来会被再次访问。
实验结果表明,LRU算法在缺页率方面表现较好,特别是在访存序列具有较强的局部性时,其性能明显优于FIFO算法。
页面置换算法实验报告
页面置换算法实验报告一、实验目的本次实验的目的是通过模拟页面置换算法的过程,了解不同算法的优缺点,掌握算法的实现方法,以及对算法的性能进行评估。
二、实验原理页面置换算法是操作系统中的一个重要概念,它是为了解决内存不足的问题而产生的。
当系统中的进程需要使用内存时,如果内存已经被占满,就需要将一些页面从内存中置换出去,以便为新的页面腾出空间。
页面置换算法就是用来决定哪些页面应该被置换出去的算法。
常见的页面置换算法有以下几种:1. 最佳置换算法(OPT)最佳置换算法是一种理论上的最优算法,它总是选择最长时间内不会被访问的页面进行置换。
但是,由于无法预测未来的页面访问情况,因此最佳置换算法无法在实际中使用。
2. 先进先出置换算法(FIFO)先进先出置换算法是一种简单的置换算法,它总是选择最先进入内存的页面进行置换。
但是,这种算法容易出现“抖动”现象,即频繁地将页面置换出去,然后再将其置换回来。
3. 最近最久未使用置换算法(LRU)最近最久未使用置换算法是一种比较常用的置换算法,它总是选择最长时间未被访问的页面进行置换。
这种算法可以避免“抖动”现象,但是实现起来比较复杂。
4. 时钟置换算法(Clock)时钟置换算法是一种改进的FIFO算法,它通过维护一个环形链表来实现页面置换。
当需要置换页面时,算法会从当前位置开始扫描链表,如果找到一个未被访问的页面,则将其置换出去。
如果扫描一圈后都没有找到未被访问的页面,则将当前位置的页面置换出去。
三、实验过程本次实验使用Python语言编写了一个页面置换算法模拟程序,可以模拟上述四种算法的过程,并输出算法的性能指标。
程序的主要流程如下:1. 读取输入文件,获取页面访问序列和内存大小等参数。
2. 根据选择的算法,初始化相应的数据结构。
3. 遍历页面访问序列,模拟页面置换的过程。
4. 输出算法的性能指标,包括缺页率、页面置换次数等。
下面分别介绍四种算法的实现方法。
1. 最佳置换算法(OPT)最佳置换算法需要预测未来的页面访问情况,因此需要遍历整个页面访问序列,找到最长时间内不会被访问的页面。
页面淘汰算法
页面淘汰算法一、什么是页面淘汰算法?页面淘汰算法是指在计算机系统中,为了减少内存的使用,将一些不常用的页面从内存中移除,以便为其他需要更多内存的程序腾出空间。
页面淘汰算法根据不同的策略选择要移除的页面,以最大化系统性能和资源利用率。
二、常见的页面淘汰算法有哪些?1. 最近最少使用算法(LRU)LRU算法是一种基于时间局部性原理的页面置换算法。
它认为如果一个页面最近被访问过,那么它可能在不久的将来也会被访问。
因此,LRU算法选择最近最少使用的页面进行淘汰。
2. 先进先出算法(FIFO)FIFO算法是一种简单而直观的页面置换策略。
它按照进入内存时间顺序进行淘汰,即先进入内存的页面先被淘汰。
3. 时钟置换算法(Clock)时钟置换算法是一种改进版FIFO算法。
它通过维护一个“指针”,指向最老的未被访问过的页面,并将该指针逐个往后移动。
当需要淘汰一个页面时,如果该页已被访问过,则将其标记为“未访问过”并继续移动指针,直到找到一个“未访问过”的页面为止。
4. 最不经常使用算法(LFU)LFU算法是一种基于统计局部性原理的页面置换算法。
它认为如果一个页面在一段时间内被访问的频率很低,那么它在未来也很少被访问。
因此,LFU算法选择最不经常使用的页面进行淘汰。
5. 随机置换算法(Random)随机置换算法是一种简单而随意的页面置换策略。
它随机选择一个页面进行淘汰,没有任何规则可言。
三、如何选择合适的页面淘汰算法?选择合适的页面淘汰算法需要考虑以下几个方面:1. 系统负载情况如果系统负载较重,应该选择效率较高、实现简单的置换算法,如FIFO和Clock;如果系统负载较轻,则可以选择效果更好但实现更复杂的LRU和LFU算法。
2. 计算资源不同的置换算法对计算资源的要求不同。
LRU和LFU需要记录每个页面最近或最少被访问的时间或次数,因此需要更多计算资源;而FIFO 和Random则只需要记录页面进入内存的时间或随机数,计算资源要求较低。
页面淘汰算法实验报告
操作系统实验报告课题:页面淘汰算法专业:班级:学号:姓名:年月日目录一实验目的 (3)二实验要求 (3)三背景知识 (3)四总体设计 (4)五详细设计 (7)六运行结果分析 (9)七心得体会 (13)八参考文献 (14)附:源代码 (15)一、实验目的本实验主要对操作系统中请求分页式内存管理及其应用的一些关键算法进行模拟。
学生通过设计与实现Clock算法,能够加强对相应理论的理解,并对了解操作系统内部的基本处理原理与过程也有很多益处。
利用简单的数据结构,模拟实现操作系统中的页面置换机制,通过写程序模拟实现上述三种内存页面置换算法,使学生进一步掌握内存页面置换的方法。
对操作系统中内存的管理有一个实践上的认识。
1、用C语言编写OPT、FIFO、LRU三种置换算法。
2、熟悉内存分页管理策略。
3、了解页面置换的算法。
4、掌握一般常用的调度算法。
5、根据方案使算法得以模拟实现。
6、锻炼知识的运用能力和实践能力。
二、实验要求●设计随机页面序号产生程序,并说明随机的性能和其性能可能对算法的影响●编写页面淘汰算法(FIFO、OPT、LRU)●结果数据的显示或提取●结果数据的分析几点说明:●设计并绘制算法流程,附加说明所需的数据结构●如何标记时间的先后、最久的将来、最久未被使用●描述Clock算法的基本原理、必要的数据结构、算法执行流程图、编码实现。
1)初始化:输入作业可占用的总页框数,初始化置空。
2)输入请求序列:输入一个作业页号访问请求序列,依次占用相应页框,直至全部占用;3)Clock算法:当页框全部占用后,对于后续新的页号访问请求,执行Clock 算法,淘汰1个页面后装入新的页号。
4)显示当前分配淘汰序列:显示淘汰的页号序列。
三、背景知识:在操作系统当中,在进程运行过程中,若其访问的页面不在内存中而需把他们调入内存,但内存已无空闲空间时,为了保证该进程能够正常的运行,系统必须从内存中调出一页程序或数据送到磁盘的兑换区中,但是应该是哪个页面被调出,需根据一定的算法来确定。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告课程名称操作系统实验项目名______LRU算法模拟班级与班级代码实验室名称(或课室)专业任课教师学号:姓名:实验日期:2012 年 5 月20 日制姓名实验报告成绩评语:指导教师(签名)年月日说明:指导教师评分后,学年论文交院(系)办公室保存。
实验八 LRU算法模拟一、实验目的(1)模拟实现LRU算法。
(2)模拟实现Clock算法。
(3)比较分析LRU算法、Clock算法。
二、实验内容(1)算法实现。
(2)拟定测试数据对算法的正确性进行测试。
(3)对比分析LRU算法和Clock算法各自的优缺点。
三、实验环境硬件要求:P4 2.0G 1G内存60G硬盘以上电脑软件要求:C、C++编程环境,Java编程环境四、实验步骤1.LRU算法(1)预备知识最近最久未使用(LRU)的页面置换算法,是根据页面调入内存后的使用情况进行决策的。
由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。
该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t ,当须淘汰一个页面时,选择现有页面中其t 值最大的,即最近最久未使用的页面予以淘汰。
(2)LRU 的实现(需要“堆栈”支持)可利用一个特殊的栈来保存当前使用的各个页面的页面号。
每当进程访问某页面时,便将该页面的页面号从栈中移出,将它压入栈顶。
因此,栈顶始终是最新被访问页面的编号,而栈底则是最近最久未使用页面的页面号。
假定现有一进程所访问的页面序列为:4,7,0,7,1,0,1,2,1,2,6随着进程的访问,栈中页面号的变化情况如图所示。
在访问页面6时发生了缺页,此时页面4是最近最久未被访问的页,应将它置换出去。
(2)具体的操作代码及其结果如下:#include<stdio.h> #include<iostream>#define num 20 #define max 65535 typedef struct PB{4771012126int page;//当前页面号int seq_num;//对于页面最近一次被访问的序列号int fg;}Pb;int k;int seek(int seq[],int i,Pb a[],int k);int test1(int seq_i,int Pn,Pb a[]);int test2(Pb a[],int Pn);int LRU(int seq[],int i,int Pn,Pb pb[]);//页块中的页面的最近最久未使用位置int seek(int seq[],int i,Pb a[],int k){int flag=0;for(int j=i-1;j>=0;j--){if(a[k].page==seq[j]){flag=1;return j;break;}}if(flag==0)return -1;}//检测当前页面在不在内存中,如果在内存中,返回所在页块号;如果不在,返回-1int test1(int seq_i,int Pn,Pb a[]){int flag=0;for(int j=0;j<Pn;j++){if(a[j].page==seq_i){flag=1;return j;break;}}if(flag==0)return -1;}//检测有没有空页块,如果有空页块,返回页块号;如果没有,返回-1 int test2(Pb a[],int Pn){int flag=0;for(int j=0;j<Pn;j++){if(a[j].page==-1){flag=1;return j;break;}}if(flag==0)return -1;}int LRU(int seq[],int i,int Pn,Pb pb[]){int temp[20];int j;for(k=0;k<Pn;k++){temp[k]=seek(seq,i,pb,k);pb[k].fg=seek(seq,i,pb,k);}for(k=1;k<Pn;k++){int lastX=1;int tem;for(j=0;j<Pn-k;j++){if(temp[j]>temp[j+1]){tem=temp[j];temp[j]=temp[j+1];temp[j+1]=tem;lastX=0;}}if(lastX==1) break;}for(k=0;k<Pn;k++){if(pb[k].fg==temp[0]){printf("%d ",pb[k].page);return k;break;}}}void PCB(){Pb pb[10];//最多只允许0-9共10个页块号int Pn;int an=0;int seq[100];int i;float ar;printf("请输入页块数Pn:\n");scanf("%d",&Pn);printf("请输入%d位长的页面访问序列seq[%d]:\n",num,num); for(i=0;i<num;i++){scanf("%d",&seq[i]);}for(i=0;i<10;i++){pb[i].page=-1;pb[i].seq_num=-1;pb[i].fg=max;}printf("淘汰页面号依次为:\n");for(i=0;i<num;i++){//做20次int a,b;a=test1(seq[i],Pn,pb);b=test2(pb,Pn);if(a==-1){//不在内存中if(b!=-1){//没满pb[b].page=seq[i];pb[b].seq_num=i;an++;}else{//满了k=LRU(seq,i,Pn,pb);pb[k].page=seq[i];pb[k].seq_num=i;an++;}}}ar=(float)an/(float)num;printf("\n缺页次数为:%d\n缺页率为%f\n",an,ar);}void main(){PCB();}(2)运行调试,输出结果:程序完成后,进行调试编译,在弹出的框中输入页块数Pn,回车,然后输入20位长的页面访问序列seq[20],回车,实验结果将显示出该组数据的淘汰页面号、缺页次数和缺页率。
注:实验结果中,输入的数据为:[12560 36536 56042 70435]。
LRU算法编译后的结果如下:(3)编译时出现的错误:调试时出错情况有三类:1)低级错误。
编写时字母写错,‘}’或‘;’丢失,等;2)警告错误。
使用指针错误,或定义的指针没有使用等;3)匹配错误。
在编译子程序时出现类型不匹配,以及一些语法错误等。
2、CLOCK算法(1)预备知识当采用简单Clock算法时,只需为每页设置一位访问位,再将内存中的所有页面都通过链接指针链接成一个循环队列。
当某页被访问时,其访问位被置1。
置换算法在选择一页淘汰时,只需检查页的访问位。
如果是0,就选择该页换出;若为1,则重新将它置0,暂不换出,而给该页第二次驻留内存的机会,再按照FIFO算法检查下一个页面。
当检查到队列中的最后一个页面时,若其访问位仍为1,则再返回到队首去检查第一个页面。
下图展示了该算法的流程和示例。
由于该算法是循环地检查各页面的使用情况,故称为Clock 算法。
但因该算法只有一位访问位,只能用它表示该页是否已经使用过,而置换时是将未使用过的页面换出去,故又把该算法称为最近未用算法NRU(Not Recently Used)。
(2)具体的操作代码如下:#include"StdAfx.h"#include<stdio.h>#include <time.h>#include <stdlib.h>#define M 3 //内存物理块数#define N 20 //虚拟内存尺寸int P; //工作集的起始位置int nin; //记录缺页次数//用于CLOCK算法的页面定义typedef struct page_clock{int num;int visit;替换指针}Page_clock;//用于改进的CLOCK算法的页面定义typedef struct page{int num; //页面号int visit; //是否访问int modify; //是否修改}Page;Page_clock b_clock[M]; //内存单元数ClockPage b[M]; //updating_clockint opt[M]; //optint ran[M]; //random replacementint fifo[M]; //FIFOint c[M][N]; //存储每个阶段状态//访问序列随机生成e个,e是工作集中包含的页数,m是工作集移动率void generate_list(int *list, int e, int m, int t){int i, j = 0, q =P, r;srand((unsigned)time(NULL));while (j < e){for (i = j;i < j + m;i++){if (i == e)break;list[i] = (q + rand() % e) % N; /*保证在虚拟内存的页号内*/ }j = i;r = rand() % 100;if (r < t)q = rand() % N;elseq = (q + 1) % N;}}//随机生产是否被修改的情况,prop(0...100),prop/100的概率未被修改void generate_modify(int *mo, int e, int prop){int i, t;for (i = 0;i < e;i++){t = rand() % 100;if (t > prop)mo[i] = 0;elsemo[i] = 1;}}//格式输出void print_format(int e){int i;printf(" ");for (i = 1;i < e;i++)printf(" ");printf(" \n");}//结果输出void print(int e,int *a){int j, i;print_format(e);for(j = 0;j < e;j++){printf(" %2d ",a[j]); //读入内存顺序}printf(" \n");printf("置换过程:");print_format(e);for(i = 0;i < M;i++){for(j = 0;j < e;j++){if(c[i][j] == -1)printf(" %c ",' ');elseprintf(" %2d ",c[i][j]);}printf(" \n");}print_format(e);}//Clock算法初始化void Init_Clock(Page_clock *b_clock){nin = 0;int i, j;for(i = 0;i < M;i++){b_clock[i].num = -1;b_clock[i].visit = 0;}for(i = 0;i < M;i++){for(j = 0;j < N;j++){c[i][j] = -1;}}}//改进的Clock算法初始化void Init_updatingClock(Page *b) {nin = 0;int i, j;for(i = 0;i < M;i++){b[i].num = -1;b[i].visit = 0;b[i].modify = 0;}for(i = 0;i < M;i++){for(j = 0;j < N;j++){c[i][j] = -1;}}}//Clock算法void Clock(int fold,Page_clock *b_clock) {int i, val = -1, p = 0; //p为查询指针for (i = 0;i < M;i++){if (fold == b_clock[i].num)val = i;}//页面在内存中if (val >= 0){b_clock[val].visit = 1;for(i = 0;i < M;i++){if (i != val){b_clock[i].visit = 0;}}}else{nin++;//初始化内存for (i = 0;i < M;i++){if (b_clock[i].num == -1){val = i;break;}}while (val < 0){if (b_clock[p].visit == 0)val = p;elseb_clock[p].visit = 0;p = (p + 1) % M;}b_clock[val].num = fold;b_clock[val].visit = 1;for(i = 0;i < M;i++){if (i != val){b_clock[i].visit = 0;}}}}//改进的Clock算法void Updating_Clock(int fold,int modiff, Page *b) { int i, p = -1; //p是查询指针int val = -1;//找是否在内存中for(i = 0;i < M;i++){if (fold == b[i].num)val = i;}if (val >= 0){b[val].visit = 1; //被访问b[val].modify = modiff;for(i = 0;i < M;i++){if (i != val){b[i].visit = 0;}}}else{nin++;//初始化内存for (i = 0;i < M;i++){if (b[i].num == -1){val = i;break;}}while (val < 0){//第一步扫描for (i = 0;i < M;i++){p = (p + 1) % M;if ((b[p].modify == 0) && (b[p].visit == 0)){val = p;break;}}//第二步扫描if (val < 0){for (i = 0;i < M;i++){p = (p + 1) % M;if ((b[p].modify == 1) && (b[p].visit == 0)){val = p;break;}else{b[p].visit = 0;}}}}//找到后,其他设置为未访问b[val].num = fold;b[val].modify = modiff;b[val].visit = 1;for(i = 0;i < M;i++){if (i != val){b[i].visit = 0;}}}}//主程序void main(){int a[N];int mo[N];int i,j;//产生随机访问串及是否修改串P = 1;int e, m, prop, t;printf("请输入工作集中包含的页数e和工作集移动率m:\n");scanf("%d %d",&e,&m);t = 50;generate_list(a, e, m, t);printf("请输入页面被修改的概率(*100):\n");scanf("%d",&prop);generate_modify(mo, e, prop);//Clock算法实现Init_Clock(b_clock);for(i = 0;i < e;i++){Clock(a[i],b_clock);for(j = 0;j < M;j++){c[j][i] = b_clock[j].num;}}printf("Clock算法的内存状态为:\n");print(e, a);nin = nin - M;printf("缺页次数为:%d\n缺页率:%.2f\n",nin,nin * 1.0 / e);printf("\n");//改进的Clock算法实现Init_updatingClock(b);for(i = 0;i < e;i++){Updating_Clock(a[i], mo[i], b);for(j = 0;j < M;j++){c[j][i] = b[j].num;}}printf("改进的Clock算法的内存状态为:\n");print(e, a);for(j = 0;j < e;j++){printf(" %2d ",mo[j]); //是否修改序列串}printf(" \n");print_format(e);nin = nin - M;printf("缺页次数为:%d\n缺页率:%.2f\n",nin,nin * 1.0 / e);printf("\n");}Clock算法实验运行结果:五、实验分析(1)页块数可变,LRU算法结果正确。