操作系统 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章