操作系統——模擬頁面置換算法(FIFO——先入先出、LRU——最近最少使用、LFU——最近最不常使用),計算置換率(包含程序框圖)
導語:
1. FIFO頁面置換算法:最簡單的頁面置換算法。這種算法的基本思想是:當需要淘汰一個頁面時,總是選擇駐留主存時間最長的頁面進行淘汰,即先進入主存的頁面先淘汰。(看時間)
2. LRU頁面置換算法:最近最少使用,簡單來說就是將數據塊中,每次使用過的數據放在數據塊的最前端,然后將存在的時間最長的,也就是數據塊的末端的數據置換掉。(看時間)
3. LFU頁面置換算法:近期最少使用算法,選擇近期最少訪問的頁面作為被替換的頁面,如果一個數據在最近一段時間內使用次數很少,那么在將來一段時間內被使用的可能性也很小。(看次數)
4. 置換率與與缺頁率不同。置換率用置換次數算,缺頁率用缺頁中斷次數算。
FIFO頁面置換算法:
Linux效果圖(采用UOS + VScode + g++)

程序框圖

C++代碼(FIFO):
#include<iostream>
using namespace std;
static int mnum;
//物理塊數
static int pnum;
//頁面走向
static int count=0;
//頁面置換次數
static int *analogblock;
//模擬物理塊
static int *block;
//物理塊
static int *process;
//隨機頁面訪問序列
int judge(int a[],int n,int x) //判斷數組中是否已有x,若有返回其下標值,沒有則返回-1 {
int i;
for (i=0;i<n;i++)
if(x==a[i])
return i;
return -1;
}
void replace(int y,int mnum,int x)//用於物理塊頁面置換,y是用來置換的頁面,x是被置換的頁面 {
int i;
for (i=0;i<mnum;i++)
if(x==block[i])
block[i]=y;
}
int main() {
int i;
int maxanalogblock=-1;
//模仿隊列的定義
int x;
cout<<"請輸入頁框大小物理塊數:\n";
cin>>mnum;
if(mnum>999999) {
cout<<"輸入超出控制大小!"<<endl;
return 0;
}
cout<<"自動生成的內存塊需求序列個數:\n";
cin>>pnum;
if(pnum>999999) {
cout<<"輸入超出控制大小!"<<endl;
return 0;
}
analogblock=new int[mnum];
block=new int[mnum];
process=new int[pnum];
for (i=0;i<mnum;i++) analogblock[i]=-1;
for (i=0;i<mnum;i++) block[i]=-1;
/////////////////////
//隨機產生頁面走向序列
cout<<"產生隨機序列如下:\n";
srand( (unsigned)time( NULL ) );
//以time函數值(即當前時間)作為種子數,保證兩次產生序列的隨機性
for (i=0; i<pnum; i++) {
process[i] = rand()%10;
cout<<process[i]<<" ";
}
cout<<endl;
//////////////////////
cout<<"先進先出(FIFO)頁面置換算法,結果: \n\n";
//////////////////////
for (x=0;x<pnum;x++) //自動讀數 {
//讀一個序列號,輸出當前數組元素
cout<<"真實物理塊情況:";
for (i=0;i<mnum;i++) {
if(block[i]!=-1)
cout<<block[i]<<" ";
}
cout<<"模擬物理塊情況:";
for (i=0;i<mnum;i++) {
if(analogblock[i]!=-1)
cout<<analogblock[i]<<" ";
}
//////////////////////////
maxanalogblock++;
//讀數后maxanalogblock自動+1
if(maxanalogblock<mnum) //若在物理塊范圍內 {
if(judge(analogblock,mnum,process[x])==-1)//若數組中不存在待插入元素 {
analogblock[maxanalogblock]=process[x];
//新元素從尾部插入
block[maxanalogblock]=process[x];
//新元素從尾部插入
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 缺頁中斷 調入頁面"<<process[x]<<endl;
} else //若數組中存在待插入元素 {
maxanalogblock--;
//因為沒有插入新元素,回滾maxanalogblock值
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 已存在 直接訪問"<<endl;
}
} else //超過物理塊數的元素 {
if(judge(analogblock,mnum,process[x])==-1)//若數組中不存在待插入元素 {
//隊列法插入(尾部元素出,新元素從頭部入)
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 缺頁中斷 頁面"<<process[x]<<"置換出頁面"<<analogblock[0]<<endl;
replace(process[x],mnum,analogblock[0]);
//置換物理塊中頁面
for (i=0;i<mnum-1;i++)
analogblock[i]=analogblock[i+1];
analogblock[mnum-1]=process[x];
//////////////////
maxanalogblock--;
//因為沒有插入新元素,回滾maxanalogblock值
count++;
} else //若數組中存在待插入元素 {
maxanalogblock--;
//因為沒有插入新元素,回滾maxanalogblock值
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 已存在 直接訪問"<<endl;
}
}
}
//讀一個序列號,輸出當前數組元素
cout<<"真實物理塊情況:";
for (i=0;i<mnum;i++) {
if(block[i]!=-1)
cout<<block[i]<<" ";
}
cout<<"模擬物理塊情況:";
for (i=0;i<mnum;i++) {
if(analogblock[i]!=-1)
cout<<analogblock[i]<<" ";
}
cout<<endl<<"頁面換算次數為:"<<count<<endl;
cout<<"置換率為:"<<(float)count/pnum<<endl;
return 0;
}
//g++ test71.cpp -o test71 -lpthread&&./test71
LRU頁面置換算法:
Linux效果圖(采用UOS + VScode + g++)

程序框圖

C++代碼(LRU):
#include<iostream>
using namespace std;
static int mnum;
//物理塊數
static int pnum;
//頁面走向
static int count=0;
//頁面置換次數
static int *analogblock;
//模擬物理塊
static int *block;
//物理塊
static int *process;
//隨機頁面訪問序列
int judge(int a[],int n,int x) //判斷數組中是否已有x,若有返回其下標值,沒有則返回-1 {
int i;
for (i=0;i<n;i++)
if(x==a[i])
return i;
return -1;
}
void replace(int y,int mnum,int x)//用於物理塊頁面置換,y是用來置換的頁面,x是被置換的頁面 {
int i;
for (i=0;i<mnum;i++)
if(x==block[i])
block[i]=y;
}
void move(int a[],int n,int i) //移動下標為i的元素到尾部 {
int j;
int m=a[i];
for (j=i;j<n-1;j++)
a[j]=a[j+1];
a[n-1]=m;
}
int main() {
int i;
int maxanalogblock=-1;
//模仿棧的定義
int x;
cout<<"請輸入頁框大小物理塊數:\n";
cin>>mnum;
if(mnum>999999) {
cout<<"輸入超出控制大小!"<<endl;
return 0;
}
cout<<"自動生成的內存塊需求序列個數:\n";
cin>>pnum;
if(pnum>999999) {
cout<<"輸入超出控制大小!"<<endl;
return 0;
}
analogblock=new int[mnum];
block=new int[mnum];
process=new int[pnum];
for (i=0;i<mnum;i++) analogblock[i]=-1;
/////////////////////
//隨機產生頁面走向序列
cout<<"產生隨機序列如下:\n";
srand( (unsigned)time( NULL ) );
//以time函數值(即當前時間)作為種子數,保證兩次產生序列的隨機性
for (i=0; i<pnum; i++) {
process[i] = rand()%10;
cout<<process[i]<<" ";
}
cout<<endl;
//////////////////////
cout<<"最近最少使用(LRU)頁面置換算法,結果: \n\n";
//////////////////////
for (x=0;x<pnum;x++) //自動讀數 {
//讀一個序列號,輸出當前數組元素
cout<<"真實物理塊情況:";
for (i=0;i<mnum;i++) {
if(block[i]!=-1)
cout<<block[i]<<" ";
}
cout<<"模擬物理塊情況:";
for (i=0;i<mnum;i++) {
if(analogblock[i]!=-1)
cout<<analogblock[i]<<" ";
}
//////////////////////////
maxanalogblock++;
//讀數后maxanalogblock自動+1
if(maxanalogblock<mnum) //若在物理塊范圍內 {
if(judge(analogblock,mnum,process[x])==-1)//若數組中不存在待插入元素 {
analogblock[maxanalogblock]=process[x];
//新元素從尾部插入
block[maxanalogblock]=process[x];
//新元素從尾部插入
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 缺頁中斷 調入頁面"<<process[x]<<endl;
} else //若數組中存在待插入元素 {
move(analogblock,maxanalogblock,judge(analogblock,mnum,process[x]));
//移動下標為i的元素到尾部
maxanalogblock--;
//因為沒有插入新元素,回滾maxanalogblock值
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 已存在 直接訪問"<<endl;
}
} else //超過物理塊數的元素 {
if(judge(analogblock,mnum,process[x])==-1)//若數組中不存在待插入元素 {
//棧法插入(第一個元素出,后面元素前移,新元素從尾部入)
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 缺頁中斷 頁面"<<process[x]<<"置換出頁面"<<analogblock[0]<<endl;
replace(process[x],mnum,analogblock[0]);
//物理塊中頁面置換
for (i=0;i<mnum-1;i++)
analogblock[i]=analogblock[i+1];
analogblock[mnum-1]=process[x];
//////////////////
maxanalogblock--;
//因為沒有插入新元素,回滾maxanalogblock值
count++;
} else //若數組中存在待插入元素 {
move(analogblock,mnum,judge(analogblock,mnum,process[x]));
//移動下標為i的元素到尾部
maxanalogblock--;
//因為沒有插入新元素,回滾maxanalogblock值
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 已存在 直接訪問"<<endl;
}
}
}
//讀一個序列號,輸出當前數組元素
cout<<"真實物理塊情況:";
for (i=0;i<mnum;i++) {
if(block[i]!=-1)
cout<<block[i]<<" ";
}
cout<<"模擬物理塊情況:";
for (i=0;i<mnum;i++) {
if(analogblock[i]!=-1)
cout<<analogblock[i]<<" ";
}
cout<<endl<<"頁面換算次數為:"<<count<<endl;
cout<<"置換率為:"<<(float)count/pnum<<endl;
return 0;
}
//g++ test72.cpp -o test72 -lpthread&&./test72
LFU頁面置換算法:
Linux效果圖(采用UOS + VScode + g++)

