一、实验内容
1.模拟分页式存储管理中硬件的地址转换和产生缺页中断
分页式虚拟存储系统是把作业信息的副本存放在磁盘上, 当作业被选中时, 可把作业的开始几页先装入主存且启动执行。 为此, 在为作业建立页表时, 应说明哪些页已在主存, 哪些页尚未装入主存。
作业执行时, 指令中的逻辑地址指出了参加运算的操作存放的页号和单元号, 硬件的地址转换机构按页号查页表, 若该页对应标志为 “1”, 则表示该页已在主存, 这时根据关系式 “绝对地址=块号 X块长十单元号” 计算出欲访问的主存单元地址 。 如果块长为2 的幕次, 则可把块号作为高地址部分, 把单元号作为低地址部分, 两者拼接而成绝对地址。若访问的页对应标志为“0”,则表示该页不在主存,这时硬件发“缺页中断”信号, 由操作系统按该页在磁盘上的位置, 把该页信息从磁盘读出装入主存后再重新执行这条指令。
2.用先进先出(FIFO)页面调度算法处理缺页中断
在分页式虚拟存储系统中,当硬件发出“缺页中断”后,引出操作系统来处理这个中断事件 。 如果主存中已经没有空闲块, 则可用 FIF0页面调度算法把 该作业中最先进入主存的一页调出, 存放到磁盘上, 然后再把当前要访问的页装入该块。 调出和装入后都要修改页表中对应页的标志。
FIF0页面调度算法总是淘汰该作业中最先进入主存的那一页, 因此可以用一个数组来表示该作业已在主存的页面 。 假定作业被选中时, 把开始的 m个页面装入主存, 则数组的元素可定为m个。
二、实验思路
-
地址转换
为更快进行实验,指令的逻辑地址定为10个,已经固定值。
通过一个for循环按顺序读入指令的逻辑地址,然后在页表中查找该逻辑地址的页号是否在内存中,如果在,则使用从页表中查到的页号的块号形成绝对地址的高位,逻辑地址的页内地址形成绝对地址的低位。 -
FIFO页面调度
初始内存为空,当有页面进入时,将3个内存单元的内容前移,起到页面的移除作用,最前面的为最早进入的,空出的第三个进入新的页面,以此循环实现FIFO算法。
三、实验截图
四、实验代码
#include<iostream>
using namespace std;
//存储器管理 块大小16 内存3
/* ----------FIFO-----------
页面引用号:3 4 2 3 5 7 8 1 5 3
3 3 3 3 5 5 5 1 1 1
0 4 4 4 4 7 7 7 5 5
0 0 2 2 2 2 8 8 8 3
是否发生置换:
1 1 1 0 1 1 1 1 1 1
缺页率为:0.9
*/
class page{
public:
int pageNum;//页号
int state;//在内存标志
int address;//磁盘地址
};
page pTable[]={
{0,0,4},{1,0,5},
{2,0,6},{3,0,7},
{4,0,9},{5,0,10},
{6,0,11},{7,0,13},
{8,0,14},{9,0,15}
};//作业信息副本
page ram[3];//内存大小
//指令的逻辑地址分为页号0-9和业内地址0-15
//页号可以在页表找到物理块号0-15
//该物理块号与页内地址拼接成物理地址
//绝对地址=块号0-15×块长15+页内地址0-15
//绝对地址=块号 X块长十单元号
//如果块长为2的幕次,
//则可把块号作为高地址部分, 把单元号作为低地址部分,
//两者拼接而成绝对地址
class Order{
public:
int idpage;//0-9
int idinpage;//0-15
};
Order ord[]={
{3,4},{4,2},{2,8},{3,6},{5,9},{7,4},{8,3},{1,8},{5,4},{3,8}
};//逻辑地址 指令集合
class Ram_address{
public:
int abshigh;
int abslow;
};//绝对地址
void FIFO(int a);
Ram_address fun(int a,int b);
void Address_translation();
Ram_address fun(int a,int b){
Ram_address A;
for(int j=0;j<10;j++){//查表
if(pTable[j].pageNum==a){
if(pTable[j].state==1){//在内存
A.abshigh=pTable[j].address;//高位 块号
A.abslow=b;//底位 页内地址
return A;
}else if(pTable[j].state==0){//不在内存
cout<<"缺"<<a<<"页中断"<<endl;
FIFO(a);
return fun(a,b);
}
}
}
}
void FIFO(int a){
int c;
int del=ram[0].pageNum;
for(int i=0;i<2;i++){
ram[i]=ram[i+1];
}
for(int j=0;j<10;j++){//页表信息更改
if(pTable[j].pageNum==del){
pTable[j].state=0;
}
if(pTable[j].pageNum==a){
pTable[j].state=1;
c=pTable[j].address;
}
}
ram[2].address=c;
ram[2].pageNum=a;
ram[2].state=1;
}
void Address_translation(){
//10个逻辑地址输入
for(int i=0;i<10;i++){//10次作业地址转换
int a=ord[i].idpage;//逻辑地址拆分
int b=ord[i].idinpage;
cout<<"指令的逻辑地址"<<a<<b<<endl;
Ram_address out;
out=fun(a,b);
cout<<"内存的绝对地址";//16进制输出便于观察
if(out.abshigh>=10){
for(int j=0;j<6;j++){
if(out.abshigh-10==j){
cout<<(char)('A'+j);
}
}
}else{cout<<out.abshigh;}
if(out.abslow>=10){
for(int j=0;j<6;j++){
if(out.abslow-10==j){
cout<<(char)('A'+j)<<endl;
}
}
}else{cout<<out.abslow<<endl<<endl;}
}
}
int main(){
Address_translation();
return 0;
}