实验四 页式虚拟存储管理中地址转换和页式中断 FIFO LRU OPT C++版本
- 格式:doc
- 大小:60.50 KB
- 文档页数:11
实验四页式虚拟存储管理中地址转换和页式中断FIFO一、实验目的深入了解页式存储管理如何实现地址转换;进一步认识页式虚拟存储管理中如何处理缺页中断以及页面置换算法。
二、实验主要内容编写程序完成页式虚拟存储管理中地址转换过程和模拟缺页中断的处理。
实验具体内容包括:首先对给定的地址进行转换工作,若发现缺页则先进行缺页中断处理,然后再进行地址转换;最后编写主函数对所做工作进行测试。
假定主存64KB,每个主存块1024字节,作业最大支持到64KB,系统中每个作业分得主存块4块。
三、实验原理1)地址转换过程:首先从逻辑地址中的高位取得页号,然后根据页号查页表,得到块号;然后从逻辑地址中的低位取得页内地址,将块号和页内地址合并即得到物理地址。
2)缺页中断处理根据页号查找页表,判断该页是否在主存储器中,若该页标志位“0”,形成缺页中断。
操作系统让调出中断处理程序处理中断。
四、实验方法与步骤实现地址转换与缺页中断处理,主要考虑三个问题:第一,设计页式虚拟存储管理方式中页表的数据结构;第二,地址转换算法的实现;第三,缺页中断处理算法的实现。
1)设计页表的数据结构页式虚拟存储管理方式中页表除了页号和该页对应的主存块号外,至少还要包括存在标志(该页是否在主存),磁盘位置(该页的副本在磁盘上的位置)和修改标志(该页是否修改过)。
在实验中页表用数组模拟,其数据结构定义如下:struct{int lnumber; //页号int flag; //表示页是否在主存中,“1”表示在,“0”表示不在int pnumber; // 该页所在主存块的块号int write; //该页是否被修改过,“1”表示修改过,“0“表示没有修改过int dnumber; //该页存放在磁盘上的位置,即磁盘块号}page[n]; //页表定义2)地址转换算法的实现地址转换是由硬件完成的,实验中使用软件程序模拟地址转换过程。
在实验中,每个主存块1024字节,则块内地址占10位;主存64KB,则主存共64块,即块号占6位;物理地址共占16位;作业最大64KB,则作业最大占64块,即页号占6位,逻辑地址共占16位。
目录1 需求分析 (2)1.1 目的和要求 (2)1.2 研究内容 (2)2 概要设计 (2)2.1 FIFO算法 (3)2.2 LRU算法 (3)2.3 OPT算法 (3)2.4 输入新的页面引用串 (3)3 详细设计 (4)3.1 FIFO(先进先出)页面置换算法: (4)3.2 LRU(最近最久未使用)置换算法: (4)3.3 OPT(最优页)置换算法 (4)4 测试 (5)5 运行结果 (5)6 课程设计总结 (9)7 参考文献 (10)8 附录:源程序清单 (10)1 需求分析1.1 目的和要求在熟练掌握计算机虚拟存储技术的原理的基础上,利用一种程序设计语言模拟实现几种置换算法,一方面加深对原理的理解,另一方面提高学生通过编程根据已有原理解决实际问题的能力,为学生将来进行系统软件开发和针对实际问题提出高效的软件解决方案打下基础。
1.2 研究内容模拟实现页式虚拟存储管理的三种页面置换算法(FIFO(先进先出)、LRU (最近最久未使用)和OPT(最长时间不使用)),并通过比较性能得出结论。
前提:(1)页面分配采用固定分配局部置换。
(2)作业的页面走向和分得的物理块数预先指定。
可以从键盘输入也可以从文件读入。
(3)置换算法的置换过程输出可以在显示器上也可以存放在文件中,但必须清晰可读,便于检验。
2 概要设计本程序主要划分为4个功能模块,分别是应用FIFO算法、应用LRU算法、应用OPT算法和页面引用串的插入。
1.1各模块之间的结构图2.1 FIFO 算法该模块的主要功能是对相应页面引用串进行处理,输出经过FIFO 算法处理之后的结果。
2.2 LRU 算法该模块的主要功功能是对相应的页面引用串进行处理,输出经过LRU 算法处理之后的结果。
2.3 OPT 算法该模块的主要功功能是对相应的页面引用串进行处理,输出经过OPT 算法处理之后的结果。
2.4 输入新的页面引用串该模块的主要功能是用户自己输入新的页面引用串,系统默认的字符串是0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,用户可以自定义全新的20个数字页面引用串。
2022年上海理工大学计算机科学与技术专业《操作系统》科目期末试卷B(有答案)一、选择题1、在磁盘上容易导致存储碎片发生的物理文件结构是()A.链接B.连续C.索引D.索引和链接2、下列选项中,磁盘逻辑格式化程序所做的T作是()I.对磁盘进行分区II.建立文件系统的根目录III.确定磁盘扇区校验码所占位数IV.对保存空闲磁盘块信息的数据结构进行初始化,A. 仅IIB.仅II、IVC.仅III,IVD.仅I、II、IV3、为多道程序提供的共享资源不足时,可能会产生死锁。
但是,不当的()也可能产生死锁。
A.进程调度顺序B.进程的优先级C.时间片大小D.进程推进顺序4、下列关于管程的叙述中,错误的是()。
A.管程只能用于实现进程的互斥B.管程是由编程语言支持的进程同步机制C.任何时候只能有一个进程在管程中执行D.管程中定义的变量只能被管程内的过程访问5、下列关于银行家算法的叙述中,正确的是()A.银行家算法可以预防死锁B.当系统处于安全状态时,系统中…定无死锁进程C.当系统处于不安全状态时,系统中一定会出现死锁进程D.银行家算法破坏了产生死锁的必要条件中的“请求和保持”条件6、下列存储管理方式中,会产生内部碎片的是()。
I.请求分段存储管理II.请求分页存储管理III.段页式分区管理IV.[固定式分区管理A.I、II、IIIB.III,IVC.只有IID.II、III、IV7、在页式虚拟存储管理系统中,采用某些页面置换算法,会出现Belady异常现象,即进程的缺页次数会随着分配给该进程的页框个数的增加而增加。
下列算,法中,可能出现Belady异常现象的是()。
I.LRU算法 II.FIFO算法 III.OPT 算法A. 仅IB.仅IIC.仅I、IIID. 仅I、III8、下列关于操作系统的论述中,正确的是()。
A.对于批处理作业,必须提供相应的作业控制信息B.对于分时系统,不一定全部提供人机交互功能C.从响应角度看,分时系统与实时系统的要求相似D.在采用分时操作系统的计算机系统中,用户可以独占计算机操作系统中的文件系统9、下列选项中,在用户态执行的是()。
实验三
课程名称:操作系统
课程类型:必修
实验项目名称:存储器管理
实验题目:模拟分页式存储管理中硬件的地址转换和产生缺页中断。
一、实验目的
在计算机系统中,为了提高主存利用率,往往把辅助存储器(如磁盘)作为主存储器的扩充,使多道运行的作业的全部逻辑地址空间总和可以超出主存的绝对地址空间。
用这种办法扩充的主存储器称为虚拟存储器。
通过本实验帮助同学理解在分页式存储管理中怎样实现虚拟存储器。
二、实验要求
模拟分页式存储管理中硬件的地址转换。
需要为作业建立页表,应说明哪些页已在主存,哪些页尚未装入主存。
作业执行时,指令中的逻辑地址指出了参加运算的操作存放的页号和单元号,硬件的地址转换机构按页号查页表,若该页对应标志为“1”,则表示该页已在主存,这时根据关系式“绝对地址=块号×块长+单元号”计算出欲访问的主存单元地址。
若产生缺页中断,引出操作系统来处理这个中断事件。
如果主存中已经没有空闲块,则可用FIFO 页面调度算法把该作业中最先进入主存的一页调出,存放到磁盘上,然后再把当前要访问的页装入该块。
调出和装入后都要修改页表页表中对应页的标志。
三、设计思想
1、物理设计
全局变量定义如下:
struct info//页表
{
int block;//物理页架号
int disk;//在磁盘上的物理块号
int flag; //内外标志
}pagelist[10];
int po;//队列标记
int t[4];
2、程序流程图
(见下图)
图1-1主程序的流程图
图1-2 init( )的流程图。
操作系统实验报告四【实验题目】虚拟内存页面置换算法【实验目的】通过这次实验,加深对虚拟内存页面置换概念的理解,进一步掌握先进先出FIFO,最佳置换OPI和最近最久未使用LRU页面置换算法的实现方法。
【实验内容】问题描述:设计程序模拟先进先出FIFO,最佳置换OPI和最近最久未使用LRU页面置换算法的工作过程。
假设内存中分配给每个进程的最小物理块数为m,在进程运行过程中要访问的页面个数为n,页面访问序列为P1, …,Pn,分别利用不同的页面置换算法调度进程的页面访问序列,给出页面访问序列的置换过程,计算每种算法缺页次数和缺页率。
程序要求如下:1)利用先进先出FIFO,最佳置换OPI和最近最久未使用LRU三种页面置换算法模拟页面访问过程。
2)模拟三种算法的页面置换过程,给出每个页面访问时的内存分配情况。
3)输入:最小物理块数m,页面个数n,页面访问序列P1, … ,Pn,算法选择1-FIFO,2-OPI,3-LRU。
4)输出:每种算法的缺页次数和缺页率。
【实验要求】1) 上机前认真复习页面置换算法,熟悉FIFO,OPI,LRU三种页面分配和置换算法的过程;2) 上机时独立编程、调试程序;3) 根据具体实验要求,完成好实验报告(包括实验的目的、内容、要求、源程序、实例运行结果截图)。
【源代码】//--------------- YeMianZhiHuan.cpp -----------------#include "iostream.h"const int DataMax=100;const int BlockNum = 10;int DataShow[BlockNum][DataMax]; // 用于存储要显示的数组bool DataShowEnable[BlockNum][DataMax]; // 用于存储数组中的数据是否需要显示//int Data[DataMax]={4,3,2,1,4,3,5,4,3,2,1,5,6,2,3,7,1,2,6,1}; // 测试数据//int N = 20; // 输入页面个数int Data[DataMax]; // 保存数据int Block[BlockNum]; // 物理块int count[BlockNum]; // 计数器int N ; // 页面个数int M;//最小物理块数int ChangeTimes;void DataInput(); // 输入数据的函数void DataOutput();void FIFO(); // FIFO 函数void Optimal(); // Optimal函数void LRU(); // LRU函数///*int main(int argc, char* argv[]){DataInput();// DataInput();// FIFO();// Optimal();// LRU();// return 0;int menu;while(true){cout<<endl;cout<<"* 菜单选择*"<<endl;cout<<"*******************************************************"<<endl;cout<<"* 1-FIFO *"<<endl;cout<<"* 2-Optimal *"<<endl;cout<<"* 3-LRU *"<<endl;cout<<"* 0-EXIT *"<<endl;cout<<"*******************************************************"<<endl;cin>>menu;switch(menu){case 1: FIFO();break;case 2: Optimal();break;case 3: LRU();break;default: break;}if(menu!=1&&menu!=2&&menu!=3) break;}}//*/void DataInput(){cout<<"请输入最小物理块数:";cin>>M;while(M > BlockNum) // 大于数据个数{cout<<"物理块数超过预定值,请重新输入:"; cin>>M;}cout<<"请输入页面的个数:";cin>>N;while(N > DataMax) // 大于数据个数{cout<<"页面个数超过预定值,请重新输入:"; cin>>N;}cout<<"请输入页面访问序列:"<<endl;for(int i=0;i<N;i++)cin>>Data[i];}void DataOutput(){int i,j;for(i=0;i<N;i++) // 对所有数据操作{cout<<Data[i]<<" ";}cout<<endl;for(j=0;j<M;j++){cout<<" ";for(i=0;i<N;i++) // 对所有数据操作{if( DataShowEnable[j][i] )cout<<DataShow[j][i]<<" ";elsecout<<" ";}cout<<endl;}cout<<"缺页次数: "<<ChangeTimes<<endl;cout<<"缺页率: "<<ChangeTimes*100/N<<"%"<<endl; }void FIFO(){int i,j;bool find;int point;int temp; // 临时变量ChangeTimes = 0;for(j=0;j<M;j++)for(i=0;i<N;i++)DataShowEnable[j][i] = false; // 初始化为false,表示没有要显示的数据for(i=0;i<M;i++){count[i] = 0; // 大于等于BlockNum,表示块中没有数据,或需被替换掉// 所以经这样初始化(3 2 1),每次替换>=3的块,替换后计数值置1,// 同时其它的块计数值加1 ,成了(1 3 2 ),见下面先进先出程序段}for(i=0;i<N;i++) // 对有所数据操作{// 增加countfor(j=0;j<M;j++)count[j]++;find = false; // 表示块中有没有该数据for(j=0;j<M;j++){if( Block[j] == Data[i] ){find = true;}}if( find ) continue; // 块中有该数据,判断下一个数据// 块中没有该数据ChangeTimes++; // 缺页次数++if( (i+1) > M ) // 因为i是从0开始记,而M指的是个数,从1开始,所以i+1 {//获得要替换的块指针temp = 0;for(j=0;j<M;j++){if( temp < count[j] ){temp = count[j];point = j; // 获得离的最远的指针}}}else point = i;// 替换Block[point] = Data[i];count[point] = 0; // 更新计数值// 保存要显示的数据for(j=0;j<M;j++){DataShow[j][i] = Block[j];DataShowEnable[i<M?(j<=i?j:i):j][i] = true; // 设置显示数据}}// 输出信息cout<< endl;cout<<"FIFO => "<< endl;DataOutput();}void Optimal(){int i,j,k;bool find;int point;int temp; // 临时变量,比较离的最远的时候用ChangeTimes = 0;for(j=0;j<M;j++)for(i=0;i<N;i++)DataShowEnable[j][i] = false; // 初始化为false,表示没有要显示的数据// for(i=0;i<M;i++)// {// count[i] = 0 ; //// }for(i=0;i<N;i++) // 对有所数据操作{find = false; // 表示块中有没有该数据for(j=0;j<M;j++){if( Block[j] == Data[i] )find = true;}if( find ) continue; // 块中有该数据,判断下一个数据// 块中没有该数据,最优算法ChangeTimes++; // 缺页次数++for(j=0;j<M;j++){// 找到下一个值的位置find = false;for( k =i;k<N;k++){if( Block[j] == Data[k] ){find = true;count[j] = k;break;}}if( !find ) count[j] = N;}if( (i+1) > M ) // 因为i是从0开始记,而BlockNum指的是个数,从1开始,所以i+1 {//获得要替换的块指针temp = 0;for(j=0;j<M;j++){if( temp < count[j] ){temp = count[j];point = j; // 获得离的最远的指针}}}else point = i;// 替换Block[point] = Data[i];// 保存要显示的数据for(j=0;j<M;j++){DataShow[j][i] = Block[j];DataShowEnable[i<M?(j<=i?j:i):j][i] = true; // 设置显示数据}}// 输出信息cout<< endl;cout<<"Optimal => "<< endl;DataOutput();}void LRU(){int i,j;bool find;int point;int temp; // 临时变量ChangeTimes = 0;for(j=0;j<M;j++)for(i=0;i<N;i++)DataShowEnable[j][i] = false; // 初始化为false,表示没有要显示的数据for(i=0;i<M;i++){count[i] = 0 ;}for(i=0;i<N;i++) // 对有所数据操作{// 增加countfor(j=0;j<M;j++)count[j]++;find = false; // 表示块中有没有该数据for(j=0;j<M;j++){if( Block[j] == Data[i] ){count[j] = 0;find = true;}}if( find ) continue; // 块中有该数据,判断下一个数据// 块中没有该数据ChangeTimes++; // 缺页次数++if( (i+1) > M ) // 因为i是从0开始记,而BlockNum指的是个数,从1开始,所以i+1 {//获得要替换的块指针temp = 0;for(j=0;j<M;j++){if( temp < count[j] ){temp = count[j];point = j; // 获得离的最远的指针}}}else point = i;// 替换Block[point] = Data[i];count[point] = 0;// 保存要显示的数据for(j=0;j<M;j++){DataShow[j][i] = Block[j];DataShowEnable[i<M?(j<=i?j:i):j][i] = true; // 设置显示数据}}// 输出信息cout<< endl;cout<<"LRU => "<< endl;DataOutput();}【效果截图】以作业为测试数据:。
页式虚拟存储管理中地址转换和缺页中断的模拟
实验目的:
1.深入了解页式虚拟存储管理技术如何实现地址转换。
2.进一步认识页式虚拟存储管理中如何处理缺页中断。
实验要求:
编写程序模拟实现页式虚拟存储管理中的地址转换过程以及缺
页中断的处理过程。
实验指导:
1.请求分页中硬件地址变换过程。
(1)
自己设计一个主存分配表。
(2)对逻辑地址进行划分为页号和页内地址
(3)越界检查,若越界直接中断退出程序的执行。
(不越界情况下)检索页表分2种情况:其一,若该页在内存,则找到其对应的物理块号;合并块号和块内地址形成物理地址。
进行输出。
(4)其二,若该页不再内存,产生缺页中断,调用缺页中断子
程序执行缺页中断处理过程。
中断返回后重新执行被中断的指令。
2.采用某一种页面置换算法实现分页管理的缺页调度。
(1)当硬件发出缺页中断后转操作系统处理缺页中断。
查看主存分块表看有无可用空闲块。
若有则为进程分配一块。
若无空闲块,当采用一种页面置换算法(例如FIFO形成队列),其头部放在变量K 中淘汰最先进入主存的一页,若该页修改过,好要重新写回磁盘。
然后再把当前要访问的页装入该内存块,并修改页表和存储分块表。
数组P中各个元素为作业已在主存的页号。
假定作业最多可分配m块。
当淘汰一页时,总是淘汰P[K]所指页。
之后调整数组P:
P[K]=要装入的页;
K=(K+1)mod m;
流程图如下:。
操作系统实验二〔第一题〕一.实验内容模拟分页式虚拟存储管理中硬件的地址转换和缺页中断,以及选择页面调度算法处理缺页中断。
二.实验目的在电脑系统总,为了提高主存利用率,往往把辅助存储器作为主存储器的扩充,使多道运行的作业的全部逻辑地址空间综合可以超出主存的绝对地址空间。
用这种方法扩充的主存储区成为虚拟存储器。
三.实验题目模拟分页式存储管理中硬件的地址转换和产生缺页中断。
四.程序清单//// 操作实验二.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"#include<iostream>#include<string>#include<fstream>using namespace std;class ins{private:string ope;long int page;long int unit;public:ins(){ }ins(string o,long int p,long int u):ope(o),page(p),unit(u){}void setope(string o){ ope=o;}void setpage(long int p){ page=p;}void setunit(long int u){ unit=u;}string getope(){return ope;}long int getpage(){return page;}long int getunit(){return unit;}};class work{private:long int Page;int sym;long int inum;long int onum;public:work(){}work(long int P, int s,long int i,long int o):Page(P),sym(s),inum(i),onum(o){} void setPage(long int P){ Page=P;}void setsym( int s){ sym=s;}void setinum(long int i){ inum=i;}void setonum(long int o){ onum=o;}long int getPage(){return Page;}int getsym(){return sym;}long int getinum(){return inum;}long int getonum(){return onum;}};void diaodu(work *w,ins * i,int numofins){ for(int j=0;j<numofins;j++){long int tempofk;long int a =i[j].getpage();for(int k=0;k<7;k++) //7是页表的页数if(w[k].getPage()!=a)continue;else{tempofk=k;break;}if(w[tempofk].getsym()==1)cout<<"绝对地址:"<<w[tempofk].getinum()*128+i[j].getunit()<<" "<<"磁盘地址为:"<<w[tempofk].getonum()<<" "<<"操作为:"<<i[j].getope()<<endl;else cout<<"*"<<"发生缺页中断"<<endl;}}int main(){ins*INS=new ins[12];INS[0].setope ("+");INS[0].setpage(0);INS[0].setunit(70);INS[1].setope ("+");INS[1].setpage(1);INS[1].setunit(50);INS[2].setope ("×");INS[2].setpage(2);INS[2].setunit(15);INS[3].setope ("存"); INS[3].setpage(3);INS[3].setunit(21);INS[4].setope ("取"); INS[4].setpage(0);INS[4].setunit(56);INS[5].setope ("-");INS[5].setpage(6);INS[5].setunit(40);INS[6].setope ("移位"); INS[6].setpage(4);INS[6].setunit(53);INS[7].setope ("+");INS[7].setpage(5);INS[7].setunit(23);INS[8].setope ("存"); INS[8].setpage(1);INS[8].setunit(37);INS[9].setope ("取"); INS[9].setpage(2);INS[9].setunit(78);INS[10].setope ("+"); INS[10].setpage(4);INS[10].setunit(1);INS[11].setope ("存"); INS[11].setpage(6);INS[11].setunit(84);work*W =new work[7]; ifstream in("g://operate1.txt");long int p;int s;long int i;long int o;for(int jj=0;jj<7 ;jj++){in>>p;in>>s;in>>i;in>>o ;W[jj].setPage(p);W[jj].setsym(s);W[jj].setinum(i);W[jj].setonum(o);}diaodu(W,INS,12);}五.结果显示操作系统实验二〔第二题〕一.用先进先出〔FIFO〕九.程序清单/ 操作系统实验二.cpp : 定义控制台应用程序的入口点。
实验目地通过模拟实现请求页式存储管理地几种基本页面置换算法,了解虚拟存储技术地特点,掌握虚拟存储请求页式存储管理中几种基本页面置换算法地基本思想和实现过程,并比较它们地效率.文档收集自网络,仅用于个人学习实验内容设计一个虚拟存储区和内存工作区,并使用下述算法计算访问命中率.1、最佳淘汰算法(OPT)2、先进先出地算法(FIFO )3、最近最久未使用算法(LRU )4、最不经常使用算法(LFU )5、最近未使用算法(NUR )命中率=1-页面失效次数/页地址流长度实验准备本实验地程序设计基本上按照实验内容进行.即首先用srand()和rand()函数定义和产生指令序列,然后将指令序列变换成相应地页地址流,并针对不同地算法计算出相应地命中率.文档收集自网络,仅用于个人学习(1)通过随机数产生一个指令序列,共320 条指令.指令地地址按下述原则生成:A:50%地指令是顺序执行地B:25%地指令是均匀分布在前地址部分C:25%地指令是均匀分布在后地址部分具体地实施方法是:A:在[0,319]地指令地址之间随机选取一起点mB:顺序执行一条指令,即执行地址为m+1 地指令C:在前地址[0,m+1] 中随机选取一条指令并执行,该指令地地址为m'D:顺序执行一条指令,其地址为m'+1E:在后地址[m'+2,319]中随机选取一条指令并执行F:重复步骤A-E ,直到320 次指令(2)将指令序列变换为页地址流设:页面大小为1K ;用户内存容量 4 页到32 页;用户虚存容量为32K.在用户虚存中,按每K 存放10 条指令排列虚存地址,即320 条指令在虚存中地存放方式为:第0 条-第9 条指令为第0 页(对应虚存地址为[0,9])第10 条-第19 条指令为第1页(对应虚存地址为[10,19])第310 条-第319条指令为第31 页(对应虚存地址为[310,319])按以上方式,用户指令可组成32 页.实验指导一、虚拟存储系统UNIX 中,为了提高内存利用率,提供了内外存进程对换机制;内存空间地分配和回收均以页为单位进行;一个进程只需将其一部分(段或页)调入内存便可运行;还支持请求调页地存储管理方式.文档收集自网络,仅用于个人学习当进程在运行中需要访问某部分程序和数据时,发现其所在页面不在内存,就立即提出请求(向CPU 发出缺中断),由系统将其所需页面调入内存.这种页面调入方式叫请求调页.文档收集自网络,仅用于个人学习为实现请求调页,核心配置了四种数据结构:页表、页框号、访问位、修改位、有效位、保 护位等 .二、页面置换算法当 CPU 接收到缺页中断信号,中断处理程序先保存现场,分析中断原因,转入缺页中断处 理程序 .该程序通过查找页表,得到该页所在外存地物理块号 .如果此时内存未满,能容纳新 页,则启动磁盘 I/O 将所缺之页调入内存,然后修改页表 .如果内存已满,则须按某种置换 算法从内存中选出一页准备换出, 是否重新写盘由页表地修改位决定, 然后将缺页调入, 修 改页表 .利用修改后地页表,去形成所要访问数据地物理地址,再去访问内存数据 .整个页面地调入过程对用户是透明地 .文档收集自网络,仅用于个人学习 常用地页面置换算法有1、最佳置换算法( Optimal )2、先进先出法( Fisrt In First Out )3、最近最久未使用( Least Recently Used )4、最不经常使用法( Least Frequently Used )5、最近未使用法( No Used Recently )三、参考程序:view plaincopy to clipboardprint?50 ··60·· ··70·····80· ··90 ·100····110 ·· ·120·130 ···140 ····150 文档收集自网络,仅用于个人学习#define TRUE 1 #define FALSE 0 #define INV ALID -1#define NULL 0 #define total_instruction 320 #define total_vp 32 #define clear_period 50 typedef struct{int pn,pfn,counter,time;}pl_type;pl_type pl[total_vp]; struct pfc_struct{int pn,pfn;struct pfc_struct *next; };typedef struct pfc_struct pfc_type;pfc_type pfc[total_vp],*freepf_head,*busypf_head,*busypf_tail; int diseffect, a[total_instruction];int page[total_instruction], offset[total_instruction]; 文档收集自网络,仅用于个人学习int initialize(int);int FIFO(int); int LRU(int); int LFU(int);10· ····20·· ·30··· ·40/* 指令流长 */ /* 虚页长 */ /*清 0周期*/ /* 页面结构 *//* 页面结构数组 */ /* 页面控制结构 */文档收集自网络,仅用于个人学习int NUR(int);int OPT(int);int main( ){int s,i,j;srand(10*getpid()); /* 由于每次运行时进程号不同,故可用来作为初始化随机数队列地“种子” */ 文档收集自网络,仅用于个人学习s=(float)319*rand( )/32767/32767/2+1; // for(i=0;i<total_instruction;i+=4) /* 产生指令队列*/ { if(s<0||s>319){ printf("When i==%d,Error,s==%d\n",i,s); exit(0);}a[i]=s; /* 任选一指令访问点m*/a[i+1]=a[i]+1; /* 顺序执行一条指令*/ a[i+2]=(float)a[i]*rand( )/32767/32767/2; /* 执行前地址指令m' */ 文档收集自网络,仅用于个人学习a[i+3]=a[i+2]+1; /* 顺序执行一条指令*/s=(float)(318-a[i+2])*rand( )/32767/32767/2+a[i+2]+2; 文档收集自网络,仅用于个人学习if((a[i+2]>318)||(s>319)) printf("a[%d+2],a number which is :%d and s==%d\n",i,a[i+2],s); 文档收集自网络,仅用于个人学习}for (i=0;i<total_instruction;i++) /* 将指令序列变换成页地址流*/{page[i]=a[i]/10; offset[i]=a[i]%10;for(i=4;i<=32;i++) /*用户内存工作区从 4 个页面到32 个页面*/{printf("---%2d page frames---\n",i);FIFO(i);LRU(i);LFU(i);NUR(i);OPT(i);} return 0;}int initialize(total_pf) int total_pf;人学习/* 初始化相关数据结构*/ 文档收集自网络,仅用于个人学习/* 用户进程地内存页面数*/ 文档收集自网络,仅用于个for(i=0;i<total_instruction;i++){if(pl[page[i]].pfn==INV ALID){diseffect+=1; if(freepf_head==NULL){p=busypf_head->next;pl[busypf_head->pn].pfn=INVALID;freepf_head=busypf_head; /* 释放忙页面队列地第一个页面 */ freepf_head->next=NULL; busypf_head=p;}p=freepf_head->next;/* 按 FIFO 方式调新页面入内存页面 */freepf_head->next=NULL; freepf_head->pn=page[i];pl[page[i]].pfn=freepf_head->pfn; if(busypf_tail==NULL){int i; diseffect=0;for(i=0;i<total_vp;i++){pl[i].pn=i;pl[i].pfn=INV ALID; pl[i].counter=0; pl[i].time=-1;}/* 置页面控制结构中地页号,页面为空 */ /* 页面控制结构中地访问次数为 0,时间为 -1*/for(i=0;i<total_pf-1;i++){pfc[i].next=&pfc[i+1]; pfc[i].pfn=i; } /* 建立 pfc[i-1] 和 pfc[i] 之间地链接 */pfc[total_pf-1].next=NULL; pfc[total_pf-1].pfn=total_pf-1; freepf_head=&pfc[0]; return 0;}int FIFO(total_pf) int total_pf;{int i,j; pfc_type *p; initialize(total_pf);/* 空页面队列地头指针为 pfc[0]*//* 先进先出算法 *//* 用户进程地内存页面数 *//* 初始化相关页面控制用数据结构 */busypf_head=busypf_tail=NULL; /* 忙页面队列头,队列尾链接 */ /* 页面失效 *//* 失效次数 */ /* 无空闲页面*/busypf_head=busypf_tail=freepf_head; else {busypf_tail->next=freepf_head; busypf_tail=freepf_head;}freepf_head=p;}elsepl[page[i]].time=present_time;收集自网络,仅用于个人学习}}printf("FIFO:%6.4f\n",1-(float)diseffect/320); return 0;}int LRU (total_pf) int total_pf;{int min,minj,i,j,present_time; initialize(total_pf); present_time=0;for(i=0;i<total_instruction;i++){if(pl[page[i]].pfn==INV ALID){diseffect++;if(freepf_head==NULL){/*最近最久未使用算法*//* 页面失效 *//* 无空闲页面 */min=32767;for(j=0;j<total_vp;j++) if(min>pl[j].time&&pl[j].pfn!=INV {/* 找出 time 地最小值 */ALID) min=pl[j].time;minj=j;}freepf_head=&pfc[pl[minj].pfn];pl[minj].pfn=INV ALID; pl[minj].time=-1;freepf_head->next=NULL;//腾出一个单元}pl[page[i]].pfn=freepf_head->pfn;pl[page[i]].time=present_time; freepf_head=freepf_head->next;//有空闲页面 ,改为有效//减少一个 free 页面/*free 页面减少一个 *///命中则增加该单元地访问次数文档present_time++;}printf("LRU:%6.4f\n",1-(float)diseffect/320); return 0;}int NUR(total_pf) int total_pf;{ int i,j,dp,cont_flag,old_dp; pfc_type *t;initialize(total_pf); dp=0;for(i=0;i<total_instruction;i++) { if (pl[page[i]].pfn==INV ALID) {diseffect++;if(freepf_head==NULL) { cont_flag=TRUE; old_dp=dp;while(cont_flag)if(pl[dp].counter==0&&pl[dp].pfn!=INV cont_flag=FALSE; else{dp++;if(dp==total_vp)dp=0; if(dp==old_dp)for(j=0;j<total_vp;j++)pl[j].counter=0;}freepf_head=&pfc[pl[dp].pfn]; pl[dp].pfn=INV ALID;freepf_head->next=NULL;}pl[page[i]].pfn=freepf_head->pfn; freepf_head=freepf_head->next;}else pl[page[i]].counter=1; if(i%clear_period==0) for(j=0;j<total_vp;j++) pl[j].counter=0;}printf("NUR:%6.4f\n",1-(float)diseffect/320); return 0;/* 最近未使用算法 *//* 页面失效 */ /* 无空闲页面 */ALID)}int OPT(total_pf) /* 最佳置换算法*/ int total_pf;{int i,j, max,maxpage,d,dist[total_vp];pfc_type *t;initialize(total_pf);for(i=0;i<total_instruction;i++){ //printf("In OPT for//i=86;i=176;206;250;220,221;192,193,194;258;274,275,276,277,278; 学习if(pl[page[i]].pfn==INV ALID) /* 页面失效*/{diseffect++;if(freepf_head==NULL) /* 无空闲页面*/{for(j=0;j<total_vp;j++)if(pl[j].pfn!=INV ALID) dist[j]=32767; /* 最大"距离" */ 习else dist[j]=0;d=1;for(j=i+1;j<total_instruction;j++){if(pl[page[j]].pfn!=INV ALID)dist[page[j]]=d;d++;}max=-1;for(j=0;j<total_vp;j++)if(max<dist[j]){max=dist[j];maxpage=j;}freepf_head=&pfc[pl[maxpage].pfn];freepf_head->next=NULL;pl[maxpage].pfn=INV ALID;}pl[page[i]].pfn=freepf_head->pfn;freepf_head=freepf_head->next;}}printf("OPT:%6.4f\n",1-(float)diseffect/320);return 0;}int LFU(total_pf) /* 最不经常使用置换法*/1,i=%d\n",i);文档收集自网络,仅用于个人文档收集自网络,仅用于个人学int total_pf;{int i,j,min,minpage; pfc_type *t;initialize(total_pf); for(i=0;i<total_instruction;i++) { if(pl[page[i]].pfn==INV ALID)/* 页面失效 */{ diseffect++; if(freepf_head==NULL) /* 无空闲页面 */ { min=32767; for(j=0;j<total_vp;j++) {if(min>pl[j].counter&&pl[j].pfn!=INV ALID){min=pl[j].counter; minpage=j; }pl[j].counter=0;}freepf_head=&pfc[pl[minpage].pfn];pl[minpage].pfn=INV ALID; freepf_head->next=NULL;}pl[page[i]].pfn=freepf_head->pfn; //有空闲页面 , 改为有效 pl[page[i]].counter++;freepf_head=freepf_head->next;// 减少一个 free 页面}else pl[page[i]].counter++;}printf("LFU:%6.4f\n",1-(float)diseffect/320); return 0;}#define TRUE 1#define FALSE 0 #define INV ALID -1#define NULL 0 #define total_instruction 320 #define total_vp 32 #define clear_period 50typedef struct { int pn,pfn,counter,time; }pl_type;pl_type pl[total_vp]; struct pfc_struct{/* 页面控制结构 */int pn,pfn;struct pfc_struct *next; };typedef struct pfc_struct pfc_type;pfc_type pfc[total_vp],*freepf_head,*busypf_head,*busypf_tail; 文档收集自网络,仅用于个人学习int diseffect,a[total_instruction];int page[total_instruction], offset[total_instruction]; 文档收集自网络,仅用于个人学习int initialize(int); int FIFO(int); int LRU(int);/* 指令流长 */ /* 虚页长 */ /*清0周期*/ /* 页面结构 *//* 页面结构数组 */int LFU(int);int NUR(int);int OPT(int);int main( ){int s,i,j;srand(10*getpid()); /* 由于每次运行时进程号不同,故可用来作为初始化随机数队列地“种子” */ 文档收集自网络,仅用于个人学习s=(float)319*rand( )/32767/32767/2+1; // for(i=0;i<total_instruction;i+=4) /* 产生指令队列*/ {if(s<0||s>319){ printf("When i==%d,Error,s==%d\n",i,s); exit(0);}a[i]=s; /* 任选一指令访问点m*/a[i+1]=a[i]+1; /* 顺序执行一条指令*/ a[i+2]=(float)a[i]*rand( )/32767/32767/2; /* 执行前地址指令m' */ 文档收集自网络,仅用于个人学习a[i+3]=a[i+2]+1; /* 顺序执行一条指令*/s=(float)(318-a[i+2])*rand( )/32767/32767/2+a[i+2]+2; 文档收集自网络,仅用于个人学习if((a[i+2]>318)||(s>319))printf("a[%d+2],a number which is :%d and s==%d\n",i,a[i+2],s); 文档收集自网络,仅用于个人学习}for (i=0;i<total_instruction;i++) /* 将指令序列变换成页地址流*/ {page[i]=a[i]/10; offset[i]=a[i]%10;for(i=4;i<=32;i++) /*用户内存工作区从4个页面到32个页面*/ { printf("---%2d page frames---\n",i);FIFO(i);LRU(i);LFU(i);NUR(i);OPT(i);}return 0;int initialize(total_pf) int total_pf; /*初始化相关数据结构*/ 文档收集自网络,仅用于个人学习/*用户进程地内存页面数*/ 文档收集自网络,仅用于个人学}习{int i;diseffect=0;for(i=0;i<total_vp;i++){pl[i].pn=i;pl[i].pfn=INV ALID; /* 置页面控制结构中地页号,页面为空*/ pl[i].counter=0;pl[i].time=-1; /* 页面控制结构中地访问次数为0,时间为-1*/ }for(i=0;i<total_pf-1;i++){pfc[i].next=&pfc[i+1];pfc[i].pfn=i;} /* 建立pfc[i-1] 和pfc[i] 之间地链接*/pfc[total_pf-1].next=NULL;pfc[total_pf-1].pfn=total_pf-1;freepf_head=&pfc[0]; return 0;}int FIFO(total_pf)int total_pf;{int i,j;pfc_type *p;initialize(total_pf); /* 空页面队列地头指针为pfc[0]*//* 先进先出算法*//* 用户进程地内存页面数*//* 初始化相关页面控制用数据结构*/busypf_head=busypf_tail=NULL; /* 忙页面队列头,队列尾链接*/ for(i=0;i<total_instruction;i++){/* 页面失效*/if(pl[page[i]].pfn==INV ALID){diseffect+=1; /* 失效次数*/if(freepf_head==NULL) /* 无空闲页面*/{p=busypf_head->next;pl[busypf_head->pn].pfn=INV ALID;freepf_head=busypf_head; /* 释放忙页面队列地第一个页面*/freepf_head->next=NULL;busypf_head=p;}p=freepf_head->next; /* 按FIFO 方式调新页面入内存页面*/freepf_head->next=NULL;freepf_head->pn=page[i]; pl[page[i]].pfn=freepf_head->pfn;if(busypf_tail==NULL)busypf_head=busypf_tail=freepf_head;else{ busypf_tail->next=freepf_head; /*free 页面减少一个*/ busypf_tail=freepf_head;} freepf_head=p;}} printf("FIFO:%6.4f\n",1-(float)diseffect/320);return 0;}int LRU (total_pf) /*最近最久未使用算法*/int total_pf;{int min,minj,i,j,present_time;initialize(total_pf);present_time=0;for(i=0;i<total_instruction;i++){if(pl[page[i]].pfn==INV ALID) {diseffect++;min=32767;/* 页面失效*/if(freepf_head==NULL){/* 无空闲页面*/for(j=0;j<total_vp;j++) /* 找出time 地最小值*/ if(min>pl[j].time&&pl[j].pfn!=INV ALID){min=pl[j].time;minj=j;} freepf_head=&pfc[pl[minj].pfn]; //腾出一个单元pl[minj].pfn=INV ALID;pl[minj].time=-1;freepf_head->next=NULL;}pl[page[i]].pfn=freepf_head->pfn;pl[page[i]].time=present_time;freepf_head=freepf_head->next; }else //有空闲页面,改为有效//减少一个free 页面pl[page[i]].time=present_time; 自网络,仅用于个人学习//命中则增加该单元地访问次数文档收集present_time++;}printf("LRU:%6.4f\n",1-(float)diseffect/320);return 0;}int NUR(total_pf)int total_pf;{ int i,j,dp,cont_flag,old_dp;pfc_type *t;initialize(total_pf);dp=0;for(i=0;i<total_instruction;i++){ if (pl[page[i]].pfn==INV ALID) {diseffect++;if(freepf_head==NULL){ cont_flag=TRUE;old_dp=dp;while(cont_flag)if(pl[dp].counter==0&&pl[dp].pfn!=INV cont_flag=FALSE;else{dp++;if(dp==total_vp)dp=0; /* 最近未使用算法*//* 页面失效*//* 无空闲页面*/ ALID)if(dp==old_dp)for(j=0;j<total_vp;j++)pl[j].counter=0;}freepf_head=&pfc[pl[dp].pfn];pl[dp].pfn=INV ALID;freepf_head->next=NULL;}pl[page[i]].pfn=freepf_head->pfn;freepf_head=freepf_head->next;}elsepl[page[i]].counter=1;if(i%clear_period==0)for(j=0;j<total_vp;j++)pl[j].counter=0;}printf("NUR:%6.4f\n",1-(float)diseffect/320);return 0;}int OPT(total_pf) /* 最佳置换算法*/int total_pf;{int i,j, max,maxpage,d,dist[total_vp];pfc_type *t;initialize(total_pf);for(i=0;i<total_instruction;i++){ //printf("In OPT for 1,i=%d\n",i);//i=86;i=176;206;250;220,221;192,193,194;258;274,275,276,277,278; 文档收集自网络,仅用于个人学习if(pl[page[i]].pfn==INV ALID) /* 页面失效*/{diseffect++;if(freepf_head==NULL) /* 无空闲页面*/{for(j=0;j<total_vp;j++)if(pl[j].pfn!=INV ALID) dist[j]=32767; /* 最大"距离" */ 文档收集自网络,仅用于个人学习elsedist[j]=0;d=1;for(j=i+1;j<total_instruction;j++){if(pl[page[j]].pfn!=INV ALID)dist[page[j]]=d;d++;}max=-1;for(j=0;j<total_vp;j++)if(max<dist[j]){max=dist[j];maxpage=j;}freepf_head=&pfc[pl[maxpage].pfn];freepf_head->next=NULL; pl[maxpage].pfn=INVALID;}pl[page[i]].pfn=freepf_head->pfn;freepf_head=freepf_head->next;}}printf("OPT:%6.4f\n",1-(float)diseffect/320);return 0;}int LFU(total_pf) /* 最不经常使用置换法 */int total_pf;{int i,j,min,minpage;pfc_type *t;initialize(total_pf); for(i=0;i<total_instruction;i++){ if(pl[page[i]].pfn==INV ALID) /* 页面失效 */{ diseffect++;if(freepf_head==NULL) /* 无空闲页面 */{ min=32767; for(j=0;j<total_vp;j++){if(min>pl[j].counter&&pl[j].pfn!=INVALID){min=pl[j].counter;minpage=j;}pl[j].counter=0;}freepf_head=&pfc[pl[minpage].pfn];pl[minpage].pfn=INV ALID;freepf_head->next=NULL;}pl[page[i]].pfn=freepf_head->pfn; pl[page[i]].counter++; freepf_head=freepf_head->next;}else pl[page[i]].counter++;} printf("LFU:%6.4f\n",1-(float)diseffect/320);return 0;}五、分析1、从几种算法地命中率看, OPT 最高,其次为 NUR 相对较高,而 FIFO 与LRU 相差无几, 最低地是 LFU. 但每个页面执行结果会有所不同 .文档收集自网络,仅用于个人学习//有空闲页面 , 改为有效// 减少一个 free 页面2、OPT 算法在执行过程中可能会发生错误五、思考1、为什么OPT 在执行时会有错误产生?本文来自CSDN 博客,转载请标明出处:/followingturing/archive/2010/12/22/6091196.aspx 文档收集自网络,仅用于个人学习版权申明本文部分内容,包括文字、图片、以及设计等在网上搜集整理。
实验报告五实验名称:模拟页面置换算法FIFO、LRU的实现日期:2015-12-9 班级:13级计科学号:姓名:一、实验目的了解页面置换的概念,理解页面置换的算法加深对页面置换算法的理解。
二、实验内容Java编程语言实现FIFO和LUR页面算法。
三、项目要求与分析FIFO算法当需要置换页面时,主要通过置换最早进入内存的页面从而达到先进先出的目的。
LRU算法当需要置换页面时,主要通过置换进入内存中最久没有被访问的页面而达到最近最久未使用的目的。
程序中可以通过标志位进行记录。
四、具体实现1.FIFO算法实现代码以及运行结果:public class FIFO {/*** 内存块的个数*/public static int N ;/*** 内存块数组*/Object[] array = new Object[N];/*** 要访问的页面数组*/public static int[]visit;private int size;/*** 内存是非空为否* @return*/public boolean isEmpty() {if(0 == size)return true;elsereturn false;}/*** 内存是非空满* @return*/public boolean isFulled() {if(size >= N)return true;elsereturn false;}/*** 元素(页框)的个数* @return*/public int size() {return size;}/*** 查找元素o在数组中的位置* @param o* @return*/public int indexOfElement(Object o) { for(int i=0; i<N; i++) {if(o == array[i]) {return i;}}return -1;}/*** 页面转换* @param obj*/public Object trans(Object obj){Object e = null;int t = 0;if(indexOfElement(obj) != -1) {t = indexOfElement(obj);for(int i=t; i<size-1; i++) {array[i] = array[i+1];}array[size-1] = obj;} else {if(!isFulled()){array[size] = obj;size ++;} else {for(int i=0; i<size-1; i++) {array[i] = array[i+1];}array[size-1] = obj;}}if( -1 == t) {return null;} else {return array[t];}}/*** 输出内存区中的各数据*/public void showMemoryBlock() {for(int i=0; i<size; i++) {System.out.print(array[i] + " "); }}/*** 清空队列(页框)*/public void clear(){}/*** @param args*/public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.print("请输入内存块的数量:");N=sc.nextInt();System.out.print("请输入总页面数目:");int n=sc.nextInt();visit=new int[n];System.out.println("请输入各个页的页面号码:");for(int i=0;i<n;i++)visit[i]=sc.nextInt();FIFO fifo = new FIFO();for(int i=0; i<visit.length; i++) {fifo.trans(visit[i]);fifo.showMemoryBlock();System.out.println();}运行结果:2.LUR算法实现代码以及运行结果:public class LRU {static int volum;// 栈的容量static List<Integer>list=new LinkedList<Integer>();//链表用来模拟栈存放页面static int[]visit;//要访问的页面数组static int count=0;//记录缺页次数public static void main(String []args){Scanner sc = new Scanner(System.in);System.out.print("请输入栈的容量:");volum=sc.nextInt();System.out.print("请输入总页面数目:");int n=sc.nextInt();visit=new int[n];System.out.println("请输入各个页的页面号码:");for(int i=0;i<n;i++)visit[i]=sc.nextInt();sLRU();//调用最近最久未使用算法System.out.println("置换页面的数目为:"+count);}public static void sLRU(){int index=0;while(index<visit.length){boolean flag=false;if(list.size()<=volum){for(int i=0;i<list.size();i++){if((int)(list.get(i))==visit[index]){list.remove(i);//先删除list.add(visit[index]);//再添加到尾部flag=true;break;}}if(!flag){if(list.size()<volum){//如果栈未满,而且此页面没有在栈中,就将它入栈list.add(visit[index]);}else{//如果栈已经满了,且该页面号码没有在栈中,就把栈底元素删除,将新页插入int temp=list.get(0);list.remove(0);//最开始一个换出list.add(visit[index]);//加到末尾count++;System.out.println("开始换页了,将栈底的"+temp+"换出"); System.out.println("这也是没有办法的事情,毕竟栈是有限的");}}System.out.print("经过第"+(index+1)+"个页面的栈内容为");for(int k=0;k<list.size();k++)System.out.print(list.get(k)+" ");System.out.println();index++;}运行结果:五、所遇问题与解决方法问题:针对于FIFO算法定义选择在内存中驻留时间最久的页面予以淘汰,对于内存中的驻留时间理解复杂了不知道如何下手。
虚拟存储器实验报告一、实验目的本次虚拟存储器实验的目的在于深入理解虚拟存储器的工作原理,掌握其基本概念和关键技术,通过实际操作和观察,分析虚拟存储器对系统性能的影响,并能够运用所学知识解决在实验过程中遇到的问题。
二、实验环境本次实验使用的操作系统为 Windows 10,开发工具为 Visual Studio 2019,编程语言为 C++。
实验所使用的计算机配置为:Intel Core i7 处理器,16GB 内存,512GB 固态硬盘。
三、实验原理虚拟存储器是一种利用硬盘等辅助存储器来扩充主存容量的技术。
它将程序的逻辑地址空间与物理地址空间分开,使得程序可以使用比实际物理内存更大的地址空间。
当程序访问的地址不在物理内存中时,系统会通过页面置换算法将暂时不用的页面换出到硬盘,将需要的页面换入到物理内存中。
虚拟存储器的实现主要依赖于页式存储管理和地址转换机制。
页式存储管理将逻辑地址空间划分为固定大小的页面,物理地址空间也划分为相同大小的页框。
地址转换通过页表来完成,页表记录了逻辑页面与物理页框的对应关系。
四、实验内容1、页面置换算法的实现首先实现了先进先出(FIFO)页面置换算法。
创建一个固定大小的物理内存页框数组,模拟物理内存。
当需要装入新页面时,如果物理内存已满,按照先进入的页面先被置换的原则选择置换页面。
接着实现了最近最少使用(LRU)页面置换算法。
为每个页面设置一个访问时间戳,当需要置换页面时,选择访问时间最久远的页面进行置换。
2、虚拟地址到物理地址的转换设计了一个简单的页表结构,包括逻辑页号、物理页框号和有效位等字段。
输入一个虚拟地址,通过查找页表将其转换为物理地址。
如果页面不在物理内存中,触发页面置换算法进行页面调入。
3、性能分析对不同大小的程序和不同的页面置换算法,测量其页面缺失率和执行时间。
分析页面大小、物理内存大小等因素对虚拟存储器性能的影响。
五、实验步骤1、初始化实验环境设定物理内存大小、页面大小等参数。
实验四页式虚拟存储管理中地址转换和页式中断FIFO一、实验目的深入了解页式存储管理如何实现地址转换;进一步认识页式虚拟存储管理中如何处理缺页中断以及页面置换算法。
二、实验主要内容编写程序完成页式虚拟存储管理中地址转换过程和模拟缺页中断的处理。
实验具体内容包括:首先对给定的地址进行转换工作,若发现缺页则先进行缺页中断处理,然后再进行地址转换;最后编写主函数对所做工作进行测试。
假定主存64KB,每个主存块1024字节,作业最大支持到64KB,系统中每个作业分得主存块4块。
三、实验原理1)地址转换过程:首先从逻辑地址中的高位取得页号,然后根据页号查页表,得到块号;然后从逻辑地址中的低位取得页内地址,将块号和页内地址合并即得到物理地址。
2)缺页中断处理根据页号查找页表,判断该页是否在主存储器中,若该页标志位“0”,形成缺页中断。
操作系统让调出中断处理程序处理中断。
四、实验方法与步骤实现地址转换与缺页中断处理,主要考虑三个问题:第一,设计页式虚拟存储管理方式中页表的数据结构;第二,地址转换算法的实现;第三,缺页中断处理算法的实现。
1)设计页表的数据结构页式虚拟存储管理方式中页表除了页号和该页对应的主存块号外,至少还要包括存在标志(该页是否在主存),磁盘位置(该页的副本在磁盘上的位置)和修改标志(该页是否修改过)。
在实验中页表用数组模拟,其数据结构定义如下:struct{int lnumber; //页号int flag; //表示页是否在主存中,“1”表示在,“0”表示不在int pnumber; // 该页所在主存块的块号int write; //该页是否被修改过,“1”表示修改过,“0“表示没有修改过int dnumber; //该页存放在磁盘上的位置,即磁盘块号}page[n]; //页表定义2)地址转换算法的实现地址转换是由硬件完成的,实验中使用软件程序模拟地址转换过程。
在实验中,每个主存块1024字节,则块内地址占10位;主存64KB,则主存共64块,即块号占6位;物理地址共占16位;作业最大64KB,则作业最大占64块,即页号占6位,逻辑地址共占16位。
(用主存的大小计算物理地址位数,用最大作业大小计算逻辑地址位数)。
在页式虚拟存储管理方式中,作业信息作为副本放在磁盘上,作业执行时仅把作业信息的部分页面装入主存储器,作业执行时若访问的页面在主存中,则进行地址转换,若访问的页面不在主存中,则产生一个“缺页中断”,由操作系统把当前所需要的页面装入主存储器后,再次执行时才可以按上述方法进行地址转换。
模拟地址转换流程度3) 缺页中断处理算法的实现缺页处理过程简单阐述如下:a) 根据当前执行指令中逻辑地址的页号查找页表,判断该页是否在主存储器中,若该页标志为“0”,形成缺页中断。
中断装置通过交换PSW 让操作系统的中断处理程序占用处理器。
b) 操作系统处理缺页中断的方法及时查主存分配表,找一个空闲主存块;若无空闲块,查页表,选择一个已在主存的页面,把它暂时调出主存。
若在执行过程中该页被修改过,则需将该页信息写回磁盘,否则不比写回;c) 找出该页的位置,启动磁盘读出该页的信息,把磁盘上读出的信息装入第2不找到的主存块,修改页表中该页的标志为“1”;d) 由于产生缺页中断的那条指令还没有执行完,所以页面装入后应该重新执行被中断的指令。
当重新执行该指令时,由于要访问的页面已在主存中,所以可以正常执行。
关于第二步的查找装入新页面的主存块处理方式,不同系统采用的策略可能有所不同,这里采用局部置换算法,就是每个作业分得一定的主存块,只能在分得的主存块内查找空闲块,若无空闲主存块,则从该作业中选择一个页面淘汰出主存。
实验中采用局部置换算法。
使用局部置换算法时,存在这样一个问题:就是在分配给作业主存空间时,装入哪些页?有的系统采取不装入任何一页,当执行过程中需要时才将其调入。
有点系统采用页面预置的方法,事先估计可能某些页面会先用到,在分配主存块后将这些页面装入。
在本实验中采用第二种方法,分配主存空间时将前几页调入主存,假定系统中每个作业分得主存块m 块,则将第 0~m-1页装入主存。
因为是模拟硬件工作,所有在实验中如果访问的页不再主存中时,则输入该页页号,表示硬件产生缺页中断,然后直接转去缺页中断处理;由于采用页面预置方法,在给定的主存块中一定无空闲块,只能淘汰已在主存的一页;没有启动磁盘的工作,淘汰的页面需要写回磁盘时,用输入页号表示,调入新的一页时,将该页在页表中的存在标志置为“1”,输出页号表示将该页调入主存。
当主存中无空闲块时,为装入一个页面,必须按照某种算法从已在主存的页中选择一页,将它暂时调出主存,让出主存空间,用来存放装入的页面,这个工作称为“页面调度”。
常用的页面调度算法有:先进现出、最近最少用算法、和最近最不常用算法。
在本实验中采用先进现出调度算法。
先进现出算法总是选择驻留在主存时间最长的一页调出。
实验中把主存储器的页的页号按照进入主存的先后次序拍成队列,每次总是调出对首的页,当装入一个新页后,把新页的页号排入对尾。
实验中,用一个数组存放页号的队列。
假定分配给作业的主存块数为m ,数组可由m 个元素组成,p[0],p[1],p[2]……p[m-1];对首指针head;采用页面预置的方法,页号队列的长度总是m ,tail等于(head+1)%m 。
因此可以使用一个指针,只用head即可。
在装入一个新的页时,装入页和淘汰页同时执行,当装入一个新的页时,将其页号存入数组:淘汰页的页号=p[head];p[head]=新装入页的页号;head=(head+1)%m;实验执行一条指令时,不模拟指令的执行,只是考虑指令执行是否修改页面,若修改页面,则将该页的页表中的修改标志位置“1”,然后输出转换后的物理地址,并输出物理地址来表示一条指令执行完成;如果访问的页不在主存时,则产生缺页中断,然后直接转去缺页中断处理,最后模拟中断返回,就是返回冲进进行地址转换。
因为没有实际主存,所有在模拟程序中首先手工输入页表信息,创建该作业的页表;然后循环执行假定的指令,观察地址转换情况。
五、练习题采用LRU页面调度算法编程实现上述虚拟页式存储管理的地址转换。
源代码#include<iostream.h>#define n 64 //页表的最大长度#define length 4 //系统为每个作业分配的主存块数struct{int lnumber; //页号int flag; //表示页是否在主存中,“1”表示在,“0”表示不在int pnumber; // 该页所在主存块的块号int write; //该页是否被修改过,“1”表示修改过,“0“表示没有修改过int dnumber; //该页存放在磁盘上的位置,即磁盘块号}page[n]; //页表定义int m;int page_length; //页表的实际长度int p[length]; //用向量模拟主存int head;void page_interrupt(int); //缺页中断处理函数void command(unsigned, int); //命令处理函数void main(){int lnumber,pnumber,write,dnumber;unsigned laddress;int i;cout<<"输入页表的信息,创建页表(页号从0开始,若页号为-1,则结束输入)\n";cout<<"请输入页号和辅存地址:";cin>>lnumber>>dnumber;cin.ignore ();i=0;while(lnumber!=-1){page[i].lnumber=lnumber;page[i].flag=0;page[i].write=0;page[i].dnumber=dnumber;i++;cout<<"请输入页号和辅存地址:";cin>>lnumber>>dnumber;}//预先将输入的页调入主存块中page_length=i;cout<<"输入主存块号(输入少于或者等于"<<i<<"个数据,若块号数为-1,则结束输入):";cin>>pnumber;cin.ignore ();m=0;head=0;while(m<length&&pnumber!=-1){if(m<i){page[m].pnumber=pnumber;page[m].flag=1;//调入主存后,标志为置1p[m]=m; //记录主存中的页号m++;}cout<<"输入主存块号(输入少于或者等于"<<i<<"个数据,若块号数为-1,则结束输入):";cin>>pnumber;cin.ignore ();}//whilecout<<"输入指令性质(1-修改,0-不需要,其他-结束程序运行)和逻辑地址\n"<<"逻辑地址最大能支持2的16次方-1=65535。
\n";cout<<"输入指令性质:";cin>>write;cin.ignore ();cout<<"输入逻辑地址:";cin>>laddress;cin.ignore ();while(write==0||write==1){command(laddress,write); //将输入的逻辑地址转换成物理地址cout<<"输入指令性质:";cin>>write;cin.ignore ();if(write!=0&&write!=1) break;cout<<"输入逻辑地址:";cin>>laddress;cin.ignore ();}//while}//main/*中断处理函数,采用先进先出的页面调度算法*/void page_interrupt(int lnumber){int j;cout<<"发生缺页中断"<<lnumber<<endl;j=p[head];p[head]=lnumber;head=(head+1)%m;if(page[j].write==1)cout<<"将页"<<j<<" 写回磁盘第"<<page[j].dnumber<<" 块!\n";page[j].flag=0;page[lnumber].pnumber=page[j].pnumber;page[lnumber].flag=1;page[lnumber].write=0;cout<<"淘汰主存块"<<page[j].pnumber<<" 中的页"<<j<<" ,从磁盘第"<<page[lnumber].dnumber<<" 块中调入页"<<lnumber<<endl;}/*地址转换函数,将逻辑地址转换成物理地址,如果要查找的页不在主存当中则产生缺页中断*/void command(unsigned laddress,int write){unsigned paddress,ad,pnumber;int lnumber;kk:lnumber=laddress>>10; //取逻辑地址高6位,页号ad=laddress&0x3ff; //页内地址cout<<"该逻辑地址的页号为:"<<lnumber<<" 页内地址为:"<<ad<<endl;if(lnumber>=page_length){ //页号大于页表的长度,则无效页号cout<<"该页不存在!\n";return;}if(page[lnumber].flag==1){ //页号为lnumber 在内存当中pnumber=page[lnumber].pnumber;paddress=pnumber<<10|ad;cout<<"逻辑地址是:"<<laddress<<" 对应物理地址是:"<<paddress<<endl;if(write==1) //该页被修改过page[lnumber].write=1;}else{ //页号为lnumber不在内存当中,则产生缺页中断page_interrupt(lnumber);goto kk;}}//command页式存储管理OPT ,LRU实验报告一、实验目的:掌握分页式存储管理的基本概念和实现方法。