1. 程式人生 > 其它 >作業系統實驗五

作業系統實驗五

頁面置換演算法

題目
設程序的邏輯地址空間共分為8個頁面,程序執行時需引用的頁面號引用串為7、0、1、2、0、3、0、4、2、3、0、3、2、1、2、0、1、7、0、1,現系統為該程序在記憶體中分配了三個物理儲存塊。請根據理論教材所授內容,採用C語言(也可採用自己熟悉的語言)分別模擬實現OPT、FIFO、LRU、NRU和LFU頁面置換演算法,對上述頁面號引用串進行排程,並計算出各演算法下的缺頁率。

程式碼如下:

OPT頁面置換演算法
#include <iostream>  
#include<map>
#include<set>
#include <algorithm>
#include<cstdio>
#include<cstring> 
#include<cmath>
#define N 200
using namespace std;  
 
int page[N];//頁面引用號 
int block[N];//物理塊,記憶體 
int dist[N][N];//表示第i次訪問記憶體的時候,記憶體中的頁面j 在以後被訪問的最小時間 

int n;//頁面引用號個數 
int m;//物理塊數目 
int page_max;//最大頁面號 

int pre[N];//page[i]在page中的索引
int opt(){//最佳頁面置換演算法 
    int page_lack = 0;
    memset(pre, 0, sizeof(pre));
    memset(dist, 0x3f, sizeof(dist));
    memset(block, -1, sizeof(block));
    for(int i=n; i>=1; --i){
         for(int j=0; j<=page_max; ++j) 
             if(pre[j])
                dist[i][j] = pre[j] - i;
         pre[page[i]] = i; 
    }
    
    for(int i=1; i<=n; ++i){//開始訪問頁面 
        int j;
        int max_dist = 0, p; 
        for(j=1; j<=m; ++j){
            if(block[j] == -1){//該物理塊中沒有被放入頁面,則直接放入, 產生缺頁 
                block[j] = page[i]; 
                cout<<"頁面"<<page[i]<<"不在記憶體,直接放入物理塊"<<j<<"中!"<<endl;
                page_lack++;
                break;
            } else if(block[j] == page[i])//頁面存在記憶體中 
                break;
            
            if(max_dist < dist[i][block[j]]){
                max_dist = dist[i][block[j]];//說明block[j] 對應的頁面以後會長時間不會用到 
                p = j;//block[] 第j個頁面會被替換掉 
            }
        }
        if(j > m){//此時物理塊中被裝滿,且沒有找到page[i]對應的分頁,接下來進行頁面替換 
             cout<<"頁面"<<page[i]<<"不在記憶體,將物理塊"<<p<<"中的頁面" <<block[p]<<"替換掉!"<<endl;
             block[p] = page[i];
             page_lack++; 
        }
        cout<<endl<<"當前記憶體中頁面的情況:"<<endl; 
        for(int k=1; k<=m; ++k)//記憶體中頁面載入情況 
            cout<<block[k]<<" ";
        cout<<endl<<endl;
    }
    return page_lack;//返回缺頁次數 
} 
int main(){
	int page_lack;
	float w;//w為缺頁中斷率 
	cout<<"請輸入頁面引用號個數" ;
    cin>>n;
	cout<<"請輸入物理塊個數";
	cin>>m;
	cout<<"輸入頁面引用序列"; 
    for(int i=1; i<=n; ++i){ 
        cin>>page[i];
        page_max = max(page_max, page[i]) ;
    } 
    page_lack=opt(); 
    w=(float)page_lack/n; 
     cout<<"OPT缺頁中斷次數:"<<page_lack<<endl;
     cout<<"缺頁中斷率:"<<w<<endl;
     return 0;
} 

執行截圖:

FIFO頁面置換演算法

#include <iostream>  
#include<map>
#include<set>
#include <algorithm>
#include<cstdio>
#include<cstring> 
#include<cmath>
#define N 200
using namespace std;  
 
int page[N];//頁面引用號 
int block[N];//物理塊,記憶體 
int dist[N][N];//表示第i次訪問記憶體的時候,記憶體中的頁面j 在以後被訪問的最小時間 

