BUAA OS 作业:页面置换算法代码实现

BUAA OS 作业:页面置换算法代码实现

题目描述

假设有10个页面,n个页框。页面的访问顺序为0, 9, 8, 4, 4, 3, 6, 5, 1, 5, 0, 2, 1, 1, 1, 1, 8, 8, 5, 3, 9, 8, 9, 9, 6, 1, 8, 4, 6, 4, 3, 7, 1, 3, 2, 9, 8, 6, 2, 9, 2, 7, 2, 7, 8, 4, 2, 3, 0, 1, 9, 4, 7, 1, 5, 9, 1, 7, 3, 4, 3, 7, 1, 0, 3, 5, 9, 9, 4, 9, 6, 1, 7, 5, 9, 4, 9, 7, 3, 6, 7, 7, 4, 5, 3, 5, 3, 1, 5, 6, 1, 1, 9, 6, 6, 4, 0, 9, 4, 3。
当n在[1,10]中取值时,请编写程序实现OPT、LRU、FIFO页面置换算法,并根据页面访问顺序模拟执行,分别计算缺页数量,画出缺页数量随页框数n的变化曲线(3条线)

文件解释

实现页面置换算法部分

|- Header.h:定义一些用到的宏
|- FIFO.cpp:实现FIFO算法
|- LRU.cpp:实现LRU算法
|- Opt.cpp:实现OPT算法(基于给定的页面“未来”访问)
|- Main.cpp:主函数入口

对得到的数据进行处理

|- data.txt:上面主函数生成的数据文件
|- draw.py:绘制变化曲线
|- result.jpg:生成的图像

代码实现与结果

算法部分

Opt.cpp,LRU.cpp,FIFO.cpp之间也有互相重用一些函数

Header.h

#ifndef HEAD
#define HEAD

#define PAGE_NUM 10
#define MAX 99999999
#define MIN(a, b) ((a) < (b) ? (a) : (b))


#endif

FIFO.cpp

#include "Header.h"
extern int pages[];
extern bool isPageInMemory(int page, int* memoryPage, int memoryPageNum);
extern void remove(int* pages, int page, int memoryPageNum);
extern int SIZE;

int FIFOAlgorithm(int pageFrameNum) {
    int pageFault = 0;
    int memoryPageNum = 0;
    int memoryPage[PAGE_NUM];  // 在内存中的页面

    for (int i = 0; i < SIZE; i++) {
        int page = pages[i];
        if (isPageInMemory(page, memoryPage, memoryPageNum)) {  // 页面是否已在内存中
            continue;
        }
        pageFault++;  // 页面不在内存中,发生缺页中断
        if (memoryPageNum < pageFrameNum) {
            // 物理页框没满,不需要换出旧的
            memoryPage[memoryPageNum] = page;
            memoryPageNum++;
        }
        else {
            // 物理页框满了,需要换出
            remove(memoryPage, memoryPage[0], memoryPageNum);
            memoryPage[memoryPageNum - 1] = page;
        }
    }
    return pageFault;
}

LRU.cpp

#include "Header.h"
#include <cstdlib>
extern int pages[];
extern int SIZE;
extern bool isPageInMemory(int page, int* memoryPage, int memoryPageNum);

void remove(int* memoryPage, int page, int memoryPageNum);

int LRUAlgorithm(int pageFrameNum) {
    int pageFault = 0;
    int memoryPageNum = 0;
    int memoryPage[PAGE_NUM];  // 在内存中的页面

    for (int i = 0; i < SIZE; i++) {
        int page = pages[i];
        if (isPageInMemory(page, memoryPage, memoryPageNum)) {  // 页面是否已在内存中
            remove(memoryPage, page, memoryPageNum);
            memoryPage[memoryPageNum - 1] = page;  // pages.append(page) 把它放到队尾
            continue;
        }
        pageFault++;  // 页面不在内存中,发生缺页中断
        if (memoryPageNum < pageFrameNum) {
            // 物理页框没满,不需要换出旧的
            memoryPage[memoryPageNum] = page;
            memoryPageNum++;
        }
        else {
            // 物理页框满了,需要换出
            remove(memoryPage, memoryPage[0], memoryPageNum);
            memoryPage[memoryPageNum - 1] = page;
        }
    }
    return pageFault;
}

