操作系统之页面置换模拟程序设计_NRU改进

介绍

  1. 假设分给一作业的内存块数为4,每个页面中可存放10条指令。

  2. 用C语言设计一个程序,模拟一作业的执行过程。设该作业共有320条指令,即它的地址空间为32页,目前它的所有页面都还未调入内存。在模拟过程中,如果所访问的指令已经在内存,则显示其物理地址,并转下一条指令。如果所访问的指令尚未装入内存,则发生缺页,此时需记录缺页的次数,并将相应页调入内存。如果4个内存块中均已装入该作业的虚页面,则需进行页面置换。最后显示其物理地址,并转下一条指令。在所有320条指令执行完毕后,请计算并显示作业运行过程中发生的缺页率。

  3. 置换算法:请考虑 NRU改进算法。

  4. 作业中指令的访问次序要求按下述原则生成:

    • 50%的指令是顺序执行的。
    • 25%的指令是均匀分布在前地址(即低地址)部分。
    • 25%的指令是均匀分布在后地址(即高地址)部分。

    具体的实施办法是:
    ① 在[0,319]之间随机选取一条起始执行指令,其序号为m;
    ② 顺序执行下一条指令,即序号为m+1的指令;
    ③ 通过随机数,跳转到前地址部分[0,m-1]中的某条指令处,其序号为m1;
    ④ 顺序执行下一条指令,即序号为m1+1的指令;
    ⑤ 通过随机数,跳转到后地址部分[m1+2,319]中的某条指令处,其序号为m2;
    ⑥ 顺序执行下一条指令,即序号为m2+1的指令;
    ⑦ 重复“跳转到前地址部分、顺序执行、跳转到后地址部分、顺序执行”的过程,直至执行完全部320条指令。

  5. 指令序列转换成页访问序列。
    第 0 条-第 9 条指令为第0页(对应虚存地址为[0,9])
    第10条-第19条指令为第1页(对应虚存地址为[10,19])
    ………………………………
    第310条-第319条指令为第31页(对应虚存地址为[310,319])

最近未用(Not Recently Used, NRU)算法_改进

CLOCK算法是给每一帧关联一个附加位,称为使用位。当某一页首次装入主存时,该帧的使用位设置为1;当该页随后再被访问到时,它的使用位也被置为1。对于页替换算法,用于替换的候选帧集合看做一个循环缓冲区,并且有一个指针与之相关联。当某一页被替换时,该指针被设置成指向缓冲区中的下一帧。当需要替换一页时,操作系统扫描缓冲区,以查找使用位被置为0的一帧。每当遇到一个使用位为1的帧时,操作系统就将该位重新置为0;如果在这个过程开始时,缓冲区中所有帧的使用位均为0,则选择遇到的第一个帧替换;如果所有帧的使用位均为1,则指针在缓冲区中完整地循环一周,把所有使用位都置为0,并且停留在最初的位置上,替换该帧中的页。由于该算法循环地检查各页面的情况,故称为CLOCK算法,又称为最近未用(Not Recently Used, NRU)算法.
而其改进算法不仅考虑使用情况A,还增加了置换代价(修改位M)。
则有四类页面 (根据A,M):
第1类:无访问(A=0) ,无修改(M=0) ;
第2类:无访问(A=0) ,有修改(M=1) ;
第3类:有访问(A=1) ,无修改(M=0) ;
第4类:有访问(A=1) ,有修改(M=1) ;

算法描述

  1. 从指针指向的当前位置开始扫描循环队列。寻找A=0,M=0页面(第一类页面)
  2. 若第一步失败,则重新开始寻找A=0,M=1页面(第二类页面)。并将经过的页面访问位置0。
  3. 若第二步失败,则返回开始位置,此时所有访问位均为0。重复第一步。(实际上是寻找第三类页面)
    若仍失败,重复第二步。(实际上是寻找第四类页面)

代码

