实验二 请求式分页存储管理算法设计与实现之FIFO
1.实验内容:模拟请求页式存储管理中硬件的地址转换和缺页中断,并用先进先出调度算法(FIFO)处理缺页中断;
2.要求:
① 指令序列的设定可以执行拟定,格式如表3;
② 在完成了FIFO换页策略后,可以选做LRU的换页策略,并进行比较;
③ 作业允许的页架数m在不同情况下的缺页中断率;
④ 程序运行时显示地址转变和页面调入调出过程。
3.步骤:
① 设计页表及其数据结构:
页号
标志:是否在主存;
页架号:设定页表在主存的位置;
修改标志:设定页面在主存中是否修改过;
磁盘上位置:设定页面在辅存中的位置;
例如:装入新页置换旧页时,若旧页在执行中没有被修改过,则不必将该页重写磁盘。因此,页表中增加是否修改过的标志,执行“存”指令和“写”指令时将对应的修改标志置成“1”表示修改过,否则为“0”表示未修改过。
②设计一个地址转换程序半模拟硬件的地址转换和缺页中断。
当访问的页在主存时则形成绝对地址,但不去模拟指令的执行,可以输出转换后的绝对地址来表示一条指令已执行完成。当访问的页不在主存中时,则输出“*页号”来表示硬件产生了一次缺页中断。模拟地址转换流程见图1.1。
③ 设计FIFO页面调度程序;
FIFO页面调度算法总是先调出作业中最先进入主存中的哪一页。因此可以用一个数组来表示(或构成)页号队列。数据中每个元素是该作业已在主存中的页面号,假定分配给作业的页(架)数为m,且该作业开始的m页已装入主存,则数组可由m个元素构成。
P[0],P[1],P[2],…,P[m-1]
它们的初值为P[0]:=0,P[1]:=1,P[2]:=2,…,P[m-1]:=m-1
用一指针K指示当要调入新页时应调出的页在数组中的位置,K的初值为“0”,当产生缺页中断后,操作系统总是选择P[K]所指出的页面调出,然后执行。
④ 设计输入数据和输出格式;
如: 假定主存中页架大小为1024个字节,现有一个共7页的作业,其副本已在磁盘上。系统为该作业分配了4个页架,且该作业的第0页至第3页已装入内存,其作3页未主存,该作业的页表如下:
如果该作业依次执行的指令序列如下表所示:
依次执行上述指令调试你所设计的程序(仅模拟指令的执行,不考虑序列中具体操作的执行)。
⑤ 编程上机,验证结果。
4.实验报告:
为进一步考察程序的执行,可自行确定若干组指令,运行程序,核对执行结果实验报告:
① 实验题目;
② 程序中所用的数据结构及说明;
③ 打印一份源程序并附上必要的说明;
④ 按照指令的执行序列,打印输出结果:绝对地址或调出、调入的页号。
P[K]:=要装入的新页页号
K:=(k+1)mod m
在实验中不必实际地启动磁盘执行调出一页和装入一页的工作,而用输出“OUT调出的页号”和“IN要装入的新页页号”来模拟一次调出和装入过程,模拟程序的流程图见附图1.1。
按流程控制过程如下:
提示:输入指令的页号和页内偏移和是否存指令 ,若d为-1则结束,否则进入流程控制过程,得P1和d,查表在主存时绝对地址P1×1024+d
图1 模拟算法流程
以上为报告要求。
*
本文为博主原创文章,未经博主允许不得转载。
版权为陈博超所有,第一次于2021年11月30日发表于BLOG上
本BLOG上原创文章未经本人许可,不得用于商业用途。转载请经允许后注明出处,否则保留追究法律责任的权利。
*
以下部分为实现代码:
温馨提示:代码所用部分特性为C++11新特性,在例如vs2010这类不支持C++11的老版本上无法使用,请在已经支持C++11新特性的vs版本上使用
头文件FIFO.h中代码:
#include<iostream>
#include<vector>
using namespace std;
class Order { //定义指令类
public:
string operate; //操作
int o_page; //页号
int address; //页内地址
};
class Page { //定义页表类
public:
int p_page; //页号
int flag; //是否位于页表内的标志
int frame; //页架号
int change_flag; //修改标志
int palce; //在磁盘上位置
int address(int x) { //求该页绝对地址的成员函数
return frame * 1024 + x;
}
};
源文件 FIFO.cpp中代码:
#include"FIFO.h"
int main() {
double num = 0;
int real_page, out_page, k = 0; //k为替换指针
int p[4] = { 0, 1, 2, 3 };
vector<Page> page = { //初始化静态生成页表容器数组
{0, 1, 5, 0, 011}, {1, 1, 8, 0, 012}, {2, 1, 9, 0, 013}, {3, 1, 1, 0, 021},
{4, 0, 0, 0, 022}, {5, 0, 0, 0, 023}, {6, 0, 0, 0, 121},
};
vector<Order> order = { //初始化静态生成指令容器数组
{"+", 0, 70}, {"-", 1, 50}, {"×", 2, 15}, {"存", 3, 21},
{"取", 0, 56}, {"-" , 6, 40}, {"移位", 4, 53}, {"+", 5, 23},
{"存", 1, 37}, {"取", 2, 78}, {"+" , 4, 01}, {"存", 6, 84},
};
while (order.size() > 0) {
cout << "操作为 " << order[0].operate << endl << "页号为 " << order[0].o_page << endl;
real_page = order[0].o_page;
if (page[real_page].flag == 1) {
if (order[0].operate == "存") {
page[real_page].change_flag = 1;
}
cout << "绝对地址是: " << page[real_page].address(order[0].address) << endl;
}
else {
cout << "*" << order[0].o_page << endl; //输出所缺的页
num++; //缺页次数加一
out_page = p[k]; //将当前替换指针所指的页取出
if (page[out_page].change_flag == 1) { //判断换出的页是否被修改过
cout << "OUT: " << out_page;
cout << "//该页已被修改过,需调出后重写磁盘,该页在磁盘中的位置为:" << page[out_page].palce << endl;
}
cout << "IN: " << real_page << endl;
p[k] = real_page; //将新入内存的页的页号放入数组中
k = (k + 1) % 4; //移动替换指针
page[real_page].flag = 1; //将新入内存的页标志置为1
page[out_page].flag = 0; //将调出页的页标志置为0
page[real_page].change_flag = 0; //将新入内存的页修改标志置为0
if (order[0].operate == "存")
page[real_page].change_flag = 1;
page[real_page].frame = page[out_page].frame; //将调出页的页架号付给新入的页
}
cout << "----------------------------" << endl;
order.erase(order.begin()); //删除容器中第一个元素
}
cout << "当前数据下的FIFO算法缺页率为: " << num / order.capacity();//缺页次数除以操作总数
return 0;
}
运行截图如下:
码字不易,穷酸学生,各位老板打赏个1分钱支持一下,谢谢大家。
前人栽树,后人乘凉。如果有学弟学妹看到了也希望能点赞支持一下,谢谢