int n;//頁面引用號個數 
int m;//物理塊數目 
int page_max;//最大頁面號 
set<int>page_set;
int fifo(){//先進先出頁面置換演算法
    int page_lack = 0; 
    memset(block, -1, sizeof(block));
    int index = 1;
    for(int i=1; i<=n; ++i){
        if(index > m) index = 1;
        set<int>::iterator it;
        it = page_set.find(page[i]);  
        if(it == page_set.end()){
            if(block[index] != -1)
                page_set.erase(block[index]);
            page_set.insert(page[i]);
            block[index++] = page[i];
            ++page_lack;
        } 
        for(int k=1; k<=m; ++k)
            cout<<block[k]<<" ";
        cout<<endl;
    } 
    return page_lack;
}

int main(){
	int v;//w為缺頁率 ,v為缺頁中斷次數 
	float w;
	cout<<"請輸入頁面引用號個數" ;
    cin>>n;
	cout<<"請輸入物理塊個數";
	cin>>m;
	cout<<"請輸入頁面號引用次序"; 
    for(int i=1; i<=n; ++i){ 
        cin>>page[i];
        page_max = max(page_max, page[i]) ;
    } 
    v=fifo();
	w=(float)v/n; 
     cout<<"FIFO缺頁中斷次數:"<<v<<endl;
     cout<<"FIFO缺頁中斷率:"<<w<<endl;
     
     return 0;
} 

執行截圖:

LRU演算法

#include <iostream>  
#include<map>
#include<set>
#include <algorithm>
#include<cstdio>
#include<cstring> 
#include<cmath>
#define N 200
using namespace std;  
 
int page[N];//頁面引用號 
int block[N];//物理塊,記憶體 
int dist[N][N];//表示第i次訪問記憶體的時候,記憶體中的頁面j 在以後被訪問的最小時間 

int n;//頁面引用號個數 
int m;//物理塊數目 
int page_max;//最大頁面號 
int pre[N];//page[i]在page中的索引
int LRU(){
    int page_lack = 0;//page_back為缺頁次數 
    memset(pre, 0, sizeof(pre));
    memset(dist, 0x3f, sizeof(dist));
    memset(block, -1, sizeof(block));
    for(int i=1; i<=n; ++i){
         for(int j=0; j<=page_max; ++j) 
             if(pre[j])
                dist[i][j] = i - pre[j];
         pre[page[i]] = i; 
    }
    
    for(int i=1; i<=n; ++i){//開始訪問頁面
        int j;
        int max_dist = 0, p; 
        for(j=1; j<=m; ++j){
            if(block[j] == -1){//該塊沒有放入頁面,則直接放入, 產生缺頁 
                block[j] = page[i]; 
                cout<<"頁面"<<page[i]<<"不在記憶體,直接放入物理塊"<<j<<"中!"<<endl;
                page_lack++;
                break;
            } else if(block[j] == page[i])//頁面存在記憶體中 
                break;
            
            if(max_dist < dist[i][block[j]]){
                max_dist = dist[i][block[j]];
                p = j;//block[] 第j個頁面會被替換掉 
            }
        }
        if(j > m){
             cout<<"頁面"<<page[i]<<"不在記憶體,將物理塊"<<p<<"中的頁面" <<block[p]<<"替換!"<<endl;
             block[p] = page[i];
             page_lack++; 
        }
        cout<<endl<<"當前記憶體中頁面的情況:"<<endl; 
        for(int k=1; k<=m; ++k)//記憶體中頁面載入情況 
            cout<<block[k]<<" ";
        cout<<endl<<endl;
    }
    return page_lack;
} 


int main(){

	cout<<"請輸入頁面引用號個數" ;
    cin>>n;
	cout<<"請輸入物理塊個數";
	cin>>m;
	cout<<"請輸入頁面引用次序";
    for(int i=1; i<=n; ++i){ 
        cin>>page[i];
        page_max = max(page_max, page[i]) ;
    } 
   	int lack=LRU(); 
    float w;
	w=(float)lack/n; 	
     cout<<"LRU缺頁中斷次數:"<<lack<<endl;
      cout<<"缺頁中斷率"<<w<<endl;
     return 0;
} 

執行結果截圖:

後續兩個演算法實驗並未完成,因此給出老師所給的程式碼作為參考

