最佳页面置换(OPT)算法: 这是一种理想情况下的页面置换算法,但实际上不可能实现。基本思想是应该淘汰最近的未 来最久不再使用的页。
先进先出(FIFO)算法 当需要选择一个页面淘汰时,总是选择最先进入内存空间的那一个页面。只要在系统中建立 一个 FIFO 队列,以反映页面的活动情况。被选择的页面总是处于队首的页面,而最近调入的页 面永远存放在队列的尾部。
最近最久未使用(LRU)算法 该算法的基本思想是用最近的过去估计最近的将来。假定在内存中某个页面,在最近一段时 间内未被使用的时间最长,那么在最近的将来也可能不再被使用。
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int n;
int L;
void OPT(int arr[], int n, int L, int miss[]){
int miss_count=0;//缺页次数
int change_count=0;//置换次数
int arr_i[n][L];//记录内存块中页号情况
memset(arr_i,-1,sizeof(arr_i));
//实现OPT算法
for(int i=0;i<L;i++){
int page=arr[i]; // 获取当前要访问的页面号
int null_index=-1;//获取空内存块号
bool found=false;// 标记物理块中是否已经存在该页面
bool judge=false;//判断内存块是否已满
if(i>0){ //更新 i 列 物理块
for(int j=0;j<n;j++){
arr_i[j][i]=arr_i[j][i-1];
}
}
for(int j=0;j<n;j++){
if(arr_i[j][i]==page){
found=true;// 如果已经存在,则标记为true
miss[i]=0;//缺页标记为 0
break;
}
}
// 如果页面不存在于物理块中,进行页面置换
//判断内存块是否已满
for(int j=0;j<n;j++){
if(arr_i[j][i] == -1){
judge=true;// 如果内存块未满,则标记为true
null_index=j;//记录空块号
break;
}
}
if(!found&&judge){//缺页且内存块未满
arr_i[null_index][i]=page;
miss[i]=1; //缺页标记 1
cout<<"内存块未满,加入页号:"<<page<<endl;
miss_count++;
}
if(!found&&!judge){//缺页且内存块满
int maxdist = -1; // 最长时间不被访问的页面距离
int maxindex = -1;// 最长时间不被访问的页面位置
// 遍历物理块数组,找出最长时间不被访问的页面
for (int j = 0; j < n; j++) {
int dist = 0; // 记录当前页面距离下一次访问的距离
for (int k = i + 1; k < L; k++) {//从page下一页开始遍历
if (arr_i[j][i] == arr[k]) {//寻找内存块 j 出现的距离
dist = k - i;
break;
}
else if(k==L-1){
dist=L-1;
}
}
//如果当前页面距离下一次访问的距离大于已经找到的最长距离,则更新
if(dist > maxdist){
maxdist=dist;
maxindex=j;
}
}
//打印置换详情
change_count++;
cout<<endl<<"发生页面置换,序号:"<<change_count<<endl;
cout<<"换出:"<<arr_i[maxindex][i]<<endl<<"换入:"<<page<<endl<<"换出内存块号:"<<maxindex+1<<endl;
// 将找到的最长时间不被访问的页面替换为当前页面
arr_i[maxindex][i]=page;
// 标记缺页
miss[i]=1;
miss_count++;
}
}
cout << "---------------------------------------------------------------------------------------------------------------------------------" << endl;
cout << "\t\t\t最佳页面置换算法OPT" << endl << endl;
cout<<"页面号\t";//输出页面号详情
for(int i=0;i<L;i++){
cout<<std::setw(6)<<std::right<<arr[i];
}
cout<<endl;
for(int i=0;i<n;i++){//输出块号详情
cout<<"块"<<i+1<<"\t";
for(int j=0;j<L;j++){
cout<<std::setw(6)<<std::right<<arr_i[i][j];
}
cout<<endl;
}
cout<<"缺页\t";//输出缺页详情
for(int i=0;i<L;i++){
cout<<std::setw(6)<<std::right<<miss[i];
}
cout<<endl<<"缺页次数:"<<miss_count<<endl;
cout<<"置换次数:"<<change_count<<endl;
cout<<"缺页率:"<<(float)(miss_count)/L*100<<"%"<<endl;
cout << "---------------------------------------------------------------------------------------------------------------------------------" << endl;
}
void FIFO(int arr[],int n,int L,int miss[]){
memset(miss,0,sizeof(miss));//重置miss数组
int miss_count=0;//缺页次数
int change_count=0;//置换次数
int arr_i[n][L];//记录内存块中页号情况
int index=0;//记录换出内存块号
memset(arr_i,-1,sizeof(arr_i));//初始化内存块表
for(int i=0;i<L;i++){
int page=arr[i]; // 获取当前要访问的页面号
int null_index=-1;//获取空内存块号
bool found=false;// 标记物理块中是否已经存在该页面
bool judge=false;//判断内存块是否已满
if(i>0){ //更新 i 列 物理块
for(int j=0;j<n;j++){
arr_i[j][i]=arr_i[j][i-1];
}
}
for(int j=0;j<n;j++){
if(arr_i[j][i]==page){
found=true;// 如果已经存在,则标记为true
miss[i]=0;//缺页标记为 0
break;
}
}
// 如果页面不存在于物理块中,进行页面置换
//判断内存块是否已满
for(int j=0;j<n;j++){
if(arr_i[j][i] == -1){
judge=true;// 如果内存块未满,则标记为true
null_index=j;//记录空块号
break;
}
}
if(!found&&judge){//缺页且内存块未满
arr_i[null_index][i]=page;
miss[i]=1; //缺页标记 1
cout<<"内存块未满,加入页号:"<<page<<endl;
miss_count++;
}
if(!found&&!judge){//缺页且内存块满
//打印置换详情
if(index > n-1){
index=0;
}
change_count++;
cout<<endl<<"发生页面置换,序号:"<<change_count<<endl;
cout<<"换出:"<<arr_i[index][i]<<endl<<"换入:"<<page<<endl<<"换出内存块:"<<index+1<<endl;
// 将内存块 index 页面替换为当前页面
arr_i[index][i]=page;
// 标记缺页
index++;//更新置换块号
miss[i]=1;
miss_count++;
}
}
cout << "---------------------------------------------------------------------------------------------------------------------------------" << endl;
cout << "\t\t\t先入先出算法FIFO" << endl << endl;
cout<<"页面号\t";//输出页面号详情
for(int i=0;i<L;i++){
cout<<std::setw(6)<<std::right<<arr[i];
}
cout<<endl;
for(int i=0;i<n;i++){//输出块号详情
cout<<"块"<<i+1<<"\t";
for(int j=0;j<L;j++){
cout<<std::setw(6)<<std::right<<arr_i[i][j];
}
cout<<endl;
}
cout<<"缺页\t";//输出缺页详情
for(int i=0;i<L;i++){
cout<<std::setw(6)<<std::right<<miss[i];
}
cout<<endl<<"缺页次数:"<<miss_count<<endl;
cout<<"置换次数:"<<change_count<<endl;
cout<<"缺页率:"<<(float)(miss_count)/L*100<<"%"<<endl;
cout << "---------------------------------------------------------------------------------------------------------------------------------" << endl;
}
void LRU(int arr[],int n,int L,int miss[]){
memset(miss,0,sizeof(miss));//重置miss数组
int miss_count=0;//缺页次数
int change_count=0;//置换次数
int arr_i[n][L];//记录内存块中页号情况
int time[n]={0};
memset(arr_i,-1,sizeof(arr_i));//初始化内存块表
for(int i=0;i<L;i++){
int page=arr[i]; // 获取当前要访问的页面号
int null_index=-1;//获取空内存块号
bool found=false;// 标记物理块中是否已经存在该页面
bool judge=false;//判断内存块是否已满
if(i>0){ //更新 i 列 物理块
for(int j=0;j<n;j++){
arr_i[j][i]=arr_i[j][i-1];
}
}
for(int j=0;j<n;j++){
int index;//判断是否跳出 循环
if(arr_i[j][i]==page){
found=true;// 如果已经存在,则标记为true
index=j;
miss[i]=0;//缺页标记为 0
}
if(found){
for(int j=0;j<n;j++){
time[j]++;
}
time[index]=0;
break;
}
}
// 如果页面不存在于物理块中,进行页面置换
//判断内存块是否已满
for(int j=0;j<n;j++){
if(arr_i[j][i] == -1){
judge=true;// 如果内存块未满,则标记为true
null_index=j;//记录空块号
break;
}
}
if(!found&&judge){//缺页且内存块未满
arr_i[null_index][i]=page;
miss[i]=1; //缺页标记 1
cout<<"内存块未满,加入页号:"<<page<<endl;
miss_count++;
for(int k=0;k<=null_index;k++){
if(k==null_index){
time[k]=0;
}
else{
time[k]++;
}
}
}
if(!found&&!judge){//缺页且内存块满
int maxtime=-1;
int maxindex=-1;
for(int j=0;j<n;j++){ //寻找最久未使用页号 所在块
if(time[j]>maxtime){
maxtime=time[j];
maxindex=j;
}
}
//arr_i[maxindex][i]=page;//置换
for(int j=0;j<n;j++){ //更新 time表
time[j]++;
}
time[maxindex]=0;
//打印置换详情
change_count++;
cout<<endl;
for(int j=0;j<n;j++){
cout<<time[j]<<" ";
}
cout<<endl;
cout<<endl<<"发生页面置换,序号:"<<change_count<<endl;
cout<<"换出:"<<arr_i[maxindex][i]<<endl<<"换入:"<<page<<endl<<"换出内存块:"<<maxindex+1<<endl;
// 将内存块 index 页面替换为当前页面
arr_i[maxindex][i]=page;
// 标记缺页
miss[i]=1;
miss_count++;
}
}
cout << "---------------------------------------------------------------------------------------------------------------------------------" << endl;
cout << "\t\t\t最久未使用算法LRU" << endl << endl;
cout<<"页面号\t";//输出页面号详情
for(int i=0;i<L;i++){
cout<<std::setw(6)<<std::right<<arr[i];
}
cout<<endl;
for(int i=0;i<n;i++){//输出块号详情
cout<<"块"<<i+1<<"\t";
for(int j=0;j<L;j++){
cout<<std::setw(6)<<std::right<<arr_i[i][j];
}
cout<<endl;
}
cout<<"缺页\t";//输出缺页详情
for(int i=0;i<L;i++){
cout<<std::setw(6)<<std::right<<miss[i];
}
cout<<endl<<"缺页次数:"<<miss_count<<endl;
cout<<"置换次数:"<<change_count<<endl;
cout<<"缺页率:"<<(float)(miss_count)/L*100<<"%"<<endl;
cout << "---------------------------------------------------------------------------------------------------------------------------------" << endl;
}
int main(){
cout << "请输入物理块的数量:";
cin>>n;
cout << "请输入要访问的页面数量:";
cin>>L;
cout<<endl;
//int arr1[L]={7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3,2,1,2,0,1,7,0,1};//页面号序列
//int arr2[L]={3,2,1,0,3,2,4,3,2,1,0,4};
//int arr3[L]={1,8,1,7,8,2,7,2,1,8,3,8,2,1,3,1,7,1,3,7};
int miss[L]={0};//缺页数组,记录缺页情况
int arr[L];
srand(time(0));
for(int i=0;i<L;i++){
arr[i]=rand()%9+1;
}
OPT(arr,n,L,miss);
FIFO(arr,n,L,miss);
LRU(arr,n,L,miss);
cout<<endl<<endl;
return 0;
}
注:一起交流一起学习,发托市玩玩,🤡🤡