• 首页

  • 官方

  • 主题

  • 关注

  • 联系

操作系统——模拟页面置换算法(FIFO——先入先出、LRU——最近最少使用、LFU——最近最不常使用),计算置换率(包含程序框图)

操作系统——模拟页面置换算法(FIFO——先入先出、LRU——最近最少使用、LFU——最近最不常使用),计算置换率(包含程序框图)

1.直接跳转到Linux端FIFO页面置换算法代码

2.直接跳转到Linux端LRU页面置换算法代码

3.直接跳转到Linux端LFU页面置换算法代码


千万注意这里的代码需要在Linux环境下运行,才能有如图所示的效果,如果必须在Windows下运行,代码应当适当改动,如:动态数组初始化时采用

block=new int[mnum] (); process=new int[pnum] ();

否则,会出现物理块输出错误、缺页率错误等问题。

导语:

1. FIFO页面置换算法:最简单的页面置换算法。这种算法的基本思想是:当需要淘汰一个页面时,总是选择驻留主存时间最长的页面进行淘汰,即先进入主存的页面先淘汰。(看时间)
2. LRU页面置换算法:最近最少使用,简单来说就是将数据块中,每次使用过的数据放在数据块的最前端,然后将存在的时间最长的,也就是数据块的末端的数据置换掉。(看时间)
3. LFU页面置换算法:近期最少使用算法,选择近期最少访问的页面作为被替换的页面,如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小。(看次数)
4. 置换率与与缺页率不同。置换率用置换次数算,缺页率用缺页中断次数算。

FIFO页面置换算法:

Linux效果图(采用UOS + VScode + g++)


image


程序框图


image


C++代码(FIFO):

#include<iostream>
using namespace std;
static int mnum;
//物理块数
static int pnum;
//页面走向 
static int count=0;
//页面置换次数 
static int *analogblock;
//模拟物理块
static int *block;
//物理块
static int *process;
//随机页面访问序列
int judge(int a[],int n,int x) //判断数组中是否已有x,若有返回其下标值,没有则返回-1 
{
	int i;
	for (i=0;i<n;i++)
	if(x==a[i])
	return i;
	return -1;
}
void replace(int y,int mnum,int x)//用于物理块页面置换,y是用来置换的页面,x是被置换的页面 
{
	int i;
	for (i=0;i<mnum;i++)
	if(x==block[i])
	block[i]=y;
}
int main() {
	int i;
	int maxanalogblock=-1;
	//模仿队列的定义
	int x;
	cout<<"请输入页框大小物理块数:\n";
	cin>>mnum;
	if(mnum>999999) {
		cout<<"输入超出控制大小!"<<endl;
		return 0;
	}
	cout<<"自动生成的内存块需求序列个数:\n";
	cin>>pnum;
	if(pnum>999999) {
		cout<<"输入超出控制大小!"<<endl;
		return 0;
	}
	analogblock=new int[mnum];
	block=new int[mnum];
	process=new int[pnum];
	for (i=0;i<mnum;i++) analogblock[i]=-1;
	for (i=0;i<mnum;i++) block[i]=-1;
	/////////////////////
	//随机产生页面走向序列
	cout<<"产生随机序列如下:\n";
	srand( (unsigned)time( NULL ) );
	//以time函数值(即当前时间)作为种子数,保证两次产生序列的随机性
	for (i=0; i<pnum; i++) {
		process[i] = rand()%10;
		cout<<process[i]<<" ";
	}
	cout<<endl;
	//////////////////////
	cout<<"先进先出(FIFO)页面置换算法,结果: \n\n";
	//////////////////////
	for (x=0;x<pnum;x++) //自动读数 
	{
		//读一个序列号,输出当前数组元素
		cout<<"真实物理块情况:";
		for (i=0;i<mnum;i++) {
			if(block[i]!=-1)
			cout<<block[i]<<" ";
		}
		cout<<"模拟物理块情况:";
		for (i=0;i<mnum;i++) {
			if(analogblock[i]!=-1)
			cout<<analogblock[i]<<" ";
		}
		//////////////////////////
		maxanalogblock++;
		//读数后maxanalogblock自动+1
		if(maxanalogblock<mnum) //若在物理块范围内 
		{
			if(judge(analogblock,mnum,process[x])==-1)//若数组中不存在待插入元素 
			{
				analogblock[maxanalogblock]=process[x];
				//新元素从尾部插入
				block[maxanalogblock]=process[x];
				//新元素从尾部插入
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 缺页中断 调入页面"<<process[x]<<endl;
			} else //若数组中存在待插入元素 
			{
				maxanalogblock--;
				//因为没有插入新元素,回滚maxanalogblock值
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 已存在 直接访问"<<endl;
			}
		} else //超过物理块数的元素 {
			if(judge(analogblock,mnum,process[x])==-1)//若数组中不存在待插入元素 
			{
				//队列法插入(尾部元素出,新元素从头部入)
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 缺页中断 页面"<<process[x]<<"置换出页面"<<analogblock[0]<<endl;
				replace(process[x],mnum,analogblock[0]);
				//置换物理块中页面
				for (i=0;i<mnum-1;i++)
				analogblock[i]=analogblock[i+1];
				analogblock[mnum-1]=process[x];
				//////////////////
				maxanalogblock--;
				//因为没有插入新元素,回滚maxanalogblock值
				count++;
			} else //若数组中存在待插入元素 
			{
				maxanalogblock--;
				//因为没有插入新元素,回滚maxanalogblock值
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 已存在 直接访问"<<endl;
			}
		}
	}
	//读一个序列号,输出当前数组元素
	cout<<"真实物理块情况:";
	for (i=0;i<mnum;i++) {
		if(block[i]!=-1)
		cout<<block[i]<<" ";
	}
	cout<<"模拟物理块情况:";
	for (i=0;i<mnum;i++) {
		if(analogblock[i]!=-1)
		cout<<analogblock[i]<<" ";
	}
	cout<<endl<<"页面换算次数为:"<<count<<endl;
	cout<<"置换率为:"<<(float)count/pnum<<endl;
	return 0;
}
//g++ test71.cpp -o test71 -lpthread&&./test71

