在操作系統中,當程序在運行過程中,若其所要訪問的頁面不再內存中而需要把他們調入內存,但內存已無空閑空間時,為了保證該進程能正常運行,系統必須從內存調出一頁程序或數據送磁盤的兌換區中。但哪一個頁面調出,須根據一定的算法確定。通常,把選擇換出頁面的算法稱為頁面置換算法(Page-Replacement Algorithms).置換算法的好壞將直接影響到系統的性能。
1) 先進先出(FIFO)頁面置換算法
該算法總是淘汰最先進入內存的頁面,即選擇在內存中駐留時間最久的頁面予以淘汰。該算法實現簡單,只需把一個進程調入內存,按先后順序排成一個隊列,並設置一個指針,稱為替換指針,使他總能指向最老的頁面。但該算法與進程與實際運行的規律不相適應,效率最差。
2) 最近最久為使用(LRU)算法
LRU算法是根據頁面調入內存后的使用情況進行決策的。就是利用“最近的過去”作為“最近的將來”的近似,因此是將最近最久未使用的頁面予以淘汰。該算法賦予每一個頁面一個訪問字段,用來記錄一個頁面自上次被訪問以來所經歷的時間t,當淘汰一個頁面時,選擇現有頁面中t值最大的,及最近最久為使用的頁面予以淘汰。
#include <stdio.h> #define PAGES 12 /*頁面引用頁數*/ #define M 3 /*當前分配給改作業的物理塊數*/ //#define M 4 /*頁面引用串*/ int page[PAGES] = {4,3,2,1,4,3,5,4,3,2,1,5}; int rel[M][PAGES]; /*存儲結果數組*/ /*內存物理塊結構體*/ typedef struct{ int pnum; /*該塊中所存的頁面號*/ int tm; /*從最近一次調入所經歷的時間*/ }PBlock; /*初始化物理塊數組*/ void init(PBlock *pb) { int i,j; //pb = (PBlock*)malloc(sizeof(PBlock)*M); for(i=0;i<M;i++){ pb[i].pnum = -1; pb[i].tm = -1; for(j=0;j<PAGES;j++){ rel[i][j] = -1; } } } /*打印結果數組*/ void printRelArr(int rel[M][PAGES]) { int i,j; for(i=0;i<M;i++){ for(j=0;j<PAGES;j++){ if(rel[i][j]==-1) printf("_ "); else printf("%d ",rel[i][j]); } printf("\n"); } } /*打印一維數組*/ void printArr1(int *arr,int n) { int i; for(i=0;i<n;i++){ printf("%d ",arr[i]); } printf("\n"); } /*查看頁面號為num的頁面是否在內存塊中,存在返回1*/ int in_mem(int num,PBlock *pb,int m) { int i; int b = 0; for(i=0;i<m;i++){ if(pb[i].pnum == num){ b = 1; break; } } return b; } /*FIFO 算法的實現,無需考慮時間*/ int fifo(PBlock *pb,int m) { int lps=0; /*缺頁次數*/ double lpp; /*缺頁率*/ int p = 0; /*替換指針*/ int index =0; /*頁面號索引*/ while(index<PAGES){ if(!in_mem(page[index],pb,M)){ //如果該頁面不在物理塊中 pb[p].pnum = page[index]; /*將該頁面放入物理塊中*/ p = (p+1)%M; /*替換指針移動*/ lps++; /*卻也次數加 1*/ for(int i=0;i<M;i++){ rel[i][index] = pb[i].pnum; } } index++; } printf("FIFO算法所得缺頁次數為 %d\n",lps); lpp = (double)lps/PAGES; printf("FIFO算法缺頁率為 %0.4lf \n",lpp); printf("頁面號序列為:\n"); printArr1(page,PAGES); printf("結果數列為:\n"); printRelArr(rel); return 0; } /*獲得最近最久的塊*/ int getP(PBlock *pb,int p) { int i; bool out = true; // for(i=0;i<M;i++){ if(pb[i].tm == -1){ p = i; out = false; break; } } if(out){ for(i=0;i<M;i++){ if(pb[i].tm>pb[p].tm) p = i; } } return p; } int getEQnum(int num,PBlock *pb) { int i; int in = -1; for(i=0;i<M;i++){ if(pb[i].pnum == num){ in = i; break; } } return in; } /*LRU算法*/ void lru(PBlock *pb,int m) { int lps=0; /*缺頁次數*/ double lpp; /*缺頁率*/ int p = 0; /*替換指針*/ int index =0; /*頁面號索引*/ while(index<PAGES){ if(!in_mem(page[index],pb,m)){ /*如果頁面不在物理塊中*/ p = getP(pb,p); pb[p].pnum = page[index]; pb[p].tm = 0; lps++; for(int i=0;i<M;i++){ rel[i][index] = pb[i].pnum; } }else{ /*如果頁面在物理塊中*/ int in = getEQnum(page[index],pb); /*獲取該頁面在物理塊中的索引*/ pb[in].tm = 0; } int i; for(i=0;i<M;i++){ if(i!=p&&pb[i].tm!=-1){ pb[i].tm++; } } index++; } printf("LRU算法所得缺頁次數為 %d \n",lps); lpp = 1.0*lps/PAGES; printf("LRU算法缺頁率為: %0.4lf\n",lpp); printf("頁面號序列為:\n"); printArr1(page,PAGES); printf("LRU結果數組為:\n"); printRelArr(rel); } int main() { //printArr(rel); PBlock pb[M]; init(pb); fifo(pb,M); init(pb); lru(pb,M); return 0; }