void remove(int* memoryPage, int page, int memoryPageNum) {
    int pos = 0;
    for (int i = 0; i < memoryPageNum; i++) {
        if (memoryPage[i] == page) {
            pos = i;
            break;
        }
    }
    for (int i = pos + 1; i < memoryPageNum; i++) {
        memoryPage[i - 1] = memoryPage[i];
    }
}

Opt.cpp

#include "Header.h"
extern int pages[];
extern int SIZE;
bool isPageInMemory(int page, int* memoryPage, int memoryPageNum);
int selectPage(int curIndex, int* memoryPage, int memoryPageNum);
int getPageIndex(int pageToReplace, int* memoryPage);

int OPTAlgorithm(int pageFrameNum) {  // pageFrameNum 页面数量最大值
    int pageFault = 0;  // 缺页中断次数
    int memoryPage[PAGE_NUM];  // 在内存中的页面
    int memoryPageNum = 0;  // 内存中页面数量
    int pageToReplace = 0;  // 准备被替换的页面

    for (int i = 0; i < SIZE; i++) {
        int page = pages[i];
        if (isPageInMemory(page, memoryPage, memoryPageNum)) {  // 页面是否已在内存中
            if (memoryPageNum == pageFrameNum) // 页面满了,需要确定下一个准备替换的页面
                pageToReplace = selectPage(i, memoryPage, memoryPageNum);
            continue;
        }
        pageFault++;  // 页面不在内存中,发生缺页中断
        if (memoryPageNum < pageFrameNum) {
            // 物理页框没满,不需要换出旧的
            memoryPage[memoryPageNum] = page;
            memoryPageNum++;
        }
        else {
            // 物理页框满了,需要换出
            int indexOfPageToReplace = getPageIndex(pageToReplace, memoryPage);
            memoryPage[indexOfPageToReplace] = page;
        }
        if (memoryPageNum == pageFrameNum)
            pageToReplace = selectPage(i, memoryPage, memoryPageNum);
    }
    return pageFault;
}

bool isPageInMemory(int page, int* memoryPage, int memoryPageNum) {
    /* 页面是否在内存中 */
    for (int i = 0; i < memoryPageNum; i++)
        if (memoryPage[i] == page)
            return true;
    return false;
}

int selectPage(int curIndex, int* memoryPage, int memoryPageNum) {
    /* 选择准备被替换的页面:未来最长时间不需要访问 */
    int nextAppear[PAGE_NUM] = {};  // 记录页面下一次出现的位置
    for (int i = 0; i < 10; i++) {
        nextAppear[i] = MAX; // 初始化成最大值s
    }
    for (int i = curIndex + 1; i < SIZE; i++) {
        nextAppear[pages[i]] = MIN(i - curIndex, nextAppear[pages[i]]);  //记录页面下一次(最早)出现位置
    }
    int toBeReplaced = 0;
    bool first = true;
    for (int i = 0; i < PAGE_NUM; i++) {
        if (!isPageInMemory(i, memoryPage, memoryPageNum)) continue;
        // 找到最长时间不需要访问的页面
        if (nextAppear[i] == MAX) return i;  // == MAX: 之后不会访问
        if ((nextAppear[i] > nextAppear[toBeReplaced] || first)) {
            toBeReplaced = i;
            first = false;
        }  
    }
    return toBeReplaced;
}

int getPageIndex(int pageToReplace, int* memoryPage) {
    for (int i = 0; ; i++) {
        if (pageToReplace == memoryPage[i]) return i;
    }
}

Main.cpp

#include <iostream>
#include "Header.h"
using namespace std;

/* used for opt algorithm */
extern int OPTAlgorithm(int pageFrameNum);
extern bool isPageInMemory(int page, int* memoryPage, int memoryPageNum);
extern int selectPage(int curIndex, int memoryPage, int memoryPageNum);
extern int getPageIndex(int pageToReplace, int* memoryPage);
/* used for LRU algorithm */
extern int LRUAlgorithm(int pageFrameNum);
extern void remove(int* pages, int page, int memoryPageNum);
/* used for FIFO algorithm */
extern int FIFOAlgorithm(int pageFrameNum);

