实验指南
运行环境:
Dev c++
算法思想
本实验是模拟虚拟存储管理方式中的请求分页式技术中的页面置换算法,对于当前访问的页面号如果有对应的内存物理块号则直接访问(必要时可调整物理块中的页面序号),否则先输出缺页访问标志+,然后再判断物理块是否已存满,未满则直接换入当前页,若已满,则先将内存物理块中块首页面号淘汰且换出,然后再将当前页换入。
FIFO是选择在内存驻留时间最长的页面进行置换。
LFU是选择最长时间没有被引用的页面进行置换。
核心数据结构
const int N = 1e3 + 10;
void out()
{
puts("***********请求分页式存储管理***********");
puts("\t*\t1.FIFO分配\t*\t");
puts("\t*\t2.LRU(LFU)分配\t*\t");
puts("\t*\t0.退出\t*\t");
printf("\t\t请输入选项:");
}
struct Y
{
int cnt, val;
friend bool operator<(Y a, Y b) //cnt为优先级 val为页面 cnt越大,优先级越高,越优先出队
{
return a.cnt < b.cnt;
}
};
priority_queue< Y, vector<Y> > q;
string s; //作业名
int n, m, ss[N], vis[N], ans[N][N], u[N];
//n为物理块的块数
//m为作业长度
//vis数组用于记录本次是否产生缺页面
//二维数组ans用于记录调度过程中的页面置换情况
//ss[N] 记录需要调度的页面顺序
vector<int> v; //用于存放物理块序列
程序框架
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
struct Y
{
int cnt, val;
friend bool operator<(Y a, Y b) //cnt为优先级 val为页面 cnt越大,优先级越高,越优先出队
{
return a.cnt < b.cnt;
}
};
priority_queue< Y, vector<Y> > q;
string s; //作业名
int n, m, ss[N], vis[N], ans[N][N], u[N];
//n为物理块的块数
//m为作业长度
//vis数组用于记录本次是否产生缺页面
//二维数组ans用于记录调度过程中的页面置换情况
//ss[N] 记录需要调度的页面顺序
vector<int> v; //用于存放物理块序列
//函数名:out 参数:无
void out()
{
//函数功能:输出选择界面菜单,1为FIFO,2为LFU,0退出
}
//函数名:input 参数:无
void input()
{
//函数功能:输入作业信息
}
//函数名:print 参数:无
void print()
{
//函数功能:输出页面置换详情和缺页中断率
}
//函数名:solve1 参数:无
void solve1()
{
//函数功能:进行FIFO调度
}
//函数名:solve2 参数:无
void solve2()
{
//函数功能:进行LRU调度
}
int main()
{
// #ifndef ONLINE_JUDGE
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// #endif
printf("请输入物理块的块数:");
cin >> n;
out();
int f;
cin>>f;
while (f!=0)
{
if (!f)
break;
input();
memset(ans, -1, sizeof ans);
memset(vis, 0, sizeof vis);
memset(u, -1, sizeof u);
if (f == 1)
{
solve1();
print();
}
else
{
solve2();
print();
}
out();
cin>>f;
}
return 0;
}
测试用例:
3
1
jobA
20
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
2
jobB
20
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
0
4
1
JobC
20
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
2
jobD
20
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
0
关键代码
#include<stdio.h>
const int N = 1e3 + 10;
char s[20]; //作业名
int n, m, u[N], vis[N], ans[N][N], ss[N];
//n为物理块的块数
//m为作业长度
//u数组记录被调出的页面
//vis数组用于记录本次是否产生缺页面(1表示缺页,0表示不缺页)
//二维数组ans用于记录调度过程中的页面置换情况
//ss[N] 记录需要调度的页面顺序
//函数名:out 参数:无
void out()
{
//函数功能:输出选择界面菜单,1为FIFO,2为LFU,0退出
printf("***********请求分页式存储管理***********\n");
printf("\t*\t1.FIFO分配\t*\t\n");
printf("\t*\t2.LRU(LFU)分配\t*\t\n");
printf("\t*\t0.退出\t*\t\n");
printf("\t\t请输入选项:\n");
}
//函数名:input 参数:无
void input()
{
//函数功能:输入作业信息
printf("请输入作业名:");
scanf("%s",&s);
printf("请输入作业页面长度:");
scanf("%d",&m);
printf("请输入作业页面顺序:\n");
for(int i = 0;i<m;i++)
scanf("%d",&ss[i]);
}
//函数名:print 参数:无
void print()
{
//函数功能:输出页面置换详情和缺页中断率
int count = 0;
printf("作业名:%s\n作业调度过程:\n",s);
printf("\t");
for(int i=0;i<m;i++)
{
printf("%2d ",i);
}
printf("\n\t");
for(int i=0;i<m;i++)
{
printf("%2d ",ss[i]);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(j==0)
{
printf("\n%d\t ",i);
}
if(ans[i][j]!=-1)
{
printf("%d ",ans[i][j]);
}
else
{
printf(" ");
}
}
}
printf("\n\t ");
for(int i=0;i<m;i++)
{
if(vis[i] == 1)
{
printf("+ ");
count++;//
}
else
{
printf(" ");
}
}
printf("\n\t ");
for(int i=0;i<m;i++)
{
if(u[i] != -1)
{
printf("%d ",u[i]);
}
else
{
printf(" ");
}
}
printf("\n缺页中断率为:%.2f\n",count*1.0/m*100);
}
//函数名:solve1 参数:无
void solve1()
{
//函数功能:进行FIFO调度
printf("**********打印作业FIFO调度进入主存页的过程**********\n");
for(int i=0;i<m;i++)
{
int flag = 0;//表示前一列是否有相同页面
for(int k = 0;k<n;k++)
{
if(i>=1&&ans[k][i-1] !=-1&&ans[k][i-1] == ss[i])
{
flag = 1;
break;
}
}
if(flag == 1)//内存里调入了当前要调入的页面
{
for(int j = 0;j<n;j++)
{
ans[j][i] = ans[j][i-1];
}
}
else//内存里没有调入了当前要调入的页面
{
int j = 0;
if(i>=1&&ans[n-1][i-1]!=-1)
{
u[i] = ans[n-1][i-1];
}
for(j = n-1;j>0&&i>=1;j--)
{
ans[j][i] = ans[j-1][i-1];
}
ans[0][i] = ss[i];
vis[i] = 1;
}
}
}
//函数名:solve2 参数:无
void solve2()
{
//函数功能:进行LRU调度
printf("**********打印作业LUR调度进入主存页的过程**********\n");
for(int i = 0;i<m;i++)
{
int flag = 0,k,j;//表示这一列是否有相同页面
for(k = 0;k<n;k++)
{
if(ans[k][i-1] !=-1&&ans[k][i-1] == ss[i])
{
flag = 1;
break;
}
}
if(flag == 1)//内存里调入了当前要调入的页面
{
j = n-1;
while(j!=k)
{
ans[j][i] = ans[j][i-1];
j--;
}
for(;j>=0;j--)
{
ans[j][i] = ans[j-1][i-1];
}
ans[0][i] = ss[i];
}
else//内存里没有调入了当前要调入的页面
{
int j = 0;
if(i>=1&&ans[n-1][i-1]!=-1)
{
u[i] = ans[n-1][i-1];
}
for(j = n-1;j>0&&i>=1;j--)
{
ans[j][i] = ans[j-1][i-1];
}
ans[0][i] = ss[i];
vis[i] = 1;
}
}
}
int main()
{
printf("请输入物理块的块数:");
scanf("%d",&n);
out();
int f;
scanf("%d",&f);
while (f!=0)
{
if (!f)
break;
input();
for(int i = 0;i<N;i++)
{
for(int j = 0;j<N;j++)
{
ans[i][j] = -1;
}
vis[i] = 0;
u[i] = -1;
}
if (f == 1)
{
solve1();
print();
}
else
{
solve2();
print();
}
out();
scanf("%d",&f);
}
return 0;
}
运行结果
实验总结
①学会了consta和define的区别;
②没有考虑到如果没有对页面置换情况数组怎么输出的问题,导致一直在算法查错;
③更加深入了解了二维数组按列存储的思想;
④保证程序的简洁性就要找到程序处理时用的方法哪里是相同的可以将其合并;
⑤还是对选择结构的条件没有把握得特别好,得多加练习。