【操作系統】頁面置換算法(最佳置換算法)(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.重復第二步。尋找未被訪問,但是被修改過的頁面。此時一定可以找到。

也就是說,改進型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");
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM