操作系統 FIFO算法 LRU算法 OPT算法(C++)

題目

實驗三 請求調頁存儲管理方式的模擬
1.實驗目的
通過對頁面、頁表、地址轉換和頁面置換過程的模擬,加深對請求調頁系統的原理和實現過程的理解。
2.實驗內容
(1)假設每個頁面中可存放10條指令,分配給作業的內存塊數爲4。
(2)用c語言模擬一個作業的執行過程,該作業共有320條指令,即它的地址空間爲32頁,目前它的所有頁都還未調入內存。在模擬過程中,如果所訪問的指令已在內存,則顯示其物理地址,並轉下一條指令。如果所訪問的指令還未裝入內存,則發生缺頁,此時需記錄缺頁的次數,並將相應頁調入內存。如果4個內存塊均已裝入該作業,則需進行頁面置換,最後顯示其物理地址,並轉下一條指令。在所有320指令執行完畢後,請計算並顯示作業運行過程中發生的缺頁率。
(3)置換算法:採用先進先出(FIFO)、最近最久未使用(LRU)和最佳置換(OPT)算法置換算法。
(4)通過隨機數產生一個指令序列,共320條指令。
1)指令的地址按下述原則生成:
① 50%的指令是順序執行的;
② 25%的指令是均勻分佈在前地址部分;
③ 25%的指令是均勻分佈在後地址部分;
具體的實施方法是:
① 在[0,319]的指令地址之間隨機選取一起點m;
② 順序執行一條指令,即執行序號爲m+1的指令;
③ 在前地址[0,m-1]中隨機選取一條指令並執行,該指令的序號爲m1;
④ 順序執行一條指令,其序號爲m1+1的指令;
⑤ 在後地址[m1+2,319]中隨機選取一條指令並執行,該指令的序號爲m2;
⑥ 順序執行一條指令,其序號爲m2+1的指令;
重複上述步驟①~⑥,直到執行320次指令。
2)將指令序列變換爲頁地址流
設頁面大小爲1K, 用戶虛存容量爲32K。在用戶虛存中,按每K存放10條指令排列虛存地址,即320條指令在虛存中的存放方式爲:
第0條~第9條指令爲第0頁(對應虛存地址爲[0,9]);
第10條~第19條指令爲第1頁(對應虛存地址爲[10,19]);
……
……
第310條~第319條指令爲第31頁(對應虛存地址爲[310,319])。
按以上方式,用戶指令可組成32頁。
3.思考
(1)如果增加分配給作業的內存塊數,將會對作業運行過程中的缺頁產生什麼影響?
(2)爲什麼一般情況下,LRU具有比FIFO更好的性能?

首先要注意的是,實驗文檔那個獲取隨機指令的方法非常糟糕,很多種情況會導致程序奔潰或者獲得的指令不在範圍內,需要特判。

FIFO算法

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <time.h>
using namespace std;
int cnt;                ///發生缺頁的次數
const int maxn = 4;     ///內存塊數的數目
const int maxn_n = 320;

typedef struct Node{
    int a[10];
    bool is_empty = true;
}Node;
Node block[maxn];///結構體數組模擬隊列,4個內存塊維護頁面

int head = 0;
int tail = 0;
int instruction[maxn_n];    ///指令

int search(int id){
    for(int i = 0; i < maxn; i++){
        if(!block[i].is_empty){
            for(int j = 0; j < 10; j++){
                if(block[i].a[j] == id){
                    return 0 * printf("已存在,物理地址爲:%d\n", i * 10 + j);
                }
            }
        }
    }
    return -1;
}

void adjust(int id){
    if(tail < maxn){
        block[tail].is_empty = false;
        for(int i = 0; i < 10; i++){
            block[tail].a[i] = id / 10 * 10 + i;

        }
        printf("調入內存後物理地址爲:%d\n", tail * 10 + id % 10);
        tail++;
    }else{
        for(int i = 0; i < 10; i++){
            block[head].a[i] = id / 10 * 10 + i;
        }
        printf("調入內存後物理地址爲:%d\n", head * 10 + id % 10);
        head = (head + 1) % maxn;
    }
}

void solve(int id){
    if(search(id) == -1){
        cnt++;
        adjust(id);
    }
}

int main(){
    srand(int(time(0)));
    int n = 320;
    int cnt_n = 0;
    while(cnt_n < 320){
        int m = rand() % n;
        instruction[cnt_n++] = m + 1;

        if(m == 0)
            continue;
        int m1 = rand() % m;
        instruction[cnt_n++] = m1;
        instruction[cnt_n++] = m1 + 1;

        if(n - m1 - 2 <= 0)
            continue;
        int m2 = rand() % (n - m1 - 2) + m1 + 2;
        instruction[cnt_n++] = m2;
        instruction[cnt_n++] = m2 + 1;
    }
    for(int i = 0; i < 320; i++){
        solve(instruction[i]);
    }
    printf("缺頁次數爲:%d\n", cnt);
    printf("缺頁率爲:%f\n", 1.0 * cnt / 320);
    return 0;
}

LRU算法

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <time.h>
using namespace std;

int cnt;                ///發生缺頁的次數
int now_time;           ///當前時間
const int maxn = 4;     ///內存塊數的數目
const int maxn_n = 320 + 20;

