【操做系統】頁面置換算法(最佳置換算法)(C語言實現)

【操做系統】頁面置換算法(最佳置換算法)(C語言實現)

(編碼水平較菜,寫博客也只是爲了我的知識的總結和督促本身學習,若是有錯誤,但願能夠指出)

1.頁面置換算法:

在地址映射過程當中,若在頁面中發現所要訪問的頁面不在內存中,則產生缺頁中斷。當發生缺頁中斷時,若是操做系統內存中沒有空閒頁面,則操做系統必須在內存選擇一個頁面將其移出內存,以便爲即將調入的頁面讓出空間。而用來選擇淘汰哪一頁的規則叫作頁面置換算法。算法

一個好的頁面置換算法,應具備較低的頁面更換頻率。從理論上講,應該保留最近重複訪問的頁面,將之後都再也不訪問或者很長時間內再也不訪問的頁面調出。----百度百科

2.具體的頁面置換算法:

2.1 最佳置換算法:一個進程在內存的若干個頁面中,哪個頁面是將來最長時間內再也不被訪問的,那麼若是發生缺頁中斷時,就將該頁面換出,以便存放後面調入內存中的頁面。

在這裏插入圖片描述

1.這是計算機操做系統(第四版)中的一個例子。系統首先爲進程分配了三個物理塊。上面一排數字是做業號。在轉滿三個物理塊後,要訪問2號做業,2號做業不在內存,因此會發生缺頁中斷,而後系統須要將2號做業調入內存,可是此時物理塊已經裝滿。
2.依據最佳置換算法,會將7號頁換出(0號頁在2號頁後第1個就會被訪問,1號頁在2號頁後第10個會被訪問,7號頁在2號頁後第14個會被訪問,7號頁在已經裝入內存的做業中是將來最長時間不會被訪問的,因此換出7號頁)。
3.後面依次類推。

2.2 先進先出算法:若是發生缺頁中斷,須要換出一個頁面的時候,老是選擇最先進入內存的頁面,即選擇在內存中駐留時間最久的頁面進行換出。

在這裏插入圖片描述
有點不清楚。。。。。就是每次發生缺頁就將最先進入內存的頁面換出,而後將剛調入的頁面換入該物理塊。數組

2.3 最近最久未使用(LRU)置換算法:LRU算法是缺頁中斷髮生時選擇最久未使用的頁面進行換出。

在這裏插入圖片描述
這個算法其實也很好判斷。分享一個小技巧。內存分配了k個物理塊,發生缺頁中斷將要往內存調入某個頁面的時候,在該頁面往前面數K個物理塊最前面的那個就會是要換出的,由於該頁面最長時間未被使用過。(可能前面會有重複的頁面,有幾個重複的頁面就再往前面多數幾個)
例如:裝入7,0,1,以後訪問2號頁面的時候會發生缺頁中斷。此時物理塊有三個,2號頁面前面有三個頁面,最前面的是7號頁面因此將7號頁面換出。學習

2.4Clock置換算法(沒有動圖,不太形象,就不舉例子了,若是不太清楚,能夠私信我。)

2.4.1簡單的Clock置換算法:將全部頁面經過連接指針鏈接成一個循環隊列。而後須要爲每個頁面設置一個訪問位。當某頁被訪問的時候,將訪問位置爲1。選擇頁面換出的時候,須要檢查頁面的訪問位。若是是0,就將頁面換出,若是是1,那麼就將訪問位置爲0。

簡單的Clock算法最多訪問兩輪:
最壞狀況就是全部的頁面訪問位都是1,訪問1輪以後,所有訪問位都會被置爲0,那麼確定會找到一個頁面換出。編碼

2.42改進型Clock算法:將全部頁面經過連接指針鏈接成一個循環隊列。而後須要爲每個頁面設置一個訪問位和一個修改位。訪問位爲0表示未訪問過,爲1表示訪問過。修改位爲0表示未修改過,爲1表示修改過。

此時頁面會有四種狀況:
1.未被訪問,未被修改,最佳淘汰。
2.未被訪問,被修改過。
3.被訪問過,未被修改。
4.被訪問過,被修改過。操作系統

換出頁面的時候:

1.尋找未被訪問,未被修改的頁面,不修改訪問位。找到則換出,找不到進行第二步。
2.尋找未被訪問,可是被修改過的頁面。此時,每次掃描頁面的時候,將全部訪問位置爲0。找到就返回,找不到就進行第三步。
3.重複第一次步驟,尋找未被訪問,未被修改的頁面,不修改訪問位。找到則換出,找不到進行第四步。
4.重複第二步。尋找未被訪問,可是被修改過的頁面。此時必定能夠找到。3d

也就是說,改進型Clock算法,最多掃描四輪隊列。由於最壞的狀況就是所有頁面的訪問位和修改位都是1的狀況。在通過第二輪掃描以後頁面的訪問位已經都是0。因此第四輪必定能夠找到一個頁面換出。

3.最佳置換算法運行截圖:

首先是前面三個裝入,就省略掉了直接從第四次以後開始打印的。
在這裏插入圖片描述指針

4.代碼

#include<stdio.h>
#include<stdlib.h>

#define MAX 20   // 定義做業序列的最大長度
#define num_alloacte 3       //內存分配給進程的物理塊數  , 也就是同一時刻最多有幾個頁面能夠在內存中

int work_list [MAX];        //存儲做業序列
int num;        //存儲要輸入的序列的長度

int memory_alloacte [num_alloacte];   // 如今在進程中的頁面序列

int current; // 記錄已經分配的做業的下標

void input(){       //初始化做業序列  , 以及內存分配給進程的物理塊數
    printf("請輸入做業的個數:");
    scanf("%d",&num);
    if (num > MAX)  {
        printf("序列過長");
        return;    
    }
    printf("請輸入做業序列:\n");
    for(int i = 0;i < num; i ++){
        scanf("%d",&work_list[i]);
    }
    for(int i = 0;i < MAX ; i ++){
        memory_alloacte[i] = -1;
    }
    for(int i = 0;i < num_alloacte;i ++){
        memory_alloacte[i] = work_list[i];
        current = i;
    }
}

void print(int* work_list,int* memory_alloacte ){
    printf("\t如今進程中的頁面序列:");
    for(int i = 0; i < num_alloacte; i ++){
        printf("%3d\t",*(memory_alloacte+i));
    }
    printf("\t\t當前剩餘的做業序列:");
    for(int i = current+1; i < num;i ++){
        printf("%3d",*(work_list+i));
    }
    printf("\n");
}

int judge(){
    int temp [num_alloacte];            //賦值一個臨時變量 記錄此時物理框中的做業號
    int count = num_alloacte;           //記錄臨時變量物理框中還剩下的個數
    for(int i = 0;i < num_alloacte; i ++){
        temp[i] = memory_alloacte[i];   
    }   
    int cur = current + 1;
    while (cur < num)
    {
       for (int i = 0; i < num_alloacte; i++)
       {
           if(work_list[cur] == temp[i]){       //若是剩下的工做序列中 現有內存中的做業還會調用的話, 就將其的值置爲  -1    
               if(count == 1){              //此時內存中剩下的那個做業號確定是最長時間沒有調用過的,後者是之後不再會調用
                   return i;
               }
               temp[i] = -1;
               count --;
               break;
           }
       }
       cur ++;
    }
    //此時再來遍歷這個 臨時的物理塊中做業號的  數組  ,  若是他的值不是  -1,就說明後面須要調用的做業中再也沒有這個做業了,因此 就能夠直接返回。  
    for(int i = 0;i < num_alloacte;i ++){
        if(temp[i] != -1){
            return i;
        }
        else
        {
            continue;
        }
        
    }
    return 0;
}

void change(){
    int index;
    int flag = 0;
    for (int i = current + 1; i < num; i++)
    {   
    
        for (int j = 0; j < num_alloacte; j++)          //來判斷下一個做業是否已經在內存中
        {
            if(work_list[i] == memory_alloacte[j]){
                flag = 1;                       //是的話讓標誌位置爲1
                break;
            }
        }
        if(flag == 0){                          //說明不在內存中,會出現頁面中斷。須要進行換頁。
            index = judge();
            if(memory_alloacte[index] != work_list[i]){
                memory_alloacte[index] = work_list[i];
            }
            current ++;
            print(work_list,memory_alloacte);
            
        }
        else
        {
            flag = 0;
            current ++;
            print(work_list,memory_alloacte);
            continue;
        }
        
    }
}
int main(){

    input();

    change();

    system("pause");
}
相關文章
相關標籤/搜索