最近學習操作系統時,實驗要求實現常見的三種頁面置換算法,博主按照書上要求試着編寫,實現了案例,並記錄在博客隨記中,以便后續自己復習並也給需要的同學分享參考一下!水平有限,若有錯,請悄悄告訴博主!博主好立即改正。
最佳置換算法(optimal replacement,OPT)是從內存中選擇今后不再訪問的頁面或者在最長一段時間后才需要訪問的頁面進行淘汰。如下例子:
根據頁面走向依次處理,得到最終的置換結果如下圖表,整個頁面缺頁次數為7,缺頁率為7/12=58%。
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #define N 12 5 #define B 3 6 using namespace std; 7 8 int pageArr[N]={1,2,3,4,1,2,5,1,2,3,4,5};//頁面走向 9 int block[B]={0};//物理塊3個,其數值是頁號 10 typedef struct FLAG { 11 int flags[B]; 12 int counts; 13 } FLAG; 14 15 void opt(int pageArr[],int block[]); 16 int inBlock(int which); 17 int findFar(int next); 18 void Replace(int index,int value); 19 void disPlay(); 20 21 int main(void){ 22 cout << "begin:" <<endl; 23 opt(pageArr,block); 24 cout << "end!" <<endl; 25 return 0; 26 } 27 28 void opt(int pageArr[],int block[]){ 29 int getIndex; 30 for(int i=0;i<N;i++){ 31 if(i<3){//前3頁號#短缺#進隊列 32 block[i]=pageArr[i]; 33 printf("缺頁:(null)-->%d\n",pageArr[i]); 34 } 35 else { 36 if(i==3){ 37 disPlay(); 38 39 } 40 if(inBlock(pageArr[i])!=-1){//下一個頁面if在物理塊中返回index並跳過,反-1 41 disPlay(); 42 43 continue; 44 } 45 getIndex=findFar(i+1);//從下一個頁號,找到最遠出現的頁面,替換的下標 46 if(getIndex==-1){ 47 cout<<"error,not replace obj!"<<'\t'; 48 } 49 else{ 50 Replace(getIndex,pageArr[i]);//由下標找到上一組替換目標,用第二參數替換 51 disPlay(); 52 53 } 54 } 55 } 56 return; 57 } 58 59 //替換block中的物理塊 60 void Replace(int index,int value){ 61 printf("缺頁:%d--被替換為-->%d\n",block[index],value); 62 block[index]=value; 63 return; 64 } 65 66 67 //找到最遠出現的頁面 68 int findFar(int next){ 69 int index=-1;//error,默認返回不存在的索引 70 FLAG myflag; 71 myflag.flags[0]=0; 72 myflag.flags[1]=0; 73 myflag.flags[2]=0; 74 myflag.counts=0; 75 int stop = N-next; 76 while(stop--){ 77 index=inBlock(pageArr[next++]); 78 if(index!=-1){ 79 myflag.flags[index]=1; 80 myflag.counts++; 81 } 82 else if(myflag.counts==B-1){//有2個不缺值時 83 break; 84 } 85 } 86 for(index=0;index<B;index++){ 87 if(myflag.flags[index]==0) 88 break; 89 } 90 return index; 91 } 92 93 94 //下一個頁面if在物理塊中返回index,反-1 95 int inBlock(int which){ 96 //int i=0; 97 //while(i<B) 98 // if(block[i++]==which) 99 // return i-1; 100 for(int i=0;i<B;i++){ 101 if(block[i]==which) 102 return i; 103 } 104 return -1; 105 } 106 107 //打印一元組 108 void disPlay(){ 109 int i=0; 110 while(i<B){ 111 printf("%d\t",block[i++]); 112 } 113 printf("\n"); 114 return; 115 }
上面是博主使用C++(基本是C語法)編寫的代碼,運行結果如下:
//////////////////////////////////////////////////////////////////////////
begin:
缺頁:(null)-->1
缺頁:(null)-->2
缺頁:(null)-->3
1 2 3
缺頁:3--被替換為-->4
1 2 4
1 2 4
1 2 4
缺頁:4--被替換為-->5
1 2 5
1 2 5
1 2 5
缺頁:1--被替換為-->3
3 2 5
缺頁:3--被替換為-->4
4 2 5
4 2 5
end!
//////////////////////////////////////////////////////////////////////////
先進先出算法:先進先出置換算法(first in first out,FIFO)是淘汰最先進入內存的頁面,即選擇在內存中駐留時間最長的頁面進行淘汰的算法。
下面舉個例子:
根據頁面走向依次處理,得到最終的置換結果如上圖表,整個頁面缺頁次數為9,缺頁率為9/12=75%。
使用代碼實現:
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #define B 3 5 #define N 12 6 7 typedef struct flag{ 8 int blocks[B]; 9 int index;//預留但沒用到 10 }FLAG; 11 using namespace std; 12 13 //全局變量(共享) 14 int pageArr[N]={1,2,3,4,1,2,5,1,2,3,4,5};//頁面走向 15 int block[B]={0};//物理塊3個,其數值是頁號 16 FLAG bflag={{0,0,0},-1}; 17 18 void disPlay(); 19 int inBlock(int value); 20 void fifo(); 21 int checkFlag(); 22 23 int main(){ 24 cout<<"begin"<<endl; 25 fifo(); 26 cout<<"end!"<<endl; 27 return 0; 28 } 29 //先進先出 30 void fifo(){ 31 int i=0; 32 int getIndex;//物理塊索引 33 int getflag;//flag索引 34 while(i<N){ 35 getIndex=inBlock(pageArr[i]); 36 if(getIndex==-1){//缺頁返回-1,不缺頁返回index並下一個 37 cout<<"缺頁:"<<pageArr[i]<<"\t\t"; 38 if((getflag=checkFlag())!=-1){//檢查呆的久的 39 block[getflag]=pageArr[i]; 40 } 41 else{ 42 block[i%B]=pageArr[i]; 43 } 44 } 45 else{ 46 bflag.blocks[getIndex]=1; 47 } 48 disPlay(); 49 i++; 50 } 51 } 52 //檢查是否在物理塊中 53 int inBlock(int value){ 54 int index=-1; 55 for(int i=0;i<B;i++){ 56 if(block[i]==value){ 57 index=i; 58 break; 59 } 60 } 61 return index; 62 } 63 //打印一組 64 void disPlay(){ 65 for(int i=0;i<B;i++){ 66 cout<<block[i]<<'\t'; 67 //printf("%d\t",block[i]); 68 } 69 printf("\n"); 70 } 71 72 int checkFlag(){ 73 int i=0; 74 int index=-1; 75 while(i<B){ 76 if(bflag.blocks[i]==1){ 77 bflag.blocks[i]=0; 78 index=i; 79 break; 80 } 81 i++; 82 } 83 return index; 84 }
運行結果:
//////////////////////////////////////////////////////////////////////////
begin
缺頁:1 1 0 0
缺頁:2 1 2 0
缺頁:3 1 2 3
缺頁:4 4 2 3
缺頁:1 4 1 3
缺頁:2 4 1 2
缺頁:5 5 1 2
5 1 2
5 1 2
缺頁:3 5 3 2
缺頁:4 5 3 4
5 3 4
end!
//////////////////////////////////////////////////////////////////////////
最近最久未使用算法:先進先出置換算法是最佳置換算法之間的主要差別是,先進先出置換算法利用頁面進入內存后的時間最為置換依據,而最佳置換算法是將來使用頁面的情況。如果以最近的過去作為不就將來的近似,那么就可以把過去最長時間里不曾被使用的頁面置換掉。它的實質是,當需要置換一頁時,選擇在最近的一段時間里最久沒有使用的頁面進行置換。這種算法就稱為最近最久未使用(least recently used,LRU)算法。最近最久未使用算法與每個頁面最后使用的時間有關。
根據頁面走向依次處理,得到最終的置換結果如下圖表,整個頁面缺頁次數為10,缺頁率為10/12=83%。
下面是一個案例:
使用代碼實現:
1 #include <iostream> 2 #include <stdio.h> 3 #define N 12 4 #define B 3 5 6 typedef struct flag{ 7 int fblock[B];//記錄各個物理塊時間戳 8 int pflag;//指針 9 }FLAG; 10 using namespace std; 11 12 //全局變量(共享) 13 int pageArr[N]={1,2,3,4,1,2,5,1,2,3,4,5};//頁面走向 14 int block[B]={0};//物理塊3個,其數值是頁號 15 FLAG myflag={{0},0}; 16 17 void lru(); 18 int inBlock(int value); 19 void disPlay(); 20 int findMaxTime(); 21 void addStamp(); 22 23 24 int main() 25 { 26 cout<<"begin"<<endl; 27 lru(); 28 cout<<"end!"<<endl; 29 return 0; 30 } 31 32 void lru(){ 33 int i; 34 int getIndex; 35 int maxOfIndex; 36 for(i=0;i<N;i++){ 37 if(i<B){//前三個頁 38 block[i]=pageArr[i]; 39 myflag.fblock[i]=B-i; 40 cout<<"缺頁:"<<pageArr[i]<<"\t\t"; 41 } 42 else{ 43 getIndex=inBlock(pageArr[i]); 44 if(getIndex==-1){//缺頁 45 maxOfIndex=findMaxTime(); 46 block[maxOfIndex]=pageArr[i]; 47 myflag.pflag=maxOfIndex; 48 cout<<"缺頁:"<<pageArr[i]<<"\t\t"; 49 } 50 else{ 51 myflag.pflag=getIndex; 52 } 53 addStamp(); 54 } 55 disPlay(); 56 } 57 } 58 59 //給其他加時間戳 60 void addStamp(){ 61 int i=0; 62 while(i<B){ 63 if(i!=myflag.pflag) 64 myflag.fblock[i]++; 65 else 66 myflag.fblock[i]=0; 67 i++; 68 } 69 } 70 71 //在物理塊中就返回索引,否則返回-1 72 int inBlock(int value){ 73 int index=-1; 74 int i=0; 75 while(i<B){ 76 if(block[i]==value){ 77 index=i; 78 break; 79 } 80 i++; 81 } 82 return index; 83 } 84 85 //打印一組 86 void disPlay(){ 87 for(int i=0;i<B;i++){ 88 printf("%d\t",block[i]); 89 } 90 printf("\n"); 91 } 92 93 //找到時間戳最大的物理塊下標 94 int findMaxTime(){ 95 int i=0; 96 int index=0;//默認第一個時間戳最大 97 for(i=1;i<B;i++){ 98 if(myflag.fblock[index]<myflag.fblock[i]) 99 index=i; 100 } 101 return index; 102 }
運行結果:
//////////////////////////////////////////////////////////////////////////
begin
缺頁:1 1 0 0
缺頁:2 1 2 0
缺頁:3 1 2 3
缺頁:4 4 2 3
缺頁:1 4 1 3
缺頁:2 4 1 2
缺頁:5 5 1 2
5 1 2
5 1 2
缺頁:3 3 1 2
缺頁:4 3 4 2
缺頁:5 3 4 5
end!
//////////////////////////////////////////////////////////////////////////