//页面置换_NRU改进 
#include<bits/stdc++.h>
using namespace std; 
int s[320];
int cnt = 0;
int lost = 0;
typedef struct node {
	int order; //页面序号 
	int A;//访问位 
	int M;//修改位 
}cache_;//页面元素 
list<cache_> cache ;
list<cache_>::iterator it ;
list<cache_>::iterator endd;
list<cache_>::iterator l;
//初始化 
void init()
{ 
	cnt = 0;	//访问次数为 0 
	lost = 0;	//缺页次数为 0  
	it = cache.begin() ;
	endd = cache.end();
	endd --;
	for(int i=0;i<320;i++)
		s[i] = 220+i;  //设置指令的物理地址 
}
//寻找当前指令是否在内存块中
bool find (int x)
{
	bool judge = false;
	for(list<cache_>::iterator iter = cache.begin() ; iter != cache.end() ; iter++)
    {
        if((*iter).order == x ){
        	judge = true; 
			(*iter).A = 1;  
		} 
    } 
    return judge;
} 
//当内存空间已满的时候,进行页面置换 
void delete_cache(){ 
	bool judge = false;
	l = it --;
	//第一次访问,寻找A=0,M=0的第一类页面,所遇到的第一个页面即为所选的淘汰页,不改变访问位 
	for(list<cache_>::iterator iter = it ; iter != cache.end() ; iter++)
    {
        if((*iter).A  == 0 && (*iter).M  == 0){
        	it = iter; 
			judge = true;
			break; 
		}  
		if (iter == endd) iter = cache.begin() ;
		if (iter == l) break; 
    } 
	if ( judge == true ) {
		cache.erase( it); 
		int cc = 1;
		for(list<cache_>::iterator iter = cache.begin() ; iter != cache.end() ; iter++)
	    {
	        if( it == iter ) {
	        	if(cc < 3) it = iter++;
	        	else it = cache.begin();
	        	break;
			}
			cc ++;
	    } 
		return;
	}
	//若第一轮失败,寻找A=0,M=1的页面,将所遇到的第一个页面作为淘汰页面,
	//并将所有扫描过的页面访问位置0 
	for(list<cache_>::iterator iter = it ; iter != cache.end() ; iter++)
    {
        if((*iter).A  == 0 && (*iter).M  == 1){
        	it = iter; 
			judge = true;
			break; 
		}  
		(*iter).A  = 0;  
		
		if (iter == endd) iter = cache.begin() ;
		if (iter == l) break; 
    } 
    if ( judge == true ) {
		cache.erase( it); 
		int cc = 1;
		for(list<cache_>::iterator iter = cache.begin() ; iter != cache.end() ; iter++)
	    {
	        if( it == iter ) {
	        	if(cc < 3) it = iter++;
	        	else it = cache.begin();
	        	break;
			}
			cc ++;
	    } 
		return;
	}
	//若第二步也失败,则将指针返回到开始的位置,重复第一步,必要时重复第二步 
	
	//第一次访问,寻找A=0,M=0的第一类页面,所遇到的第一个页面即为所选的淘汰页,不改变访问位 
	for(list<cache_>::iterator iter = it ; iter != cache.end() ; iter++)
    {
        if((*iter).A  == 0 && (*iter).M  == 0){
        	it = iter; 
			judge = true;
			break; 
		}  
		
		if (iter == endd) iter = cache.begin() ;
		if (iter == l) break; 
    } 
	if ( judge == true ) {
		cache.erase( it); 
		int cc = 1;
		for(list<cache_>::iterator iter = cache.begin() ; iter != cache.end() ; iter++)
	    {
	        if( it == iter ) {
	        	if(cc < 3) it = iter++;
	        	else it = cache.begin();
	        	break;
			}
			cc ++;
	    } 
		return;
	}
	//若第一轮失败,寻找A=0,M=1的页面,将所遇到的第一个页面作为淘汰页面,
	//并将所有扫描过的页面访问位置0 
	for(list<cache_>::iterator iter = it ; iter != cache.end() ; iter++)
    {
        if((*iter).A  == 0 && (*iter).M  == 1){
        	it = iter; 
			judge = true;
			break; 
		}  
		(*iter).A  = 0;  
		
		if (iter == endd) iter = cache.begin() ;
		if (iter == l) break; 
    } 
    if ( judge == true ) {
		cache.erase( it); 
		int cc = 1;
		for(list<cache_>::iterator iter = cache.begin() ; iter != cache.end() ; iter++)
	    {
	        if( it == iter ) {
	        	if(cc < 3) it = iter++;
	        	else it = cache.begin();
	        	break;
			}
			cc ++;
	    } 
		return;
	}
}
//执行每一条指令 
int process(int x)
{
	cout<<"第"<< cnt<<" 条指令  " ;  
	cnt++; 
	cache_ y;
	y.order = x/10;
	y.A = 0;
	y.M = 0;
	//判断当前指令是否在内存块中 
	bool judge = find(x/10);
	//如果当前指令在内存块中,显示其物理地址 
	if(judge == true) {
		cout <<"  物理地址:"<<s[x]<<endl;
	}
	//如果当前指令不在内存块中 
	else{ 
		lost ++;
		//如果内存块还有空余,直接将该指令所在页面调入内存块 
		if(cache.size() < 4 ){
			cache.push_back(y);
		}
		//如果内存块没有空余,进行页面置换 
		else {
			delete_cache();
			cache.push_back(y);
		} 
		cout <<"  物理地址:"<<s[x]<<endl;
	}
	return 1;
}
int main()
{
	init();
	int m=rand()%320;//在[0,319]之间随机选取一条起始执行指令,其序号为m 
	process(m);//执行指令,即序号为 m的指令
	process(m+1);//顺序执行下一条指令,即序号为m+1的指令 
	//	重复"跳转到前地址部分、顺序执行、跳转到后地址部分、顺序执行"的过程,159次 
	for(int i=0;i<316;i+=4)
	{ 
		int m1=rand()%m;//通过随机数,跳转到前地址部分[0,m-1]中的某条指令处,其序号为m1
		process(m1);//执行指令,即序号为m1的指令
		process(m1+1);//顺序执行下一条指令,即序号为m1+1的指令
		int m2=rand()%(320-(m1+2)) + m1 + 2;//通过随机数,跳转到后地址部分[m1+2,319]中的某条指令处,其序号为m2
		process(m2);//执行指令,即序号为m1的指令
		process(m2+1);//顺序执行下一条指令,即序号为m2+1的指令
	}
	int m1=rand()%m;//通过随机数,跳转到前地址部分[0,m-1]中的某条指令处,其序号为m1
	process(m1);//执行指令,即序号为m1的指令
	process(m1+1);//顺序执行下一条指令,即序号为m1+1的指令
	cout<<endl<<"缺页率为"<<lost/320.0  <<endl; 
	return 0;
} 

