頁面置換演算法 FIFO和LRU 及各自的命中率
阿新 • • 發佈:2019-01-09
(1) 先進先出演算法FIFO:該演算法的實質是選擇作業中在主存駐留時間最長的一頁淘汰,這種演算法容易實現,例如分配一個作業的儲存塊數為m,則只需建立一張m個元素的隊列表Q(0)、Q(1)、…、Q(m-1)和一個替換指標。這個佇列是按頁調入主存的一頁。如圖4-1所示,某時刻調入主存四個塊,(即m=4),它們按頁進入主存的先後順序為4、5、1、2,當需要置換時,總是淘汰替換指標所指向的那一頁, 新調進的頁面裝入主存後,修改相應的佇列元素,然後將替換指標往前移動,使其指向當前最老的一頁。
(2) 最近最少使用頁面淘汰演算法(LRU):這是一種經常使用的方法,有多種不同的實施方案。這裡採用不斷調整頁錶鏈的方法,即總是淘汰頁錶鏈鏈首的頁面,而把新訪問的頁面插入鏈尾。如果當前呼叫頁面已在頁表內,則把它再次調整到鏈尾。這樣就能保證最近使用的頁面總處於靠近鏈尾部分,而不常使用的頁面被移到鏈首,逐個被淘汰。
#include<stdio.h> #define N 100 #define M 12//作業數 #define ASSIGN 4//儲存塊數 //請求式分頁儲存演算法 //佇列 typedef struct Queue{ int Q[N];//儲存頁面 int front,rear;//隊頭和隊尾 }Queue; //連結串列 typedef struct AdjList{ int data; struct AdjList *next; }AdjList; //初始化佇列 void InitQueue(Queue *Q){ Q->front=-1; Q->rear=0; } //加入佇列 void EnterQueue(Queue *Q,int n){ if(Q->front>=Q->rear){ printf("插入失敗\n"); }else{ Q->front++; Q->Q[Q->front]=n; Q->rear++; } } //出隊 void OutQueue(Queue *Q){ if(Q->front<0){ printf("queue is empty\n"); }else{ Q->front--; Q->rear--; } } //在佇列中查詢 int CheckQueue(Queue *Q,int n){ int i; if(Q->front<0){ //printf("queue is empty\n"); }else{ for(i=0;i<Q->rear;i++){ if(n==Q->Q[i]){ return 1; } } } return 0; } //列印佇列 void PrintQueue(Queue *Q){ int i; if(Q->front<0){ //printf("queue is empty\n"); }else{ printf("列印佇列:"); for(i=0;i<Q->rear;i++){ printf("%d ",Q->Q[i]); } printf("\n"); } } //先進先出並算命中率 void FIFO(int A[]){ int i,num=0,k=0; Queue *Q=(Queue *)malloc(sizeof(Queue)); InitQueue(Q); for(i=0;i<M;i++){ if(CheckQueue(Q,A[i])==1){ num++; }else{ if(k<ASSIGN){ EnterQueue(Q,A[i]); }else{ OutQueue(Q); EnterQueue(Q,A[i]); } k++; } PrintQueue(Q); } printf("FIFO的命中率為%f\n",(float)num/M); } //插入連結串列 頭插法,鏈尾為隊首(邏輯上) void AddTail(AdjList *L,int n){ if(L!=NULL){ AdjList *p=(AdjList *)malloc(sizeof(AdjList)); p->next=L->next; p->data=n; L->next=p; }else{ printf("連結串列為空\n"); } } //刪除鏈首 void deleteTail(AdjList *L){ if(L!=NULL){ AdjList *p=L; while(p->next->next!=NULL){ p=p->next; } p->next=NULL; }else{ printf("連結串列為空\n"); } } //查詢n,若在,則調整到隊尾 int CheckChangeTail(AdjList *L,int n){ if(L!=NULL){ AdjList *p=L; while(p->next!=NULL){ //printf("連結串列為空\n"); if(p->next->data==n){ p->next=p->next->next; AddTail(L,n); return 1; } p=p->next; } return 0; } } //列印連結串列、 void printTail(AdjList *L){ if(L!=NULL){ AdjList *p=L->next; printf("列印連結串列:"); while(p!=NULL){ printf("%d ",p->data); p=p->next; } printf("\n"); } } //最近最少使用頁面淘汰演算法 void LRU(int A[]){ int i,num=0,k=0; AdjList *L=(AdjList *)malloc(sizeof(AdjList)); L->next=NULL; for(i=0;i<M;i++){ //printf("連結串列為空\n"); if(CheckChangeTail(L,A[i])==1){ num++; }else{ if(k<ASSIGN){ AddTail(L,A[i]); }else{ deleteTail(L); AddTail(L,A[i]); } k++; } printTail(L); } printf("LRU的命中率為%f\n",(float)num/M); } int main(){ int i,A[N]; for(i=0;i<M;i++){//隨機產生個M個程序作業數,沒次呼叫的頁面在1-8之間 A[i]=rand()%8+1; printf("%d ",A[i]); } printf("\n"); FIFO(A); LRU(A); }