NRU演算法
void NRU (int ref_len, int vsize){
    int i, find, miss, rep, least;
    int flag[MEM_FRAME_SIZE];                   //訪問位
    float rate = 0;

    printf("-------(4) NRU頁面缺頁演算法-------\n");

    miss = 0;
    ini_mem ();                   //初始化記憶體迴圈頁框
    for (i = 0; i < MEM_FRAME_SIZE; i ++)         //初始化記憶體迴圈頁框的訪問位
       flag[i] = 0;
    rep = 0;
    for (i = 0; i < ref_len; i ++) {
       find = search (MEM_FRAME_SIZE, reference[i]);
       if (find != FALSE && mem_frame[find] == -1) {    //記憶體迴圈頁框未滿
          miss ++;
          mem_frame[find] = reference[i];//頁面缺頁
          printf("頁框未滿,置入頁面%d\n",reference[i]);
          flag[rep] = 1; // 置訪問為1
          rep = (rep+1) % MEM_FRAME_SIZE;  //頁面不在記憶體中,掃描指標下移
       }
       else if (find == FALSE) {          //記憶體迴圈頁框已滿且擬置入頁面不在頁框中
          miss ++;
          while (flag[rep] != 0) {       //最近被使用過,給第二次機會
             flag[rep] = 0;
             rep = (rep+1) % MEM_FRAME_SIZE;
          }
          printf("換出頁面%d,換入頁面%d\n",mem_frame[rep],reference[i]);
          mem_frame[rep] = reference[i];//頁面缺頁
          flag[rep] = 1; // 置訪問為1
          rep = (rep+1) % MEM_FRAME_SIZE;  //頁面不在記憶體中,掃描指標下移
       }
       else{//在記憶體迴圈頁框中找到擬置入頁面
          printf("記憶體頁框中存在頁面%d,無需置入\n",reference[i]);
          flag[find] = 1; //頁面的記憶體中,掃描指標不動
       }
    }
    rate = (float)miss/(float)ref_len;          //計算頁面缺頁率
    printf("-----NRU頁面缺頁率為:%d/%d=%.2f-----\n\n",miss,ref_len,rate);
}

LFU演算法
void LFU (int ref_len, int vsize){
    int i, j, find, miss, rep, least;
    int count[MEM_FRAME_SIZE];            //計數器:記錄記憶體頁框中頁面的使用頻率
    float rate = 0;

    printf("-------(5) LFU頁面缺頁演算法-------\n");

    miss = 0;
    ini_mem ();                          //初始化記憶體頁框
    for (i = 0; i < MEM_FRAME_SIZE; i ++)         //初始化記憶體頁框中頁面的使用頻率
        count[i] = 0;
    for (i = 0; i < ref_len; i ++) {
        find = search (MEM_FRAME_SIZE, reference[i]);
        if (find != FALSE && mem_frame[find] == -1) {     //記憶體頁框未滿
           miss ++;
           mem_frame[find] = reference[i];//頁面缺頁
           printf("頁框未滿,置入頁面%d\n",reference[i]);
        }
        else if (find == FALSE) {       //記憶體頁框已滿且擬置入頁面不在頁框中
           miss ++;
           least = count[0];
           rep = 0;
           for (j = 1; j < MEM_FRAME_SIZE; j ++) {//選擇記憶體頁框中使用頻率最小的頁面
              if (count[j] < least) {
                 least = count[j];
                 rep = j;
              }
           }
           printf("換出頁面%d,換入頁面%d\n",mem_frame[rep],reference[i]);
           mem_frame[rep] = reference[i];//頁面缺頁
           count[rep] = 0;
        }
        else{//在記憶體頁框中找到擬置入頁面
           printf("記憶體頁框中存在頁面%d,無需置入\n",reference[i]);
           count[find] ++;
        }
        if ((i+1) % 4== 0) {    //沒有移位暫存器,用計數器定期衰減模擬移位,如果把4改成10,缺頁率結果又如何?
           for (j = 0; j < MEM_FRAME_SIZE; j ++)
              count[j] /= 2; //移位
        }
    }
    rate = (float)miss/(float)ref_len;          //計算頁面缺頁率
    printf("-----LFU頁面缺頁率為:%d/%d=%.2f-----\n\n",miss,ref_len,rate);
}

OPT、FIFO、LRU、NRU和LFU頁面置換演算法優缺點分析

本次實驗有一定的難度,尤其是後面兩個演算法的思想和如何實現,後續有時間還要再研究