操作系统实验五
页面置换算法
题目
设进程的逻辑地址空间共分为8个页面,进程运行时需引用的页面号引用串为7、0、1、2、0、3、0、4、2、3、0、3、2、1、2、0、1、7、0、1,现系统为该进程在内存中分配了三个物理存储块。请根据理论教材所授内容,采用C语言(也可采用自己熟悉的语言)分别模拟实现OPT、FIFO、LRU、NRU和LFU页面置换算法,对上述页面号引用串进行调度,并计算出各算法下的缺页率。
代码如下:
OPT页面置换算法
#include <iostream>
#include<map>
#include<set>
#include <algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define N 200
using namespace std;
int page[N];//页面引用号
int block[N];//物理块,内存
int dist[N][N];//表示第i次访问内存的时候,内存中的页面j 在以后被访问的最小时间
int n;//页面引用号个数
int m;//物理块数目
int page_max;//最大页面号
int pre[N];//page[i]在page中的索引
int opt(){//最佳页面置换算法
int page_lack = 0;
memset(pre, 0, sizeof(pre));
memset(dist, 0x3f, sizeof(dist));
memset(block, -1, sizeof(block));
for(int i=n; i>=1; --i){
for(int j=0; j<=page_max; ++j)
if(pre[j])
dist[i][j] = pre[j] - i;
pre[page[i]] = i;
}
for(int i=1; i<=n; ++i){//开始访问页面
int j;
int max_dist = 0, p;
for(j=1; j<=m; ++j){
if(block[j] == -1){//该物理块中没有被放入页面,则直接放入, 产生缺页
block[j] = page[i];
cout<<"页面"<<page[i]<<"不在内存,直接放入物理块"<<j<<"中!"<<endl;
page_lack++;
break;
} else if(block[j] == page[i])//页面存在内存中
break;
if(max_dist < dist[i][block[j]]){
max_dist = dist[i][block[j]];//说明block[j] 对应的页面以后会长时间不会用到
p = j;//block[] 第j个页面会被替换掉
}
}
if(j > m){//此时物理块中被装满,且没有找到page[i]对应的分页,接下来进行页面替换
cout<<"页面"<<page[i]<<"不在内存,将物理块"<<p<<"中的页面" <<block[p]<<"替换掉!"<<endl;
block[p] = page[i];
page_lack++;
}
cout<<endl<<"当前内存中页面的情况:"<<endl;
for(int k=1; k<=m; ++k)//内存中页面加载情况
cout<<block[k]<<" ";
cout<<endl<<endl;
}
return page_lack;//返回缺页次数
}
int main(){
int page_lack;
float w;//w为缺页中断率
cout<<"请输入页面引用号个数" ;
cin>>n;
cout<<"请输入物理块个数";
cin>>m;
cout<<"输入页面引用序列";
for(int i=1; i<=n; ++i){
cin>>page[i];
page_max = max(page_max, page[i]) ;
}
page_lack=opt();
w=(float)page_lack/n;
cout<<"OPT缺页中断次数:"<<page_lack<<endl;
cout<<"缺页中断率:"<<w<<endl;
return 0;
}
运行截图:
FIFO页面置换算法
#include <iostream>
#include<map>
#include<set>
#include <algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define N 200
using namespace std;
int page[N];//页面引用号
int block[N];//物理块,内存
int dist[N][N];//表示第i次访问内存的时候,内存中的页面j 在以后被访问的最小时间
int n;//页面引用号个数
int m;//物理块数目
int page_max;//最大页面号
set<int>page_set;
int fifo(){//先进先出页面置换算法
int page_lack = 0;
memset(block, -1, sizeof(block));
int index = 1;
for(int i=1; i<=n; ++i){
if(index > m) index = 1;
set<int>::iterator it;
it = page_set.find(page[i]);
if(it == page_set.end()){
if(block[index] != -1)
page_set.erase(block[index]);
page_set.insert(page[i]);
block[index++] = page[i];
++page_lack;
}
for(int k=1; k<=m; ++k)
cout<<block[k]<<" ";
cout<<endl;
}
return page_lack;
}
int main(){
int v;//w为缺页率 ,v为缺页中断次数
float w;
cout<<"请输入页面引用号个数" ;
cin>>n;
cout<<"请输入物理块个数";
cin>>m;
cout<<"请输入页面号引用次序";
for(int i=1; i<=n; ++i){
cin>>page[i];
page_max = max(page_max, page[i]) ;
}
v=fifo();
w=(float)v/n;
cout<<"FIFO缺页中断次数:"<<v<<endl;
cout<<"FIFO缺页中断率:"<<w<<endl;
return 0;
}
运行截图:
LRU算法
#include <iostream>
#include<map>
#include<set>
#include <algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define N 200
using namespace std;
int page[N];//页面引用号
int block[N];//物理块,内存
int dist[N][N];//表示第i次访问内存的时候,内存中的页面j 在以后被访问的最小时间
int n;//页面引用号个数
int m;//物理块数目
int page_max;//最大页面号
int pre[N];//page[i]在page中的索引
int LRU(){
int page_lack = 0;//page_back为缺页次数
memset(pre, 0, sizeof(pre));
memset(dist, 0x3f, sizeof(dist));
memset(block, -1, sizeof(block));
for(int i=1; i<=n; ++i){
for(int j=0; j<=page_max; ++j)
if(pre[j])
dist[i][j] = i - pre[j];
pre[page[i]] = i;
}
for(int i=1; i<=n; ++i){//开始访问页面
int j;
int max_dist = 0, p;
for(j=1; j<=m; ++j){
if(block[j] == -1){//该块没有放入页面,则直接放入, 产生缺页
block[j] = page[i];
cout<<"页面"<<page[i]<<"不在内存,直接放入物理块"<<j<<"中!"<<endl;
page_lack++;
break;
} else if(block[j] == page[i])//页面存在内存中
break;
if(max_dist < dist[i][block[j]]){
max_dist = dist[i][block[j]];
p = j;//block[] 第j个页面会被替换掉
}
}
if(j > m){
cout<<"页面"<<page[i]<<"不在内存,将物理块"<<p<<"中的页面" <<block[p]<<"替换!"<<endl;
block[p] = page[i];
page_lack++;
}
cout<<endl<<"当前内存中页面的情况:"<<endl;
for(int k=1; k<=m; ++k)//内存中页面加载情况
cout<<block[k]<<" ";
cout<<endl<<endl;
}
return page_lack;
}
int main(){
cout<<"请输入页面引用号个数" ;
cin>>n;
cout<<"请输入物理块个数";
cin>>m;
cout<<"请输入页面引用次序";
for(int i=1; i<=n; ++i){
cin>>page[i];
page_max = max(page_max, page[i]) ;
}
int lack=LRU();
float w;
w=(float)lack/n;
cout<<"LRU缺页中断次数:"<<lack<<endl;
cout<<"缺页中断率"<<w<<endl;
return 0;
}
运行结果截图:
后续两个算法实验并未完成,因此给出老师所给的代码作为参考
NRU算法
void NRU (int ref_len, int vsize){
int i, find, miss, rep, least;
int flag[MEM_FRAME_SIZE]; //访问位
float rate = 0;
printf("-------(4) NRU页面缺页算法-------\n");
miss = 0;
ini_mem (); //初始化内存循环页框
for (i = 0; i < MEM_FRAME_SIZE; i ++) //初始化内存循环页框的访问位
flag[i] = 0;
rep = 0;
for (i = 0; i < ref_len; i ++) {
find = search (MEM_FRAME_SIZE, reference[i]);
if (find != FALSE && mem_frame[find] == -1) { //内存循环页框未满
miss ++;
mem_frame[find] = reference[i];//页面缺页
printf("页框未满,置入页面%d\n",reference[i]);
flag[rep] = 1; // 置访问为1
rep = (rep+1) % MEM_FRAME_SIZE; //页面不在内存中,扫描指针下移
}
else if (find == FALSE) { //内存循环页框已满且拟置入页面不在页框中
miss ++;
while (flag[rep] != 0) { //最近被使用过,给第二次机会
flag[rep] = 0;
rep = (rep+1) % MEM_FRAME_SIZE;
}
printf("换出页面%d,换入页面%d\n",mem_frame[rep],reference[i]);
mem_frame[rep] = reference[i];//页面缺页
flag[rep] = 1; // 置访问为1
rep = (rep+1) % MEM_FRAME_SIZE; //页面不在内存中,扫描指针下移
}
else{//在内存循环页框中找到拟置入页面
printf("内存页框中存在页面%d,无需置入\n",reference[i]);
flag[find] = 1; //页面的内存中,扫描指针不动
}
}
rate = (float)miss/(float)ref_len; //计算页面缺页率
printf("-----NRU页面缺页率为:%d/%d=%.2f-----\n\n",miss,ref_len,rate);
}
LFU算法
void LFU (int ref_len, int vsize){
int i, j, find, miss, rep, least;
int count[MEM_FRAME_SIZE]; //计数器:记录内存页框中页面的使用频率
float rate = 0;
printf("-------(5) LFU页面缺页算法-------\n");
miss = 0;
ini_mem (); //初始化内存页框
for (i = 0; i < MEM_FRAME_SIZE; i ++) //初始化内存页框中页面的使用频率
count[i] = 0;
for (i = 0; i < ref_len; i ++) {
find = search (MEM_FRAME_SIZE, reference[i]);
if (find != FALSE && mem_frame[find] == -1) { //内存页框未满
miss ++;
mem_frame[find] = reference[i];//页面缺页
printf("页框未满,置入页面%d\n",reference[i]);
}
else if (find == FALSE) { //内存页框已满且拟置入页面不在页框中
miss ++;
least = count[0];
rep = 0;
for (j = 1; j < MEM_FRAME_SIZE; j ++) {//选择内存页框中使用频率最小的页面
if (count[j] < least) {
least = count[j];
rep = j;
}
}
printf("换出页面%d,换入页面%d\n",mem_frame[rep],reference[i]);
mem_frame[rep] = reference[i];//页面缺页
count[rep] = 0;
}
else{//在内存页框中找到拟置入页面
printf("内存页框中存在页面%d,无需置入\n",reference[i]);
count[find] ++;
}
if ((i+1) % 4== 0) { //没有移位寄存器,用计数器定期衰减模拟移位,如果把4改成10,缺页率结果又如何?
for (j = 0; j < MEM_FRAME_SIZE; j ++)
count[j] /= 2; //移位
}
}
rate = (float)miss/(float)ref_len; //计算页面缺页率
printf("-----LFU页面缺页率为:%d/%d=%.2f-----\n\n",miss,ref_len,rate);
}
OPT、FIFO、LRU、NRU和LFU页面置换算法优缺点分析
本次实验有一定的难度,尤其是后面两个算法的思想和如何实现,后续有时间还要再研究
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)