作業系統頁面置換演算法 ---之---FIFO置換演算法、OPTIMAL置換算
作業系統頁面置換演算法
---之---
FIFO置換演算法、OPTIMAL置換演算法、LRU置換演算法
頁面置換演算法在記憶體中沒有空閒頁面時被呼叫,其目的是選出一個被淘汰的頁面,把記憶體和外存統一管理的目的是把那些訪問概率高的頁面放在記憶體,因此,頁面置換演算法因該置換那些訪問概率低的頁面,並把它們移除記憶體。
當程序產生缺頁中斷時,若記憶體已經沒有空閒區域時,為了保證程序能夠正常執行,系統必須依據一定的演算法從記憶體中選擇某頁程式(基於請求分頁儲存管理方式)或資料送到磁碟的交換區,所採用的演算法即是頁面置換演算法。
這裡簡單講到三中簡單的頁面置換演算法:FIFO置換演算法、OPTIMAL置換演算法、LRU置換演算法
OPTIMAL置換演算法(最佳置換演算法)
最佳置換演算法是一種理想化的置換演算法,其置換的頁面將是以後永久不使用的,或是將來很長時間內不再使用的頁面(程式碼中置換的是引用串中較長時間不適用的頁面)。它可以保證最低的缺頁率。
FIFO置換演算法(先進先出置換演算法)
這種演算法的出發點是先裝入記憶體的頁面先被置換。其總是先淘汰那些駐留時間最長的頁面。
LRU置換演算法(最近最久未使用置換演算法)
該演算法根據頁面調入記憶體後的使用情況進行決策。由於無法預測各頁面將來的使用情況,只能利用“最近的過去”作為“最近的將來”的近似。該演算法賦予每個頁面一個訪問欄位,用來記錄一個頁面自上次被訪問以來所經歷的時間T,當須淘汰一個頁面時,選擇現有頁面中其T值最大的,即最近最久未使用的頁面予以淘汰。
#include <iostream>
#define M 3 //物理塊數
#define N 20 //頁面引用串長度
using namespace std;
struct block
{
int iPageNum; //物理塊裡儲存的頁面號
int iBlockFlag; //在三種演算法中用到的標記。例如在FIFO中為在記憶體中的時間
};
//演算法模擬移位暫存器原理
void FIFO(int iTempPage[N],int flag[N],block myBlock[M]);//先進先出置換演算法
void Optimal(int iTempPage[N],int flag[N],block myBlock[M]);//最佳置換演算法
void LRU(int iTempPage[N],int flag[N],block myBlock[M]);//最近最久未使用置換演算法
int PageNum(int array[]);
int main()
{
block myBlock[M];
int iPageString[N]={7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1};
//頁面引用串
int iTempPage[N]; //臨時頁面引用串
int flag[N]; //缺頁標記;1為缺頁,0為不缺頁,在統計缺頁次數時用
int i;
bool bExitFlag=true; //退出標記
char ch; //接收選擇演算法時傳進來的值
while(bExitFlag)
{
cout<<"\n"<<"請選擇頁面置換演算法:\n";
cout<<"f:FIFO置換演算法\to:OPT置換演算法\tl:LRU置換演算法\tx:退出置換演算法程式.\n";
cin>>ch;
//初始化資料
if((ch=='f')||(ch=='o')||(ch=='l'))
{
for(i=0;i<N;i++)
{
iTempPage[i]=iPageString[i]; //初始化臨時頁面引用串
flag[i]=0; //初始化缺頁標記為0,即不缺頁
}
}
switch(ch)
{
case 'f':
cout<<"FIFO置換演算法的結果是:\n";
FIFO(iTempPage,flag,myBlock);
//用PageNum(flag)統計缺頁次數
cout<<"\n缺頁次數為"<<PageNum(flag)<<endl;
break;
case 'o':
cout<<"OPT置換演算法的結果是:\n";
Optimal(iTempPage,flag,myBlock);
cout<<"\n缺頁次數為"<<PageNum(flag)<<endl;
break;
case 'l':
cout<<"LRU置換演算法的結果是:\n";
LRU(iTempPage,flag,myBlock);
cout<<"\n缺頁次數為"<<PageNum(flag)<<endl;
break;
case 'x':
cout<<"退出置換演算法。\n";
bExitFlag=false;
break;
default:
cout<<"輸入有誤,請重新選擇置換演算法:\n";
}
}
return 0;
}
//對陣列中的數累加
int PageNum(int array[])
{
int num=0;
for(int j=0;j<N;j++)
num=num+array[j];
return num;
}
//定位函式,在最佳演算法中用於定位;
//定位物理塊中的某一個頁面在引用串中還未訪問串中頁面的位置
int allocate(int iPage,int iLoc,int iTempPage[N])
{
int i;
for(i=iLoc;i<N;i++)
{
if (iPage==iTempPage[i])
return i;
}
//永遠不再訪問的頁面位置假定為N
return N;
}
//找陣列中最大值所在的下標,返回最大值在陣列中的位置(下標)
int max(block array[M])
{
int j,loc;
int temp=array[0].iBlockFlag;
loc=0;
for(j=1;j<M;j++)
{
if (temp<array[j].iBlockFlag)
{
temp=array[j].iBlockFlag;
loc=j;
}
}
return loc;
}
//輸出剩餘的資料
//loc為頁面引用串中
void output(int iPage,int flag,block myBlock[M],int blockNum)
{
int j;
//如果缺頁則輸出缺頁標誌,否則不輸出
if (flag==1)
cout<<"\n "<<flag;
else
cout<<"\n ";
cout<<"\t "<<iPage;
for(j=0;j<blockNum;j++)
cout<<"\t "<<myBlock[j].iPageNum;
}
//初始化物理塊的內容,因任一種演算法在物理塊內容為空時,結果都一樣的
//同時將目前物理塊中的內容輸出
void InitialBlock(int iTempPage[N],int flag[N],block myBlock[M])
{
int i;
for(i=0;i<M;i++)
{
//初始化物理塊的內容,因任一種演算法在物理塊內容為空時,結果都一樣的
myBlock[i].iPageNum=iTempPage[i];
//myBlock[i].iBlockFlag的值:0為最後進來的,數越大表示進來的越早
//在最佳置換演算法中則初始化此值沒有意義
myBlock[i].iBlockFlag=(M-1)-i;
flag[i]=1; //此時為缺頁
}
//輸出
cout<<"\n缺頁\t引用串\t物理塊1\t物理塊2\t物理塊3";
for(i=0;i<M;i++)
output(iTempPage[i],flag[i],myBlock,i+1);
}
//FIFO置換演算法
void FIFO(int iTempPage[N],int flag[N],block myBlock[M])
{
int i,j,k,loc;
bool ExistFlag=false;//退出標記
//初始化物理塊的內容,因任一種演算法在物理塊內容為空時,結果都一樣的
//同時將目前物理塊中的內容輸出
InitialBlock(iTempPage,flag,myBlock);
//從引用串中的第4個頁面開始
for(i=3;i<N;i++)
{
ExistFlag=false;
for(j=0;j<M;j++)
{
//物理塊中存在
if (myBlock[j].iPageNum==iTempPage[i])
{
//模擬移位暫存器
for(k=0;k<M;k++)
myBlock[k].iBlockFlag++;//物理塊中存在
ExistFlag=true;
flag[i]=0;
break;
}
}
//物理塊中不存在
if (!ExistFlag)
{
//查詢最先進來的頁面,也就是block中iBlockFlag最大的物理塊
loc=max(myBlock);
myBlock[loc].iPageNum=iTempPage[i];
//置缺頁標誌
flag[i]=1;
// 將物理塊中與引用串匹配的物理塊的標記位置0,其餘加1(模擬移位暫存器)
for(k=0;k<M;k++)
if (k!=loc)
myBlock[k].iBlockFlag++;
else
myBlock[k].iBlockFlag=0;
}
//輸出
output(iTempPage[i],flag[i],myBlock,M);
}
cout<<endl;
}
//Optimal最佳置換演算法
void Optimal(int iTempPage[N],int flag[N],block myBlock[M])
{
int i,j,k,loc;
bool ExistFlag=false;//退出標記
//初始化物理塊的內容,因任一種演算法在物理塊內容為空時,結果都一樣的
//同時將目前物理塊中的內容輸出
InitialBlock(iTempPage,flag,myBlock);
for(i=3;i<N;i++)
{
for(j=0;j<M;j++)
{
//物理塊中存在
if(myBlock[j].iPageNum==iTempPage[i])
{
flag[i]=0;
break;
}
}
//物理塊中不存在
if(j==M)
{
for(j=0;j<M;j++)
//定位物理塊中的某一個頁面在引用串中還未訪問串中頁面的位置,存入物理塊標記
myBlock[j].iBlockFlag=allocate(myBlock[j].iPageNum,i+1,iTempPage);
//找出標記最大的物理塊
loc=max(myBlock);
//換出操作
myBlock[loc].iPageNum=iTempPage[i];
flag[i]=1;
}
output(iTempPage[i],flag[i],myBlock,M);
}
}
//LRU置換演算法
void LRU(int iTempPage[N],int flag[N],block myBlock[M])
{
int i,j,k,loc;
bool ExistFlag=false;//退出標記
//初始化物理塊的內容,因任一種演算法在物理塊內容為空時,結果都一樣的
//同時將目前物理塊中的內容輸出
InitialBlock(iTempPage,flag,myBlock);
for(i=3;i<N;i++)
{
for(j=0;j<M;j++)
{
//物理塊中存在
if(myBlock[j].iPageNum==iTempPage[i])
{
//將物理塊中與引用串匹配的物理塊的標記位置0,其餘置1 (模擬移位暫存器)
for(k=0;k<M;k++)
if(k==j)
myBlock[k].iBlockFlag=0;
else
myBlock[k].iBlockFlag++;
// 缺頁標記
flag[i]=0;
break;
}
}
if(j==M)
{
//將物理塊中標記值最大的物理塊的下標找出
loc=max(myBlock);
//換出操作
myBlock[loc].iPageNum=iTempPage[i];
//缺頁標記
flag[i]=1;
// 將物理塊中與引用串匹配的物理塊的標記位置0,其餘加1(模擬移位暫存器)
for(k=0;k<M;k++)
if(k!=loc)
myBlock[k].iBlockFlag++;
else
myBlock[k].iBlockFlag=0;
}
output(iTempPage[i],flag[i],myBlock,M);
}
}
-------------------------------------------------------------------------------------------------
成果不易,如若有益,歡迎打賞