LRU页面置换算法:

Linux效果图(采用UOS + VScode + g++)


image


程序框图


image

C++代码(LRU):

#include<iostream>
using namespace std;
static int mnum;
//物理块数
static int pnum;
//页面走向 
static int count=0;
//页面置换次数 
static int *analogblock;
//模拟物理块
static int *block;
//物理块
static int *process;
//随机页面访问序列
int judge(int a[],int n,int x) //判断数组中是否已有x,若有返回其下标值,没有则返回-1 
{
	int i;
	for (i=0;i<n;i++)
	if(x==a[i])
	return i;
	return -1;
}
void replace(int y,int mnum,int x)//用于物理块页面置换,y是用来置换的页面,x是被置换的页面 
{
	int i;
	for (i=0;i<mnum;i++)
	if(x==block[i])
	block[i]=y;
}
void move(int a[],int n,int i) //移动下标为i的元素到尾部 
{
	int j;
	int m=a[i];
	for (j=i;j<n-1;j++)
	a[j]=a[j+1];
	a[n-1]=m;
}
int main() {
	int i;
	int maxanalogblock=-1;
	//模仿栈的定义
	int x;
	cout<<"请输入页框大小物理块数:\n";
	cin>>mnum;
	if(mnum>999999) {
		cout<<"输入超出控制大小!"<<endl;
		return 0;
	}
	cout<<"自动生成的内存块需求序列个数:\n";
	cin>>pnum;
	if(pnum>999999) {
		cout<<"输入超出控制大小!"<<endl;
		return 0;
	}
	analogblock=new int[mnum];
	block=new int[mnum];
	process=new int[pnum];
	for (i=0;i<mnum;i++) analogblock[i]=-1;
	/////////////////////
	//随机产生页面走向序列
	cout<<"产生随机序列如下:\n";
	srand( (unsigned)time( NULL ) );
	//以time函数值(即当前时间)作为种子数,保证两次产生序列的随机性
	for (i=0; i<pnum; i++) {
		process[i] = rand()%10;
		cout<<process[i]<<" ";
	}
	cout<<endl;
	//////////////////////
	cout<<"最近最少使用(LRU)页面置换算法,结果: \n\n";
	//////////////////////
	for (x=0;x<pnum;x++) //自动读数 
	{
		//读一个序列号,输出当前数组元素
		cout<<"真实物理块情况:";
		for (i=0;i<mnum;i++) {
			if(block[i]!=-1)
			cout<<block[i]<<" ";
		}
		cout<<"模拟物理块情况:";
		for (i=0;i<mnum;i++) {
			if(analogblock[i]!=-1)
			cout<<analogblock[i]<<" ";
		}
		//////////////////////////
		maxanalogblock++;
		//读数后maxanalogblock自动+1
		if(maxanalogblock<mnum) //若在物理块范围内 
		{
			if(judge(analogblock,mnum,process[x])==-1)//若数组中不存在待插入元素 
			{
				analogblock[maxanalogblock]=process[x];
				//新元素从尾部插入
				block[maxanalogblock]=process[x];
				//新元素从尾部插入
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 缺页中断 调入页面"<<process[x]<<endl;
			} else //若数组中存在待插入元素
			{
				move(analogblock,maxanalogblock,judge(analogblock,mnum,process[x]));
				//移动下标为i的元素到尾部
				maxanalogblock--;
				//因为没有插入新元素,回滚maxanalogblock值
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 已存在 直接访问"<<endl;
			}
		} else //超过物理块数的元素 
		{
			if(judge(analogblock,mnum,process[x])==-1)//若数组中不存在待插入元素 
			{
				//栈法插入(第一个元素出,后面元素前移,新元素从尾部入)
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 缺页中断 页面"<<process[x]<<"置换出页面"<<analogblock[0]<<endl;
				replace(process[x],mnum,analogblock[0]);
				//物理块中页面置换
				for (i=0;i<mnum-1;i++)
				analogblock[i]=analogblock[i+1];
				analogblock[mnum-1]=process[x];
				//////////////////
				maxanalogblock--;
				//因为没有插入新元素,回滚maxanalogblock值
				count++;
			} else //若数组中存在待插入元素 
			{
				move(analogblock,mnum,judge(analogblock,mnum,process[x]));
				//移动下标为i的元素到尾部
				maxanalogblock--;
				//因为没有插入新元素,回滚maxanalogblock值
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 已存在 直接访问"<<endl;
			}
		}
	}
	//读一个序列号,输出当前数组元素
	cout<<"真实物理块情况:";
	for (i=0;i<mnum;i++) {
		if(block[i]!=-1)
		cout<<block[i]<<" ";
	}
	cout<<"模拟物理块情况:";
	for (i=0;i<mnum;i++) {
		if(analogblock[i]!=-1)
		cout<<analogblock[i]<<" ";
	}
	cout<<endl<<"页面换算次数为:"<<count<<endl;
	cout<<"置换率为:"<<(float)count/pnum<<endl;
	return 0;
}
//g++ test72.cpp -o test72 -lpthread&&./test72

