实验七 虚拟存储管理实验

一、实验目的

  1. 通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解。熟悉虚存管理的各种页面淘汰算法
  2. 通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。

二、实验类型
综合性实验。综合高级语言、数据结构、存储管理模型等多方面的知识
三、实验示例

例题

设计一个请求页式存储管理方案。并编写模拟程序实现之。产生一个需要访问的指令地址流。它是一系列需要访问的指令的地址。为不失一般性,你可以适当地(用人工指定地方法或用随机数产生器)生成这个序列,使得
50%的指令是顺序执行的。25%的指令均匀地散布在前地址部分,25%的地址是均匀地散布在后地址部分 为简单起见。页面淘汰算法采用
FIFO页面淘汰算法,并且在淘汰一页时,只将该页在页表中抹去。而不再判断它是否被改写过,也不将它写回到辅存。

具体的做法可以是:
  产生一个需要访问的指令地址流;
  指令合适的页面尺寸(例如以 1K或2K为1页);
指定内存页表的最大长度,并对页表进行初始化;
每访问一个地址时,首先要计算该地址所在的页的页号,然后查页表,判断该页是否在主存——如果该页已在主存,则打印页表情况;如果该页不在主存且页表未满,则调入一页并打印页表情况;如果该页不足主存且页表已满,则按 FIFO页面淘汰算法淘汰一页后调入所需的页,打印页表情况; 逐个地址访问,直到所有地址访问完毕。

存储管理算法的流程图如下:
在这里插入图片描述
四、实验选题

编写并调试完成请求页式存储管理程序。(参考课本P145-149例子)
页面置换算法:最佳置换算法(OPT)、先进先出算法(FIFO)和最近最少用算法(LRU)。
要求打印每个页面置换算法的页面置换变化示意图、缺页中断次数和缺页中断率,以比较各种算法的优缺点。


具体实现:

  1. 头文件,全局变量等
#include <iostream>
#include<fstream>
#include<vector>
using namespace std;

//【约定】作业名不能为0,可以取1~9。

int read[50];  //存取文件读取的作业
int page_length;   //页内作业数,最大不超过9
double page_fault_interrupt = 0;   //记录缺页中断次数

MyLinkedList *the_page = new MyLinkedList();
int total = read_data(0);
  1. 链表类
//一页,容量为page_content
class MyLinkedList {
public:
    struct LinkedNode {
        int val;
        LinkedNode *next;

        LinkedNode(int val) : val(val), next(nullptr) {}
    };

private:
    LinkedNode *dummy_head;
    int size;

public:
    MyLinkedList() {
        //虚拟头节点
        dummy_head = new LinkedNode(0);
        size = 0;
    }

    int get(int index) {
        if (index > size - 1)
            return -1;

        LinkedNode *tmp = dummy_head;
        for (int i = 0; i <= index; i++) {
            tmp = tmp->next;
        }
        return tmp->val;
    }

    void addAtHead(int val) {
        auto *head = new LinkedNode(val);
        head->next = dummy_head->next;
        dummy_head->next = head;
        size++;
    }

    void addAtTail(int val) {
        LinkedNode *last = dummy_head;
        while (last->next != NULL) {
            last = last->next;
        }
        last->next = new LinkedNode(val);
        size++;
    }

    void addAtIndex(int index, int val) {
        LinkedNode *tmp = dummy_head;
        for (int i = 0; i < index; i++) {
            tmp = tmp->next;
        }
        auto *addedNode = new LinkedNode(val);
        if (tmp != nullptr) {
            addedNode->next = tmp->next;
            tmp->next = addedNode;
            size++;
        }
    }

    void deleteAtIndex(int index) {
        LinkedNode *deletedNode = nullptr;
        LinkedNode *tmp = dummy_head;
        for (int i = 0; i < index; i++) {
            tmp = tmp->next;
        }
        if (tmp != nullptr)
            deletedNode = tmp->next;
        if (tmp != nullptr && tmp->next != nullptr) {
            tmp->next = tmp->next->next;
            delete deletedNode;
            size--;
        }
    }

    int find(int val) {      //找到返回index,没有返回-1
        LinkedNode *tmp = dummy_head->next;
        for (int i = 0; i < size; i++) {
            if (tmp->val == val)
                return i;
            tmp = tmp->next;
        }
        return -1;
    }

    int getSize() const {
        return size;
    }

    void Myprint(int break_or_not, int insert) {
        if(break_or_not)
            page_fault_interrupt++;     //更新缺页中断次数
        cout << insert << " -> ";
        LinkedNode *t = dummy_head;
        int i = page_length + 1;
        while (t->next) {
            t = t->next;
            cout << "|" << t->val;
            i--;
        }
        while (i--) {
            cout << "| ";
        }
        if (break_or_not)
            cout << "+";
        cout << endl;
    }
};
  1. 菜单函数
void menu() {
    cout << "************************************************************************" << endl;
    cout << "                                 页面置换算法                      " << endl;
    cout << "                 1. OPT     2. FIFO     3. LRU      4. 退出      " << endl;
    int choose;
    recin:
    cin >> choose;
    if(choose == 1 || choose == 2 || choose == 3) {
        cout << "请输入页内作业数,最大不超过9:";
        cin >> page_length;
    }
    switch (choose) {
        case 1:
            OPT();
            break;
        case 2:
            FIFO();
            break;
        case 3:
            LRU();
            break;
        case 4:
            cout << "程序正常结束,欢迎再次使用。";
            exit(-1);
        default:
            cout << "输入错误,请重新输入。" << endl;
            goto recin;
    }
}
  1. 3个主要的算法(OPT,FIFO,LRU)