程序框圖

C++代碼(LFU):
#include<iostream>
using namespace std;
static int mnum;
//物理塊數
static int pnum;
//頁面走向
static int count=0;
//頁面置換次數
static int **analogblock;
//模擬物理塊
static int *block;
//物理塊
static int *process;
//隨機頁面訪問序列
int judge(int *a[],int n,int x) //判斷數組中是否已有x,若有返回其下標值,沒有則返回-1 {
int i;
for (i=0;i<n;i++)
if(x==a[i][0])
return i;
return -1;
}
void replace(int y,int mnum,int x)//用於物理塊頁面置換,y是用來置換的頁面,x是被置換的頁面 {
int i;
for (i=0;i<mnum;i++)
if(x==block[i])
block[i]=y;
}
void move(int *a[],int n,int i) //移動下標為i的元素,比較訪問次數次多少進行前進 {
int j;
int m=a[i][0];
int m2=a[i][1];
for (j=i;j<n-1;j++) {
if(m2>=a[j+1][1]) {
a[j][0]=a[j+1][0];
a[j][1]=a[j+1][1];
a[j+1][0]=m;
a[j+1][1]=m2;
}
}
}
int main() {
int i;
int maxanalogblock=-1;
//模仿棧的定義
int x;
//動態數組初始化
cout<<"請輸入頁框大小物理塊數:\n";
cin>>mnum;
if(mnum>999999) {
cout<<"輸入超出控制大小!"<<endl;
return 0;
}
cout<<"自動生成的內存塊需求序列個數:\n";
cin>>pnum;
if(pnum>999999) {
cout<<"輸入超出控制大小!"<<endl;
return 0;
}
analogblock=(int**) (new int[mnum]);
block=new int[mnum];
process=new int[pnum];
for (i=0;i<mnum;i++) analogblock[i]=(int*) new int[2];
//用於保存頁面號和訪問次數
for (i = 0; i < mnum; i++) {
analogblock[i][0]=-1;
analogblock[i][1]=0;
}
/////////////////////
//隨機產生頁面走向序列
cout<<"產生隨機序列如下:\n";
srand( (unsigned)time( NULL ) );
//以time函數值(即當前時間)作為種子數,保證兩次產生序列的隨機性
for (i=0; i<pnum; i++) {
process[i] = rand()%10;
cout<<process[i]<<" ";
}
cout<<endl;
//////////////////////
cout<<"最近最不常使用(LFU)頁面置換算法,結果: \n\n";
//////////////////////
for (x=0;x<pnum;x++) //自動讀數 {
//讀一個序列號,輸出當前數組元素
cout<<"真實物理塊情況:";
for (i=0;i<mnum;i++) {
if(block[i]!=-1)
cout<<block[i]<<" ";
}
cout<<"模擬物理塊情況:";
for (i=0;i<mnum;i++) {
if(analogblock[i][0]!=-1)
cout<<analogblock[i][0]<<" ";
//<<"訪問次數"<<analogblock[i][1]<<" "
}
//////////////////////////
maxanalogblock++;
//讀數后maxanalogblock自動+1
if(maxanalogblock<mnum) //若在物理塊范圍內 {
if(judge(analogblock,mnum,process[x])==-1)//若數組中不存在待插入元素 {
analogblock[0][0]=process[x];
//新元素從頭部插入
analogblock[0][1]=1;
block[maxanalogblock]=process[x];
//新元素從尾部插入
move(analogblock,mnum,0);
//移動下標為i的元素到相同訪問次數頁面的頂部
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 缺頁中斷 調入頁面"<<process[x]<<endl;
} else //若數組中存在待插入元素 {
// move(analogblock,maxanalogblock,judge(analogblock,mnum,process[x]));//移動下標為i的元素到尾部
analogblock[judge(analogblock,mnum,process[x])][1]++;
move(analogblock,mnum,judge(analogblock,mnum,process[x]));
//移動下標為i的元素到相同訪問次數頁面的頂部
maxanalogblock--;
//因為沒有插入新元素,回滾maxanalogblock值
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 已存在 直接訪問"<<endl;
}
} else //超過物理塊數的元素 {
if(judge(analogblock,mnum,process[x])==-1)//若數組中不存在待插入元素 {
//棧法插入(新元素從頭部入,替換掉頭部)
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 缺頁中斷 頁面"<<process[x]<<"置換出頁面"<<analogblock[0][0]<<endl;
replace(process[x],mnum,analogblock[0][0]);
//物理塊中頁面置換
analogblock[0][0]=process[x];
analogblock[0][1]=1;
move(analogblock,mnum,0);
//移動下標為i的元素相同訪問次數頁面的頂部
//////////////////
maxanalogblock--;
//因為沒有插入新元素,回滾maxanalogblock值
count++;
} else //若數組中存在待插入元素 {
analogblock[judge(analogblock,mnum,process[x])][1]++;
move(analogblock,mnum,judge(analogblock,mnum,process[x]));
//移動下標為i的元素到相同訪問次數頁面的頂部
maxanalogblock--;
//因為沒有插入新元素,回滾maxanalogblock值
cout<<" 第"<<x+1<<"次訪問,頁面"<<process[x]<<" 已存在 直接訪問"<<endl;
}
}
}
//讀一個序列號,輸出當前數組元素
cout<<"真實物理塊情況:";
for (i=0;i<mnum;i++) {
if(block[i]!=-1)
cout<<block[i]<<" ";
}
cout<<"模擬物理塊情況:";
for (i=0;i<mnum;i++) {
if(analogblock[i][0]!=-1)
cout<<analogblock[i][0]<<" ";
}
cout<<endl<<"頁面換算次數為:"<<count<<endl;
cout<<"置換率為:"<<(float)count/pnum<<endl;
return 0;
}
//g++ test73.cpp -o test73 -lpthread&&./test73