int pages[] = { 0, 9, 8, 4, 4, 3, 6, 5, 1, 5, 0, 2, 1, 1, 1, 1, 8, 8, 5, 3,
            9, 8, 9, 9, 6, 1, 8, 4, 6, 4, 3, 7, 1, 3, 2, 9, 8, 6, 2, 9,
            2, 7, 2, 7, 8, 4, 2, 3, 0, 1, 9, 4, 7, 1, 5, 9, 1, 7, 3, 4,
            3, 7, 1, 0, 3, 5, 9, 9, 4, 9, 6, 1, 7, 5, 9, 4, 9, 7, 3, 6,
            7, 7, 4, 5, 3, 5, 3, 1, 5, 6, 1, 1, 9, 6, 6, 4, 0, 9, 4, 3 };
int SIZE = (int)(sizeof(pages) / sizeof(int));

int main(int argc, char** argv) {
    int pageFrameNum = 10;
    int OPTFaults[10];
    int LRUFaults[10];
    int FIFOFaults[10];

    #pragma warning(suppress : 4996)
    freopen("data.txt", "w", stdout);

    for (int i = 0; i < pageFrameNum; i++) {
        OPTFaults[i] = OPTAlgorithm(i + 1);
        LRUFaults[i] = LRUAlgorithm(i + 1);
        FIFOFaults[i] = FIFOAlgorithm(i + 1);
    }
    cout << "algo\t";
    for (int i = 1; i <= PAGE_NUM; i++) {
        cout << i << "\t";
    }
    cout << endl << "OPT\t";
    for (int i = 0; i < PAGE_NUM; i++) {
        cout << OPTFaults[i] << "\t";
    }
    cout << endl << "LRU\t";
    for (int i = 0; i < PAGE_NUM; i++) {
        cout << LRUFaults[i] << "\t";
    }
    cout << endl << "FIFO\t";
    for (int i = 0; i < PAGE_NUM; i++) {
        cout << FIFOFaults[i] << "\t";
    }

    return 0;
}

生成的数据

algo	1	2	3	4	5	6	7	8	9	10	
OPT	90	64	48	37	29	22	16	12	11	10	
LRU	90	79	71	58	52	42	28	17	13	10	
FIFO	90	80	67	59	47	39	30	20	12	10	

数据处理和图像绘制

draw.py

import matplotlib.pyplot as plt

data = open("data.txt", "r", encoding="utf-8")  # 读入数据
readIn = data.readlines()
data.close()

x = readIn[0].strip().split()  # x轴刻度标签
del x[0]
x = list(map(int, x))

y1 = readIn[1].strip().split()  # 第1条折线数据:OPT
del y1[0]
y1 = list(map(int, y1))
y2 = readIn[2].strip().split()  # 第2条折线数据:LRU
del y2[0]
y2 = list(map(int, y2))
y3 = readIn[3].strip().split()  # 第3条折线数据:FIFO
del y3[0]
y3 = list(map(int, y3))

plt.figure(figsize=(12, 6))

plt.plot(x, y1, color='#FF0000', label='OPT', linewidth=1.0)
plt.plot(x, y2, color='#00FF00', label='LRU', linewidth=1.0)
plt.plot(x, y3, color='#0000FF', label='FIFO', linewidth=1.0)

# 添加x轴和y轴标签
plt.xlabel(u'page_frame_num', fontsize=12)
plt.ylabel(u'page_fault', fontsize=12)

# 标题
plt.title(u'Efficiency of Page Replacement Algorithm', fontsize=18)
# 图例
plt.legend(fontsize=12)

# 保存图片
plt.savefig('./result.jpg', bbox_inches='tight')

# 显示图片
plt.show()

posted @ 2022-04-19 11:10  NormalLLer  阅读(205)  评论(0编辑  收藏  举报