void OPT() {
    page_fault_interrupt = 0;   //初始化缺页中断次数
    cout << "OPT算法页面变化示意图:" << endl;
    for (int i = 0; i < total; i++) {
        if (the_page->getSize() < page_length) {      //1. 页未满
            //输出此时页内容
            the_page->Myprint(1, read[i]);

            the_page->addAtTail(read[i]);
        } else if (the_page->find(read[i]) != -1) {     //2. 页满,该页本来就有这个作业,直接调用即可。
            the_page->Myprint(0, read[i]);
        } else {
            //3. 页满,计算作业调用优先级
            auto *tmp = new MyLinkedList;
            //此for循环退出条件:a. 遍历完毕 b. tmp满了
            for (int j = i + 1; j < total; j++) {     //往后找最后(或不会)调用的作业
                if (the_page->find(read[j]) != -1) {       //该作业需要被调用
                    if (tmp->find(read[j]) == -1) {     //之前没有发现它,直接加在尾部就行
                        tmp->addAtTail(read[j]);
                        if (tmp->getSize() == page_length) {      //tmp满了,说明作业找齐了,退出循环
                            break;
                        }
                    }
                }
            }
            int mark;
            if (tmp->getSize() == page_length) {      //1. tmp满了,置换tmp最后一个
                mark = the_page->find(tmp->get(page_length - 1));
                the_page->deleteAtIndex(mark);
            } else {       //2. tmp未满,置换不在tmp的即可
                for (int j = 0; j < page_length; j++) {
                    if (tmp->find(the_page->get(j)) == -1) {    //tmp的作业找不到就被置换
                        the_page->deleteAtIndex(j);
                        mark = j;
                        break;
                    }
                }
            }
            the_page->addAtIndex(mark, read[i]);
            the_page->Myprint(1, read[i]);
            delete (tmp);       //回收tmp,以免重复使用,内存冲突
        }
    }
    //清一下页面,方便其他算法共用the_page
    delete(the_page);
    the_page = new MyLinkedList;
    cout << "该算法一共发生了 " << page_fault_interrupt << " 次页面置换,缺页中断率为 "
         << page_fault_interrupt / total * 100 << "%" << endl;
}

void FIFO(){
    page_fault_interrupt = 0;   //初始化缺页中断次数
    cout << "FIFO算法页面变化示意图:" << endl;
    for (int i = 0; i < total; i++) {
        if (the_page->getSize() < page_length) {      //1. 页未满
            //输出此时页内容
            the_page->addAtTail(read[i]);
            the_page->Myprint(1, read[i]);
        } else if (the_page->find(read[i]) != -1) {     //2. 页满,该页本来就有这个作业,直接调用即可。
            the_page->Myprint(0, read[i]);
        } else {
            //3. 页满,先进先出

            the_page->deleteAtIndex(0);
            the_page->addAtTail(read[i]);
            the_page->Myprint(1, read[i]);
        }
    }
    //清一下页面,方便其他算法共用the_page
    delete(the_page);
    the_page = new MyLinkedList;
    cout << "该算法一共发生了 " << page_fault_interrupt << " 次页面置换,缺页中断率为 "
         << page_fault_interrupt / total * 100 << "%" << endl;
}

void LRU(){
    page_fault_interrupt = 0;   //初始化缺页中断次数
    cout << "LRU算法页面变化示意图:" << endl;
    //【约定】尾部是最新的
    for (int i = 0; i < total; i++) {
        if (the_page->getSize() < page_length) {      //1. 页未满
            //输出此时页内容
            the_page->addAtTail(read[i]);
            the_page->Myprint(1, read[i]);
        } else if (the_page->find(read[i]) != -1) {     //2. 页满,调换一下顺序,将最新的放尾部
            the_page->deleteAtIndex(the_page->find(read[i]));
            the_page->addAtTail(read[i]);
            the_page->Myprint(0, read[i]);
        } else {
            //3. 页满,将最旧的置换成插入的作业
            the_page->deleteAtIndex(0);     //头部是最旧的
            the_page->addAtTail(read[i]);
            the_page->Myprint(1, read[i]);
        }
    }
    //清一下页面,方便其他算法共用the_page
    delete(the_page);
    the_page = new MyLinkedList;
    cout << "该算法一共发生了 " << page_fault_interrupt << " 次页面置换,缺页中断率为 "
        << page_fault_interrupt / total * 100 << "%" << endl;
}
  1. 读取数据
int read_data(int print_or_not) {
    ifstream in("C:\\Users\\Louis\\Desktop\\project\\CLion_files\\exp7\\data.txt");
    if (!in.is_open()) {
        cout << "路径错误或者文件不存在!";
        exit(1);
    }
    char buffer[256];   //读取文件之用
    in.getline(buffer, 100);
    int j = 0;
    if (print_or_not)
        cout << "页面序列为:";
    int sub = 48;   //"0" - 0 = 48
    for (int i = 0; buffer[i] != '.'; i += 3, j++) {
        read[j] = buffer[i] - sub;
        if (print_or_not)
            cout << "  " << read[j];
    }
    cout << endl;
    return j;   //返回作业数目
}
  1. 主函数
int main() {
    read_data(1);
    while(true){
        menu();
    }
}

data.txt

  • 存放位置
    在这里插入图片描述
  • 内容:(本程序以 “, .” 为结束符分割数据值)
7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1, .

结果:

  • OPT算法
    在这里插入图片描述
  • FIFO算法
    在这里插入图片描述
  • LRU算法
    在这里插入图片描述
  • 5
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Caseythekiwi_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值