最近最少使用演算法(LRU)——頁面置換

来源:https://www.cnblogs.com/chiweiming/archive/2018/05/21/9066722.html
-Advertisement-
Play Games

原創 上一篇博客寫了先進先出演算法(FIFO)——頁面置換:http://www.cnblogs.com/chiweiming/p/9058438.html 此篇介紹最近最少使用演算法(LRU)——頁面置換,與上一篇的代碼大同小異,只是用了不同的方法從頁面隊列 中選出需要淘汰出的頁面。 還是辣個慄子: ...


原創


上一篇博客寫了先進先出演算法(FIFO)——頁面置換:http://www.cnblogs.com/chiweiming/p/9058438.html

此篇介紹最近最少使用演算法(LRU)——頁面置換,與上一篇的代碼大同小異,只是用了不同的方法從頁面隊列

中選出需要淘汰出的頁面。(題目闡述看我上一篇博客)

還是辣個慄子:

現記憶體頁面為:  15  31  24  17  18  5  9  26  4  21

部分地址流為:  4  31  24  17  18  26  17  5  5  9  31  18  18  21  15  8

頁面 8 為下一個需要調入進去的頁面,由於記憶體頁面已滿,需要使用LRU調出一個最近未被使用頁面。

尋找淘汰頁面的方式如下:

從頁面 8 往前看,遇到與記憶體頁面中相同的頁面即把它移除(即不淘汰它),等到移除了 max_page-1 個頁面之

後,剩下最後一個未被移除的頁面即是需要淘汰出去的。

在上面例子中,依次將 15 21 18 31 9 5 17 26 24 (已經9個),剩下最後一個 4 即是需要淘汰出去的頁面。

可以用這樣的偽代碼去實現:用一個數組 flag 來備份記憶體頁塊號中的頁面,從 8 往前看,依次將之前的數和數組

里的數比較,若匹配成功,則將數組裡面此位置 -1 ,等到置了 max_page-1 個 -1 後跳出;再從 flag 中篩選出不

是 -1 的值(即要淘汰出的頁面),再拿此值和當前記憶體頁面隊列中的值比較,匹配成功則將此頁面調出去,將頁

面 8 調入。

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define max_page 10    //記憶體頁面數

int Page[320]={0};    //虛擬存儲區,存儲320條指令,32個頁面 
int Page_flu[320]={0};    //存儲320個頁地址流
int count=0;    //計算隨機產生的指令條數
double lack_page=0;    //記錄缺頁數 
int count_page=max_page;     //計算隊列空頁面個數 
int flag[max_page+1]={0};    //存儲記憶體塊中的頁面號 
int ff=0;

struct Memo{    //用結構體存儲記憶體頁面塊
    int num;     //給每個頁面編號,方便將其從隊列中找到並調出
    int a;
    struct Memo *next;
};

int Judge_Page(int value){    //輸入指令,返回指令對面的頁面號 
    return value/10;
}

int scan_queen(struct Memo *hear,int value){    //value代表頁面號,掃描隊列,缺頁返回0,否則返回1
    struct Memo *move;
    move=hear->next;
    while(move!=NULL){
        if(move->a==value){
            return 1;
        }
        move=move->next;
    }
    return 0;
}

void print(struct Memo *hear){    //輸出記憶體頁面
    struct Memo *move;
    move=hear->next;
    printf("當前頁面隊列為: ");
    while(move!=NULL){
        printf("%d ",move->a);
        move=move->next;
    }
    printf("\n");
}

void insert(struct Memo *hear,int value,int ZL,int x){    //將頁面value調入記憶體,ZL為對應指令,x為頁面value在頁地址流中的序號 
    if(count_page>=1){    //記憶體頁面空間充足
        struct Memo *move;
        move=hear->next;
        while(move->a!=-1){
            move=move->next;
        }
        move->a=value;    //將頁面調入
        count_page--;
        printf("頁面 %d 被調入————對應指令為: %d \n",value,ZL);
    }
    else{    //記憶體空間不足,使用LRU選出需調出的頁面後,將頁面value後調入
        struct Memo *move;
        move=hear->next;
        int i=0;
        for(i=1;i<=max_page;i++){
            flag[i]=move->a;    //將記憶體塊中的頁面號放入flag備份 
            move=move->next; 
        }
        int t=0;
        for(t=x-1;t>=0;t--){    //迴圈結束後flag裡面只有一個不為0,把此頁面調出即可
            for(i=max_page;i>=1;i--){
                if(Page_flu[t]==flag[i]){
                    flag[i]=-1;
                    ff++;
                    break;
                }
            }
            if(ff==max_page-1){
                break;
            }
        }
        for(i=1;i<=max_page;i++){    //選出被淘汰出的頁面號
            if(flag[i]!=-1){
                ff=flag[i];    //備份要淘汰出的頁面號 
                break;
            }
        }
        move=hear->next;
        while(move!=NULL){
            if(move->a==ff){
                int j=0;
                printf("前20個地址流為:"); 
                for(j=x-20;j<=x-1;j++){
                    printf("%d ",Page_flu[j]);
                }
                printf("\n");
                printf("頁面 %d 被調出,頁面 %d 被調入----指令為:%d \n",ff,value,ZL);
                move->a=value;    //將頁面插入
                break; 
            }
            move=move->next;
        }
    }
    
    ff=0;
    print(hear);    //調入後輸出記憶體隊列 
}

void LRU(struct Memo *hear){
    int i=0;
    for(i=0;i<=319;i++){    //迴圈掃描頁面
        if( scan_queen(hear,Page_flu[i])==0){    //判斷是否缺頁
            lack_page++;
            insert(hear,Page_flu[i],Page[i],i);    //缺頁將頁面調入記憶體
        }
        else{    //不缺頁
            printf("指令 %d 對應頁面 %d 已在記憶體\n",Page[i],Page_flu[i]);
        }
        //不缺頁無需操作
    }
}

void Pro_Page(){    //形成頁地址流函數 
    int m=0;    //在[0,319]的指令地址之間隨機選取一起點m
    m=rand()%320;
    
    Page[count]=m;
    count++;
    if(count==320){
        return;
    }
    int m_=0;    //在前地址[0,m+1]中隨機選取一條指令並執行
    m_=rand()%(m+1);
    
    Page[count]=m_;
    count++;
    if(count==320){
        return;
    }
    Page[count]=m_+1;
    count++;
    if(count==320){
        return;
    }
    int m__=0;
    m__=(m_+2)+rand()%( 319-(m_+2)+1 );    //在後地址[m_+2,319]的指令地址之間隨機選取一條指令並執行
    Page[count]=m__;
    count++;
    if(count==320){
        return;
    }
    
    Pro_Page();
}

void Flu(){    //將指令轉換為頁地址流
    int i=0;
    for(i=0;i<=319;i++){
        Page_flu[i]=Judge_Page( Page[i] );
    }
}

int main(){
    struct Memo Stu[max_page+1];
    struct Memo *hear;
    hear=&Stu[0];
    //*************************************
    int i=0;
    for(i=0;i<=max_page;i++){    //形成記憶體頁面隊列
        if(i==max_page){
            Stu[i].a=-1;
            Stu[i].next=NULL;
            Stu[i].num=i;
            break;
        }
        Stu[i].next=&Stu[i+1];
        Stu[i].a=-1;
        Stu[i].num=i;
    }
    //*************************************
    srand(time(0));    //放在Pro_Page函數外面
    Pro_Page();    //形成頁地址流
    Flu();    //形成頁地址流 
    /*
    printf("頁地址流:\n");
    for(i=0;i<=319;i++){    //輸出頁地址流
        printf("%d ",Page[i]);
        if(i%3==0 && i!=0){
            printf("\n");
        }
    }
    printf("\n");
    */
    //*************************************
    
    LRU(hear);
    printf("缺頁次數為: %0.0lf\n",lack_page);
    printf("命中率為:%lf\n",1-lack_page/320);
    
    return 0;
}

(部分結果截圖)

08:31:06

2018-05-22


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 在給定上下文的軟體體繫結構中,為瞭解決某些經常出現的問題而形成的通用且可重用的解決方案稱之為架構模式,而常見的體系架構模式主要有以下十種 分層模式 客戶端 伺服器模式 主從設備模式 管道 過濾器模式 代理模式 點對點模式 事件匯流排模式 模型 視圖 控制器模式 黑板模式 解釋器模式 而下麵我將詳 ...
  • 前言 從0到1構建分散式秒殺系統案例的代碼已經全部上傳至碼雲,文章也被分發到各個平臺。其中也收到了不少小伙伴喜歡和反饋,有網友如是說: 說實話,能用上的不多,中小企業都不可能用到,大型企業也不是一個人就能搞起的,大部分人一輩子都用不上,等有這個需要再搞吧。 我的觀點是贊同但不支持,基本上任何事物都是 ...
  • 先來看段代碼 先看一下 String.valueOf() 裡面是怎麼寫的 String.valueOf() 在遇到 null 和 空串的情況下 ,都能正常輸出,所以不拋錯 再來看下 包裝類型 Integer裡面又是如何處理的 這兩個方法裡面都需要先 parseInt( s,10),就是將字元串s先轉 ...
  • 上一篇文章說了 CAS 原理,其中說到了 Atomic 類,他們實現原子操作的機制就依靠了 volatile 的記憶體可見性特性。如果還不瞭解 CAS 和 Atomic ,建議看一下 "我們說的 CAS 自旋鎖是什麼" 併發的三個特性 首先說我們如果要使用 volatile 了,那肯定是在多線程併發的 ...
  • 學Python將近一個月了,第一次寫了兩百多行代碼,一個很簡單的腳本。 員工信息管理系統: 需求: 1.管理員賬戶能夠增加,刪除,修改,查詢員工信息,並且設置管理員賬戶。 2.普通賬戶可以查看所有員工信息,但不能增加,修改,刪除員工信息。 3.可以針對員工信息類型進行模糊查詢,並能記錄搜索出多少條結 ...
  • 狀態模式-State Pattern 在狀態模式(State Pattern)中,類的行為是基於它的狀態改變的。當一個對象的內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類。 State介面 表明狀態, 實體類是根據狀態的變化而發生響應行為的變化的. AngryState類 狀態的一種實現 ...
  • 今天突然有空想起來寫篇隨筆,說說ICE 3.3.0在HP-UX 下的編譯安裝。 ICE3.3版本之後不再支持HP-UX了,所以以後的版本不要試圖在HPUX下安裝了,^_^ 有關3.3.0的版本鏈接 ,包括說明文檔、源碼和安裝包等。由於HPUX使用的安騰架構,所以我們使用源碼編譯,源碼編譯需要依賴第三 ...
  • 2011年1月21日 微信(WeChat) 是騰訊公司於2011年1月21日推出的一個為智能終端提供即時通訊服務的免費應用程式,由張小龍所帶領的騰訊廣州研發中心產品團隊打造 。在互聯網飛速發展的下、民眾的需求下,微信已經更新到2.6.2.31版本,全民微信時代。村口的張大媽,家裡的老父親都知道怎麼使 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...