测试结果

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设每个页面中可存放10条指令,分配给作业的内存块数为4。 用C语言语言模拟一个作业的执行过程,该作业共有320条指令, 即它的地址空间为32页,目前它的所有页都还未调入内存。在模拟过程中,如果所访问的指令已在内存,则显示其物理地址,并转下一条指令。如果所访问的指令还未装入内存,则发生缺页,此时需要记录缺页的次数,并将相应页调入内存。如果4个内存块均已装入该作业,则需要进行页面置换,最后显示其物理地址,并转向下一条指令。在所有320条指令执行完毕后,请计算并显示作业运行过程中发生的缺页率。 置换算法:请分别考虑最佳置换算法(OPT)、先进先出(FIFO)算法和最近最久未使用算法(LRU)。 作业中指令的访问次序按下述原则生成: 50%的指令是顺序执行的; 25%的指令是均匀分布在前地址部分; 25%的指令是均匀分布在后地址部分; 具体的实施方法是:    在[0,319]的指令地址之间随机选取一起点m;    顺序执行下一条指令,即执行地址序号为m+1的指令;    通过随机数,跳转到前地址部分[0,m+1]中的某条指令处,其序号为m1;    顺序执行下一条指令,其地址序号为m1+1的指令;    通过随机数,跳转到后地址部分[m1+2,319]中的某条指令处,其序号为m2;    顺序执行下一条指令,其地址序号为m2+1的指令; 重复跳转到前地址部分,顺序执行,跳转到后地址部分,顺序执行的过程直至执行320条指令。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值