typedef struct Node{
    int id;                 ///塊序號
    int a[10];
    int passage = -1;       ///頁
    int recent_time = -1;   ///上次使用的時間,越大說明越接近現在我們所處的時間
}Node;
Node block[maxn];///結構體數組模擬隊列,4個內存塊維護頁面

int instruction[maxn_n];    ///指令

bool search(int id, int passage){
    for(int i = 0; i < maxn; i++){
        if(block[i].passage == passage){
            block[i].recent_time = now_time;
            printf("已存在,物理地址爲:%d\n", block[i].id * 10 + id % 10);
            return true;
        }
    }
    return false;
}

bool cmp(Node a, Node b){
    return a.recent_time < b.recent_time;///從小到大排序,小的離現在最久遠
}

void adjust(int id, int passage){
    sort(block, block + maxn, cmp);
    for(int i = 0; i < 10; i++){
        block[0].a[i] = id / 10 * 10 + i;
    }
    block[0].passage = passage;
    block[0].recent_time = now_time;
    printf("調入內存後,物理地址爲:%d\n", block[0].id * 10 + id % 10);
}

void solve(int id){
    if(!search(id, id / 10)){///找不到該頁
        cnt++;
        adjust(id, id / 10);
    }
    now_time++;
}

int main(){
    srand(int(time(0)));
    int n = 320, cnt_n = 0;
    while(cnt_n < 320){
        int m = rand() % n;
        instruction[cnt_n++] = m + 1;

        if(m == 0)
            continue;
        int m1 = rand() % m;
        instruction[cnt_n++] = m1;
        instruction[cnt_n++] = m1 + 1;

        if(n - m1 - 2 <= 0)
            continue;
        int m2 = rand() % (n - m1 - 2) + m1 + 2;
        instruction[cnt_n++] = m2;
        instruction[cnt_n++] = m2 + 1;
    }
    for(int i = 0; i < maxn; i++){
        block[i].id = i;
    }
    for(int i = 0; i < n; i++){
        solve(instruction[i]);
    }
    printf("缺頁次數爲:%d\n", cnt);
    printf("缺頁率爲:%f\n", 1.0 * cnt / n);
    return 0;
}

OPT算法

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <time.h>
using namespace std;
int now;
int cnt;                ///發生缺頁的次數
const int maxn = 4;     ///內存塊數的數目
const int maxn_n = 320 + 20;
const int INF = 0x3f3f3f3f;

typedef struct Node{
    int id;                 ///塊序號
    int a[10];
    int passage = -1;       ///頁
    int next_use = INF;     ///這個頁面下次要用到的位置
}Node;
Node block[maxn];///結構體數組模擬隊列,4個內存塊維護頁面

int next_use[maxn];         ///第i條指令所處的頁面下次要使用到的位置
int instruction[maxn_n];    ///指令

bool search(int pos, int id, int passage){
    for(int i = 0; i < maxn; i++){
        if(block[i].passage == passage){
            block[i].next_use = next_use[pos];
            printf("已存在,物理地址爲:%d\n", block[i].id * 10 + id % 10);
            return true;
        }
    }
    return false;
}

bool cmp(Node a, Node b){
    return a.next_use - now > b.next_use - now;///大到小排序,最晚用到的替代掉
}

void adjust(int pos,int id, int passage){
    sort(block, block + maxn, cmp);
    if(block[3].next_use - pos <= 0){
        for(int i = 0; i < 10; i++){
        block[3].a[i] = id / 10 * 10 + i;
        }
        block[3].passage = passage;
        block[3].next_use = next_use[pos];
        printf("調入內存後,物理地址爲:%d\n", block[3].id * 10 + id % 10);
    }
    else
    {
        for(int i = 0; i < 10; i++){
            block[0].a[i] = id / 10 * 10 + i;
        }
        block[0].passage = passage;
        block[0].next_use = next_use[pos];
        printf("調入內存後,物理地址爲:%d\n", block[0].id * 10 + id % 10);
    }
}

void solve(int pos, int id){
    if(!search(pos, id, id / 10)){///找不到該頁
        cnt++;
        adjust(pos, id, id / 10);
    }
}

int main(){
    srand(int(time(0)));
    int n = 320, cnt_n = 0;
    while(cnt_n < 320){
        int m = rand() % n;
        instruction[cnt_n++] = m + 1;

        if(m == 0)
            continue;
        int m1 = rand() % m;
        if(m1 + 1 >= n)
            continue;
        instruction[cnt_n++] = m1;
        instruction[cnt_n++] = m1 + 1;

        if(n - m1 - 2 <= 0)
            continue;
        int m2 = rand() % (n - m1 - 2) + m1 + 2;
        instruction[cnt_n++] = m2;
        instruction[cnt_n++] = m2 + 1;
    }
    //預處理出多久後會再使用
    for(int i = 0; i < n; i++){
        for(int j = i + 1; j <= n; j++){
            if(j == n){
                next_use[i] = INF;
                break;
            }
            if(instruction[i] >= instruction[j] / 10 * 10 && instruction[i] < (instruction[j] / 10 + 1) * 10){
                next_use[i] = j;
                break;
            }
        }
    }
    for(int i = 0; i < maxn; i++){
        block[i].id = i;
    }
    for(int i = 0; i < n; i++){
        now = i;
        solve(i, instruction[i]);
    }
    printf("缺頁次數爲:%d\n", cnt);
    printf("缺頁率爲:%f\n", 1.0 * cnt / n);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章