一. 實驗目的:
1、通過編寫和調試存儲管理的模擬程序以加深對存儲管理方案的理解。熟悉虛存管理的各種頁面淘汰算法
2、通過編寫和調試地址轉換過程的模擬程序以加強對地址轉換過程的瞭解。
二 . 實驗指導:
設計一個請求頁式存儲管理方案。並編寫模擬程序實現之。流程圖見下圖。
產生一個需要訪問的指令地址流。它是一系列需要訪問的指令的地址。爲不失一般性,你可以適當地(用人工指定地方法或用隨機數產生器)生成這個序列。 頁面淘汰算法分別採用 FIFO頁面淘汰算法和LRU算法,並且在淘汰一頁時,只將該頁在頁表中抹去。而不再判斷它是否被改寫過,也不將它寫回到輔存。
具體的做法可以是:
產生一個需要訪問的指令地址流(也可以依次輸入地址);
指定合適的頁面尺寸(例如以 1K或2K爲1頁);
制定爲進程分配的物理塊數
每訪問一個地址時,首先要計算該地址所在的頁的頁號,然後查各物理塊,判斷該頁是否在主存——如果該頁已在主存,則打印物理快使用情況;如果該頁不在主存且物理快未滿,則調入一頁並打印物理塊使用情況;如果該頁不在主存且物理塊已滿,則淘汰算法淘汰一頁後調入所需的頁,打印物理塊使用情況;
逐個地址訪問,直到所有地址訪問完畢。
LRU算法:
思路:
LRU
利用一個鏈表來實現,
每次新插入數據的時候將新數據插到鏈表的尾部;
每次緩存命中(即數據被訪問),
則將數據移到鏈表尾部;
那麼當鏈表滿的時候,
就將鏈表頭部的數據丟棄。
void LRU()
{
// vector<int> page_number_set;//放置過去的和現在的頁號
vector<table> ta(physics_cnt);
for(int i=0; i<ta.size(); i++) //初始化
{
ta[i].physical_block_number=i;
ta[i].page_number=-1;
}
while(1)
{
cout<<endl;
cout<<"輸入要訪問的邏輯地址(-1退出):";
cin>>logical_address;
if(logical_address==-1)
{
system("cls");
break;
}
else if(logical_address<job_logical_size*1024)
{
address_transformation(logical_address);
// page_number_set.push_back(page_num);
cout<<endl;
cout<<"\t頁號:"<<page_num;
int flag=0;
int index_page;
vector<table>::iterator it=ta.begin();
for(int i=0; i<ta.size(); i++,it++)
{
if(ta[i].page_number==page_num)
{
index_page=i;
flag=1;//命中
break;
}
}
if(flag==0)
{
cout<<" 該頁不在內存中,調入!"<<endl;
int f=0;
for(int i=0; i<ta.size(); i++)
{
if(ta[i].page_number==-1)//直接調入
{
f=1;
ta[i].page_number=page_num;
break;
}
}
if(f==0)//已無空閒物理塊,置換!
{
cout<<endl;
cout<<"\t已無空閒物理塊,置換!"<<endl;
vector<table>::iterator k = ta.begin();
table node1;
node1.page_number=page_num;
node1.physical_block_number=(*k).physical_block_number;
ta.erase(k);
ta.push_back(node1);
}
}
else//命中
{
cout<<" 該頁已在內存中!"<<endl;
table node;
node.page_number=ta[index_page].page_number;
node.physical_block_number=ta[index_page].physical_block_number;
ta.erase(it);
ta.push_back(node);
}
cout<<endl;
cout<<" 物理塊號 頁號"<<endl;
for(int i=0; i<ta.size(); i++)
{
cout<<"\t "<<ta[i].physical_block_number<<" ";
printf("%2d\n",ta[i].page_number);
}
cout<<endl;
cout<<" 塊號是:";
int index;
for(int i=0; i<ta.size(); i++)
{
if(page_num==ta[i].page_number)
{
index=i;
break;
}
}
cout<<ta[index].physical_block_number<<" 物理地址是:"<<physics_address+1024*ta[index].physical_block_number<<endl;
}
else
{
cout<<endl;
cout<<" 錯誤,地址越界!!"<<endl;
cout<<endl;
}
}
}
FIFO算法:
該算法思路特別簡單,在此我不多做贅述,直接看代碼
void FIFO()
{
vector<table> ta(physics_cnt);
for(int i=0; i<ta.size(); i++) //初始化
{
ta[i].physical_block_number=i;
ta[i].page_number=-1;
}
while(1)
{
cout<<endl;
cout<<"輸入要訪問的邏輯地址(-1退出):";
cin>>logical_address;
if(logical_address==-1)
{
system("cls");
break;
}
else if(logical_address<job_logical_size*1024)
{
address_transformation(logical_address);
cout<<endl;
cout<<"\t頁號:"<<page_num;
int flag=0;
for(int i=0; i<ta.size(); i++)
{
if(ta[i].page_number==page_num)
flag=1;
}
if(flag==0)
{
cout<<" 該頁不在內存中,調入!"<<endl;
int f=0;
for(int i=0; i<ta.size(); i++)
{
if(ta[i].page_number==-1)//直接調入
{
f=1;
ta[i].page_number=page_num;
break;
}
}
if(f==0)//已無空閒物理塊,置換!
{
cout<<endl;
cout<<"\t已無空閒物理塊,置換!"<<endl;
vector<table>::iterator k = ta.begin();
table node;
node.physical_block_number=ta[0].physical_block_number;
node.page_number=page_num;
ta.erase(k);
ta.push_back(node);
}
}
else//命中
{
cout<<" 該頁已在內存中!"<<endl;
}
cout<<endl;
cout<<" 物理塊號 頁號"<<endl;
for(int i=0; i<ta.size(); i++)
{
cout<<"\t "<<ta[i].physical_block_number<<" ";
printf("%2d\n",ta[i].page_number);
}
cout<<endl;
cout<<" 塊號是:";
int index;
for(int i=0; i<ta.size(); i++)
{
if(page_num==ta[i].page_number)
{
index=i;
break;
}
}
cout<<ta[index].physical_block_number<<" 物理地址是:"<<physics_address+1024*ta[index].physical_block_number<<endl;
}
else
{
cout<<endl;
cout<<" 錯誤,地址越界!!"<<endl;
cout<<endl;
}
}
}
源代碼:
#include<bits/stdc++.h>
using namespace std;
int page_size=1;//頁面大小
int job_logical_size=20;//作業邏輯地址空間大小
int physics_cnt=3;//物理塊數
int logical_address;//邏輯地址
int page_num;//頁號
int physics_address;//物理地址
struct table
{
int physical_block_number;//物理塊號
int page_number;//頁號
};
void menu()
{
cout<<"\n\n"<<endl;
cout<<"\t 頁面置換算法模擬程序"<<endl;
cout<<endl;
cout<<"\t1. 初始化"<<endl;
cout<<endl;
cout<<"\t2. FIFO算法"<<endl;
cout<<endl;
cout<<"\t3. LRU算法"<<endl;
cout<<endl;
cout<<"\t0. 退出"<<endl;
cout<<endl;
cout<<" 注:已初始化頁面大小爲1kb,作業地址空間大小爲20kb。"<<endl;
cout<<endl;
cout<<" 已爲作業分配物理塊數爲3。頁面分配策略採用固定分配局部置換。"<<endl;
cout<<endl;
cout<<endl;
cout<<"請輸入選擇:";
}
void init()
{
system("cls");
cout<<endl;
cout<<"輸入頁面大小(kb):";
cin>>page_size;
cout<<endl;
cout<<"請輸入作業邏輯地址空間大小(kb):";
cin>>job_logical_size;
cout<<endl;
cout<<"輸入物理塊數:";
cin>>physics_cnt;
system("cls");
}
void address_transformation(int logical_address)
{
int L;
L=page_size*1024;
page_num=logical_address/L;
physics_address=logical_address%L;
}
void FIFO()
{
vector<table> ta(physics_cnt);
for(int i=0; i<ta.size(); i++) //初始化
{
ta[i].physical_block_number=i;
ta[i].page_number=-1;
}
while(1)
{
cout<<endl;
cout<<"輸入要訪問的邏輯地址(-1退出):";
cin>>logical_address;
if(logical_address==-1)
{
system("cls");
break;
}
else if(logical_address<job_logical_size*1024)
{
address_transformation(logical_address);
cout<<endl;
cout<<"\t頁號:"<<page_num;
int flag=0;
for(int i=0; i<ta.size(); i++)
{
if(ta[i].page_number==page_num)
flag=1;
}
if(flag==0)
{
cout<<" 該頁不在內存中,調入!"<<endl;
int f=0;
for(int i=0; i<ta.size(); i++)
{
if(ta[i].page_number==-1)//直接調入
{
f=1;
ta[i].page_number=page_num;
break;
}
}
if(f==0)//已無空閒物理塊,置換!
{
cout<<endl;
cout<<"\t已無空閒物理塊,置換!"<<endl;
vector<table>::iterator k = ta.begin();
table node;
node.physical_block_number=ta[0].physical_block_number;
node.page_number=page_num;
ta.erase(k);
ta.push_back(node);
}
}
else//命中
{
cout<<" 該頁已在內存中!"<<endl;
}
cout<<endl;
cout<<" 物理塊號 頁號"<<endl;
for(int i=0; i<ta.size(); i++)
{
cout<<"\t "<<ta[i].physical_block_number<<" ";
printf("%2d\n",ta[i].page_number);
}
cout<<endl;
cout<<" 塊號是:";
int index;
for(int i=0; i<ta.size(); i++)
{
if(page_num==ta[i].page_number)
{
index=i;
break;
}
}
cout<<ta[index].physical_block_number<<" 物理地址是:"<<physics_address+1024*ta[index].physical_block_number<<endl;
}
else
{
cout<<endl;
cout<<" 錯誤,地址越界!!"<<endl;
cout<<endl;
}
}
}
void LRU()
{
// vector<int> page_number_set;//放置過去的和現在的頁號
vector<table> ta(physics_cnt);
for(int i=0; i<ta.size(); i++) //初始化
{
ta[i].physical_block_number=i;
ta[i].page_number=-1;
}
while(1)
{
cout<<endl;
cout<<"輸入要訪問的邏輯地址(-1退出):";
cin>>logical_address;
if(logical_address==-1)
{
system("cls");
break;
}
else if(logical_address<job_logical_size*1024)
{
address_transformation(logical_address);
// page_number_set.push_back(page_num);
cout<<endl;
cout<<"\t頁號:"<<page_num;
int flag=0;
int index_page;
vector<table>::iterator it=ta.begin();
for(int i=0; i<ta.size(); i++,it++)
{
if(ta[i].page_number==page_num)
{
index_page=i;
flag=1;//命中
break;
}
}
if(flag==0)
{
cout<<" 該頁不在內存中,調入!"<<endl;
int f=0;
for(int i=0; i<ta.size(); i++)
{
if(ta[i].page_number==-1)//直接調入
{
f=1;
ta[i].page_number=page_num;
break;
}
}
if(f==0)//已無空閒物理塊,置換!
{
cout<<endl;
cout<<"\t已無空閒物理塊,置換!"<<endl;
vector<table>::iterator k = ta.begin();
table node1;
node1.page_number=page_num;
node1.physical_block_number=(*k).physical_block_number;
ta.erase(k);
ta.push_back(node1);
}
}
else//命中
{
cout<<" 該頁已在內存中!"<<endl;
table node;
node.page_number=ta[index_page].page_number;
node.physical_block_number=ta[index_page].physical_block_number;
ta.erase(it);
ta.push_back(node);
}
cout<<endl;
cout<<" 物理塊號 頁號"<<endl;
for(int i=0; i<ta.size(); i++)
{
cout<<"\t "<<ta[i].physical_block_number<<" ";
printf("%2d\n",ta[i].page_number);
}
cout<<endl;
cout<<" 塊號是:";
int index;
for(int i=0; i<ta.size(); i++)
{
if(page_num==ta[i].page_number)
{
index=i;
break;
}
}
cout<<ta[index].physical_block_number<<" 物理地址是:"<<physics_address+1024*ta[index].physical_block_number<<endl;
}
else
{
cout<<endl;
cout<<" 錯誤,地址越界!!"<<endl;
cout<<endl;
}
}
}
int main()
{
int flag=1;
while(1)
{
menu();
int sel;
cin>>sel;
switch(sel)
{
case 1:
init();
break;
case 2:
FIFO();
break;
case 3:
LRU();
break;
case 0:
flag=0;
break;
}
if(flag==0)
break;
}
return 0;
}
運行效果:
FIFO:
LRU: