这是最近做完上学期的操作系统的课程设计,想起可以上BLOG写点什么,以防自己学无所获,弄完就忘记。
首先回忆一下,为什么会有分页置换算法?
分页置换算法是基于虚拟内存而言,由于在一般的内存管理算法中,执行指令必须是在物理内存中,满足这一条件就必须将整个进程放入内存中,这就会对进程的大小进行限制,跑不了超出物理内存的程序,当然动态载入能够减轻这一限制,但这是远远不够的,于是引出了新的方案:虚拟内存
所以我们就不用担心进程或者程序的大小,只需要关心要解决的问题。
于是就引出了demand paging,它是虚拟内存系统采用的方法之一,即只有程序执行需要时才载入页,那些没有用到的页不会调入到物理内存。
对于这种方案,需要一定形式的硬件来支持区分哪些页在内存哪些在disk上。
所以有有效位与无效(valid-invalid bit)位来区分。
而当进程试图访问那些未调入到内存的页(invalid bit),会产生页错误陷阱(page-fault trap)
处理这种错误一般会进行如下操作:
1检查进程的内存页表,以确定该引用是合法还是非法的地址访问。
2如果是引用非法,则终止进程,若是合法的引用于是现在应调入。
3找一个空闲的帧(free frame)
4从磁盘中将所需要的页调入到刚刚分配的free frame 中
5修改进程内部表和页表,说明所需要的页已经在内存中
6重新启动刚刚因陷阱而中断的指令
#include<iostream>
#include<fstream>
using namespace std;
//定义页面和页框的总容量
const int PAGESIZE = 20;
const int FRAMESIZE = 10;
int page[PAGESIZE]; //定义 page数组 存放页面
int frame[FRAMESIZE]; //定义 frame数组
int result[PAGESIZE][FRAMESIZE]; //用来存放页框和页面二维数组 保存页面置换结果用来输出
int pageLength = 0; //用户实际使用的页面数目
int frameLength = 0; //用户实际使用的页框数目
int frameFlag[FRAMESIZE]; //用于LRU与OPT算法中,辅助、判断换出的页面
int noPageCount = 0;
int pageReplaceCount = 0;
//****************************************************************************************************
void inputData()
{
cout<<"请输入页框(物理块)数(1<=F<="<<FRAMESIZE<<')'<<endl;
cin>>frameLength;
cout<<"请输入页面数(1<=p<="<<PAGESIZE<<')'<<endl;
cin>>pageLength;
while(frameLength<=0||frameLength>FRAMESIZE||pageLength<=0||pageLength>PAGESIZE){//判断用户输入是否在范围内
cout<<"输入范围错误,请从新输入:"<<endl;
cout<<"请输入页框(物理块)数(1<=F<="<<FRAMESIZE<<')'<<endl;
cin>>frameLength;
cout<<endl<<"请输入页面数(1<=p<="<<PAGESIZE<<')'<<endl;
cin>>pageLength;
}
cout<<"请依次输入要引用的页面"<<endl;
for(int i = 0;i<pageLength;i++){
cin>>page[i];
}
}
//****************************************************************************************************
//初始化page数组
void initPage()
{
for(int i = 0;i<PAGESIZE;i++){
page[i] = -1;
}
}
//****************************************************************************************************
//初始化frame与result数组
void initFrameResult()
{
int i = 0;
for(i = 0;i<FRAMESIZE;i++)
frame[i] = -1;
for(i = 0;i < PAGESIZE;i++){
for(int j = 0; j <FRAMESIZE;j++){
result[i][j] = -1;
}
}
}
//****************************************************************************************************
//判断页框中是否已存在 要调用的页面
bool isexist(int i)
{
for(int j = 0;j < frameLength;j++)
if(frame[j] == i)returntrue;
return false;
}
//****************************************************************************************************
//用于返回页框中存在的 要引用的页面的下标
//输入参数i为要引用的页面
int existFlag(int i)
{
for(int j = 0;j < frameLength;j++)
if(frame[j] == i)
return j;
}
//****************************************************************************************************
//LRU算法中,用于返回最近最久未使用的页面对应的页框的下标
int lastestUnused()
{
int min = frameFlag[0];
int j = 0;
for(int i = 0;i <frameLength;i++){
if(min < frameFlag[i]){
min = frameFlag[i];
j = i;
}
}
return j;
}
//****************************************************************************************************
//在最佳置换算法中,用于判断将来最长时间未使用的页面对应的页框的下标
int optimalPosition()
{
int j = 0;
int max = frameFlag[0];
for(int i = 0;i <frameLength;i++)
if(max < frameFlag[i]){
max = frameFlag[i];
j = i;
}
return j;
}
//****************************************************************************************************
//用于显示 保存在result数组中的结果
void showResult()
{
// char ch = '0';
for(int i =0 ;i <pageLength;i++){
cout<<" "<<page[i]<<" ";
for(int j = 0;j <frameLength;j++){
if(-1 ==result[i][j])
break;
elsecout<<'['<<result[i][j]<<']'<<' ';
}
system("pause");
cout<<endl;
}
}
//****************************************************************************************************
//FIFO
void FIFO()
{
int frameFlag = 0; //页框的标记,用于确定该换出的页框的下标
int pageFlag = 0; //页面标记(下标),指向下一个页面
int resultFlag = 0; //结果标记,表示结果的行,即result数组的行标
noPageCount = 0; //缺页次数
pageReplaceCount = 0; //置换页面次数
int i = 0; //i,j为for循环中的 循环变量
int j = 0;
int position = 0; //指示页框,通过与页框实际总大小来判断有无空白的页框
while (pageFlag < pageLength){
if(isexist(page[pageFlag])) //判断页面是否已经存在
resultFlag++;
else{
if(position < frameLength){ //判断可用的frame
frame[position] = page[pageFlag];
position++;
noPageCount++;
for(i = 0;i <= position;i++) //每置换一次页面后,将页框情况存入result二维数组中
result[resultFlag][i] = frame[i];
resultFlag++;
}
else{
frame[frameFlag] = page[pageFlag]; //frameFlag指示的就是要换出的页面
noPageCount++;
pageReplaceCount++;
for(i = 0;i <frameLength;i++) //每置换一次页面后,将页框情况存入result数组中
result[resultFlag][i] = frame[i];
resultFlag++;
frameFlag++;
frameFlag = frameFlag % frameLength;
}
}
pageFlag++;
}
showResult();
cout<<"*********************************************************"<<endl;
cout<<"缺页次数为:"<<noPageCount<<endl; //计算缺页次数、置换次数、缺页率
cout<<"置换页面次数为:"<<pageReplaceCount<<endl;
cout<<"缺页率为:"<<((double)pageReplaceCount/pageLength)*100<<'%'<<endl;
cout<<"*******************************************************"<<endl;
return;
}
//****************************************************************************************************
//Least-Recently-Used
void LRU()
{
int i = 0;
noPageCount = 0;
pageReplaceCount = 0;
int pageFlag = 0;
int resultFlag = 0;
int position = 0; //用于判断是否有空页框
for(i = 0;i <FRAMESIZE;i++) //初始化 时间记录数组 用来判断最久未用的页面
frameFlag[i] = 0;
while(pageFlag < pageLength){
if(isexist(page[pageFlag])){ //判断页面 是否 已经在页框中
resultFlag++;
frameFlag[existFlag(page[pageFlag])]= 0; //如果在,则将时间记录数组对应位置为0
}
else{
if(position <frameLength){ //如果有空白页框,则将页面放入空白页框中
frame[position] = page[pageFlag];
frameFlag[position] =0;
position++;
noPageCount++;
for(i= 0;i <= position;i++)
result[resultFlag][i]= frame[i];
resultFlag++;
}
else{
frame[lastestUnused()]= page[pageFlag]; //置换出最久未使用的页面
frameFlag[lastestUnused()]= 0;
noPageCount++;
pageReplaceCount++;
for(i = 0;i <frameLength;i++)
result[resultFlag][i]= frame[i];
resultFlag++;
}
}
for(i = 0;i <frameLength;i++)
frameFlag[i]++;
pageFlag++;
}
showResult();
cout<<"**********************************************************"<<endl;
cout<<"缺页次数为:"<<noPageCount<<endl;
cout<<"置换页面次数为:"<<pageReplaceCount<<endl;
cout<<"缺页率为:"<<((double)pageReplaceCount/pageLength)*100<<'%'<<endl;
cout<<"***********************************************************"<<endl;
return;
}
//****************************************************************************************************
//Optimal page-replacement algorithm
void OPT()
{
int i = 0;
int j = 0;
int position = 0;
noPageCount = 0;
pageReplaceCount = 0;
int pageFlag = 0;
int resultFlag = 0;
for(i = 0;i < FRAMESIZE;i++)
frameFlag[i] = 0;
while(pageFlag < pageLength){
if(isexist(page[pageFlag]))
resultFlag++;
else{
if(position <frameLength){
frame[position] =page[pageFlag];
position++;
noPageCount++;
for(i = 0;i <position;i++)
result[resultFlag][i]= frame[i];
resultFlag++;
}
else{
for(i = 0;i <frameLength;i++){
for(j =pageFlag+1;j < pageLength;j++){
if(frame[i]== page[j]){
frameFlag[i]= j;
break;
}
}
if(j ==pageLength)frameFlag[i] = 99999;
}
frame[optimalPosition()]= page[pageFlag];
noPageCount++;
pageReplaceCount++;
for(i = 0;i <frameLength;i++)
result[resultFlag][i]= frame[i];
resultFlag++;
}
}
pageFlag++;
}
showResult();
cout<<"******************************************************"<<endl;
cout<<"缺页次数为:"<<noPageCount<<endl; 计算缺页次数、置换次数、缺页率
cout<<"置换页面次数为:"<<pageReplaceCount<<endl;
cout<<"缺页率为:"<<((double)pageReplaceCount/pageLength)*100<<'%'<<endl;
cout<<"*****************************************************"<<endl;
return;
}
//****************************************************************************************************
//保存result数组中的数据
void saveResult()
{
ofstream outfile; //申请变量名为outfile的文件输出流
outfile.open("result.txt",ios::out); //输出文件,写
if(!outfile){
cout<<"没有保存成功 !"<<endl;
}
for(int i = 0;i <pageLength;i++){
outfile<<" "<<page[i]<<" ";
for(int j = 0;j <frameLength;j++){
if(-1 == result[i][j])
break;
elseoutfile<<'['<<result[i][j]<<']'<<' ';
}
outfile<<endl;
}
outfile<<"**********************************************************"<<endl;
outfile<<"缺页次数为:"<<noPageCount<<endl; 计算缺页次数、置换次数、缺页率
outfile<<"置换页面次数为:"<<pageReplaceCount<<endl;
outfile<<"缺页率为:"<<((double)pageReplaceCount/pageLength)*100<<'%'<<endl;
outfile<<"**********************************************************"<<endl;
outfile.close();
//cout<<"保存成功!";
}
//****************************************************************************************************
//保存页面
void savePage()
{
ofstream outfile;
outfile.open("page.txt",ios::out);
if(!outfile){
cout<<"没有保存成功 !"<<endl;
}
outfile<<frameLength<<''<<pageLength<<' ';
for(int i =0;i<pageLength;i++)
outfile<<page[i]<<'';
outfile.close();
cout<<"***********************(:**保存成功!**:)**********************************"<<endl;
}
//****************************************************************************************************
//打开文件page.txt
void openPage()
{
ifstreaminfile("page.txt",ios::in); //输入文件读
if(!infile){
cout<<"没有打开成功!";
}
infile>>frameLength;
infile>>pageLength;
for(int i = 0;i <pageLength;i++)
infile>>page[i];
infile.close();
cout<<"************打开成功!请继续选择用哪种置换算法来显示:*************"<<endl;
}
//****************************************************************************************************
//主函数main()
int main()
{
initPage();
initFrameResult();
int choice = 'a';
while(choice !=7){
cout<<"页面置换"<<endl
<<" *******************************************************"<<endl
<<" ** 请选择所需要的功能: **"<<endl
<<" ** 1.输入数据 **"<<endl
<<" ** 2.先进先出(FIFO)置换算法 **"<<endl
<<" ** 3.最近最久未使用(LRU)置换算法 **"<<endl
<<" ** 4.最佳(optimal)置换算法 **"<<endl
<<" ** 5.保存这次的数据 **"<<endl
<<" ** 6.打开保存的数据 **"<<endl
<<" ** 7.退出: **"<<endl
<<" *******************************************************"<<endl;
switch(choice)
{
case 1:
inputData();
break;
case 2:
initFrameResult();
FIFO();
break;
case 3:
initFrameResult();
LRU();
break;
case 4:
initFrameResult();
OPT();
break;
case 5:
saveResult();
savePage();
break;
case 6:
openPage();
break;
case 7:break;
}
cout<<"请选择功能:";
cin>>choice;
system("cls");
}
return 0;
}