LFU页面置换算法:

Linux效果图(采用UOS + VScode + g++)


image


程序框图


image


C++代码(LFU):

#include<iostream>
using namespace std;
static int mnum;
//物理块数
static int pnum;
//页面走向 
static int count=0;
//页面置换次数 
static int **analogblock;
//模拟物理块
static int *block;
//物理块
static int *process;
//随机页面访问序列
int judge(int *a[],int n,int x) //判断数组中是否已有x,若有返回其下标值,没有则返回-1 
{
	int i;
	for (i=0;i<n;i++)
	if(x==a[i][0])
	return i;
	return -1;
}
void replace(int y,int mnum,int x)//用于物理块页面置换,y是用来置换的页面,x是被置换的页面 
{
	int i;
	for (i=0;i<mnum;i++)
	if(x==block[i])
	block[i]=y;
}
void move(int *a[],int n,int i) //移动下标为i的元素,比较访问次数次多少进行前进 
{
	int j;
	int m=a[i][0];
	int m2=a[i][1];
	for (j=i;j<n-1;j++) {
		if(m2>=a[j+1][1]) {
			a[j][0]=a[j+1][0];
			a[j][1]=a[j+1][1];
			a[j+1][0]=m;
			a[j+1][1]=m2;
		}
	}
}
int main() {
	int i;
	int maxanalogblock=-1;
	//模仿栈的定义
	int x;
	//动态数组初始化
	cout<<"请输入页框大小物理块数:\n";
	cin>>mnum;
	if(mnum>999999) {
		cout<<"输入超出控制大小!"<<endl;
		return 0;
	}
	cout<<"自动生成的内存块需求序列个数:\n";
	cin>>pnum;
	if(pnum>999999) {
		cout<<"输入超出控制大小!"<<endl;
		return 0;
	}
	analogblock=(int**) (new int[mnum]);
	block=new int[mnum];
	process=new int[pnum];
	for (i=0;i<mnum;i++) analogblock[i]=(int*) new int[2];
	//用于保存页面号和访问次数
	for (i = 0; i < mnum; i++) {
		analogblock[i][0]=-1;
		analogblock[i][1]=0;
	}
	/////////////////////
	//随机产生页面走向序列
	cout<<"产生随机序列如下:\n";
	srand( (unsigned)time( NULL ) );
	//以time函数值(即当前时间)作为种子数,保证两次产生序列的随机性
	for (i=0; i<pnum; i++) {
		process[i] = rand()%10;
		cout<<process[i]<<" ";
	}
	cout<<endl;
	//////////////////////
	cout<<"最近最不常使用(LFU)页面置换算法,结果: \n\n";
	//////////////////////
	for (x=0;x<pnum;x++) //自动读数 
	{
		//读一个序列号,输出当前数组元素
		cout<<"真实物理块情况:";
		for (i=0;i<mnum;i++) {
			if(block[i]!=-1)
			cout<<block[i]<<" ";
		}
		cout<<"模拟物理块情况:";
		for (i=0;i<mnum;i++) {
			if(analogblock[i][0]!=-1)
			cout<<analogblock[i][0]<<" ";
			//<<"访问次数"<<analogblock[i][1]<<" "
		}
		//////////////////////////
		maxanalogblock++;
		//读数后maxanalogblock自动+1
		if(maxanalogblock<mnum) //若在物理块范围内 
		{
			if(judge(analogblock,mnum,process[x])==-1)//若数组中不存在待插入元素 
			{
				analogblock[0][0]=process[x];
				//新元素从头部插入
				analogblock[0][1]=1;
				block[maxanalogblock]=process[x];
				//新元素从尾部插入
				move(analogblock,mnum,0);
				//移动下标为i的元素到相同访问次数页面的顶部
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 缺页中断 调入页面"<<process[x]<<endl;
			} else //若数组中存在待插入元素 
			{
				// move(analogblock,maxanalogblock,judge(analogblock,mnum,process[x]));//移动下标为i的元素到尾部
				analogblock[judge(analogblock,mnum,process[x])][1]++;
				move(analogblock,mnum,judge(analogblock,mnum,process[x]));
				//移动下标为i的元素到相同访问次数页面的顶部
				maxanalogblock--;
				//因为没有插入新元素,回滚maxanalogblock值
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 已存在 直接访问"<<endl;
			}
		} else //超过物理块数的元素 
		{
			if(judge(analogblock,mnum,process[x])==-1)//若数组中不存在待插入元素 
			{
				//栈法插入(新元素从头部入,替换掉头部)
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 缺页中断 页面"<<process[x]<<"置换出页面"<<analogblock[0][0]<<endl;
				replace(process[x],mnum,analogblock[0][0]);
				//物理块中页面置换
				analogblock[0][0]=process[x];
				analogblock[0][1]=1;
				move(analogblock,mnum,0);
				//移动下标为i的元素相同访问次数页面的顶部
				//////////////////
				maxanalogblock--;
				//因为没有插入新元素,回滚maxanalogblock值
				count++;
			} else //若数组中存在待插入元素 
			{
				analogblock[judge(analogblock,mnum,process[x])][1]++;
				move(analogblock,mnum,judge(analogblock,mnum,process[x]));
				//移动下标为i的元素到相同访问次数页面的顶部
				maxanalogblock--;
				//因为没有插入新元素,回滚maxanalogblock值
				cout<<" 第"<<x+1<<"次访问,页面"<<process[x]<<" 已存在 直接访问"<<endl;
			}
		}
	}
	//读一个序列号,输出当前数组元素
	cout<<"真实物理块情况:";
	for (i=0;i<mnum;i++) {
		if(block[i]!=-1)
		cout<<block[i]<<" ";
	}
	cout<<"模拟物理块情况:";
	for (i=0;i<mnum;i++) {
		if(analogblock[i][0]!=-1)
		cout<<analogblock[i][0]<<" ";
	}
	cout<<endl<<"页面换算次数为:"<<count<<endl;
	cout<<"置换率为:"<<(float)count/pnum<<endl;
	return 0;
}
//g++ test73.cpp -o test73 -lpthread&&./test73
posted @ 2021-07-15 15:01  戈小戈  阅读(2630)  评论(1编辑  收藏  举报