操作系统内存管理基础实验

本次实验要模拟三种cache替换算法(FIFO, LRU, OPT),并且给出相应的缺页率。

首先说明一下符号定义:

int array[100]; // 请求访问的内存地址数组,需要依此访问array[0], array[1], ....
int page[100]; // 请求访问的页面数,规定一个页面大小为100,也就是说,page[0]:0-99, 
			   // page[1]:100-199
// 因此,将第i个请求地址映射到对应的页面号的公式:page[i] = array[i]/100+1
int pageSize = 3, size; // 缓存中一共能够存储3个页面,size为请求访问的地址数目
bool bre; // 终端标志,如果缓存中发生缺页,那么bre=true

每种替换算法,采用函数的方式实现。
主函数如下:

int main()
{
    int i, select;
    bool judge = true;
    cout << "输入地址总数和地址序列:" << endl;
    cin >> size;
    for (int i = 0; i < size; i ++)
    {
        cin >> array[i];
        page[i] = array[i] / 100 + 1;
    }
    while(judge) // 一直循环
    {
        cout << "1:FIFO" << endl;
        cout << "2:LRU" << endl;
        cout << "3:OPT" << endl;
        cin >> select; // 输入你想观察的算法编号
        switch(select) // 调用相应的算法求解
        {
            case 1: FIFO(); break;
            case 2: LRU(); break;
            case 3: OPT(); break;
        }
    }
    return 0;
}

每个算法会定义相应的cache中的缓存页队列que,表示已经缓存的页面编号,并且从队首到队尾表示最先到最近访问的页面。

(1)FIFO

void FIFO()
{
    int queye = 1, i;
    cout << "FIFO" << endl;
    queue<int> que;
    // 加载第一个访问的页面
    que.push(page[0]);
    // 一定会发生冷不命中
    bre = true;
    // 打印函数(打印当前访问的页面以及cache中缓存的页面编号)(见下一个代码段)
    print(que, page[0]);
    // 按照输入的顺序依此访问页面
    for (i = 1; i < size; i ++)
    {
    	// isEqual(queue<int> que, int x)函数,判断que中是否有x (见下下个代码段)
    	// 也就是判断cache中是否已经缓存了页面page[i],缓存了返回true,否则返回false
        if(!isEqual(que, page[i])) // 缺页
        {
            bre = true; // 终端标志=true
            if(que.size() < 3) // 如果缓存页数小于3
            //(表示刚刚启动,发生的都是冷不命中,只需要将相应页加载进缓存即可)
            {
                que.push(page[i]);
                queye++;
            }
            else{ // 发生的是冲突不命中,需要替换,这里是FIFO(First In First Out)
                que.pop(); // 将最先加载的的弹出
                // 注意**这里是将最先加载的弹出,而LRU是将最早访问的弹出**
                que.push(page[i]); // push进入队列
                queye++;
            }
            print(que, page[i]);
        }
        else // 命中
        {
            bre = false;
            print(que, page[i]);
        }
        
    }
    double queyelv = (double) queye / (double) size; // 计算缺页率
    cout << "缺页率:" << queyelv << endl;
}
void print(queue<int> que, int p)
{
    printf("调用的页面为:%d", p);
    if(bre) cout << "    产生中断: ";
    else cout << "    不产生中断: ";
    while(que.size())
    {
        cout << que.front() << " ";
        que.pop();
    }
    cout << endl;
}

bool isEqual(queue<int> que, int num)
{
    while(que.size())
    {
        if(que.front() == num)
            return true;
        que.pop();
    }
    return false;
}

(2)LRU(Latest Recently Used)

void LRU()
{
    int queye = 1, i;
    cout << "LRU" << endl;
    queue<int> que;
    que.push(page[0]);
    bre = true;
    print(que, page[0]);
    for (i = 1; i < size; i ++)
    {
        if(!isEqual(que, page[i]))
        {
            bre = true;
            if(que.size() < 3)
            {
                que.push(page[i]);
                queye++;
            }
            else
            {
            	// 不命中,将最早访问的弹出
                que.pop();
                que.push(page[i]);
                queye++;
            }
            print(que, page[i]);
        }
        else // 命中,但是需要更新一下队列,将这个访问页面放到队列末尾,表示最近访问
        {
            bre = false;
            que = LRU_update(que, page[i]); // 更新队列函数(见下一个代码段)
            print(que, page[i]);
        }
    }
    double queyelv = (double) queye / (double) size;
    cout << "缺页率:" << queyelv << endl;
}
queue<int> LRU_update(queue<int> que, int num)
{
    queue<int> que1;
    while(que.size())
    {
        if(que.front() != num)
        {
            que1.push(que.front());
        }
        que.pop();
    }
    que1.push(num);
    return que1;
}

(3)OPT(optimal)

void OPT()
{
    int queye = 1;
    cout << "OPT" << endl;
    queue<int> que;
    que.push(page[0]);
    bre = true;
    print(que, page[0]);
    for (int i = 1; i < size; i ++)
    {
        if(!isEqual(que, page[i]))
        {
            bre = true;
            if(que.size() >= 3)
            {
                int remove_element = select_most_far(i, que); // 找到最优替换页的函数(见下一个代码段)
                que = OPT_update(que, page[i], remove_element); // 更新队列
                print(que, page[i]);
            }
            else
            {
                que.push(page[i]);
                print(que, page[i]);
            }
            queye++;
        }
        else
        {
            bre = false;
            print(que, page[i]);
        }
    }
    double queyelv = (double) queye / (double) size;
    cout << "缺页率:" << queyelv << endl;
}
// 比对缓存中的三个页面在未来的访问顺序中的距离(距离越大,表示未来越晚访问该页面)
// 找到未来最晚访问的已缓存页面,并return页面编号
// index表示目前正在处理哪一个访问
int select_most_far(int index, queue<int> que)
{
    int a = que.front();
    que.pop();
    int b = que.front();
    que.pop();
    int c = que.front();
    int dis1 = 10000000, dis2 = 10000000, dis3 = 10000000, i, max;
    index ++;
    for (int i = index; i < size; i ++)
    {
        if(page[i] == a){
            dis1 = i - index;
            break;
        }
    }
    for (int i = index; i < size; i ++)
    {
        if(page[i] == b){
            dis2 = i - index;
            break;
        }
    }
    for (int i = index; i < size; i ++)
    {
        if(page[i] == c){
            dis3 = i - index;
            break;
        }
    }
    int result;
    if(dis1 > dis2){
        max = dis1;
        result = a;
    }
    else{
        max = dis2;
        result = b;
    }
    if(max > dis3) return result;
    else return c;
}
queue<int> OPT_update(queue<int> que, int insert_element, int remove_element)
{
    queue<int> que1;
    while(que.size())
    {
        if(que.front() != remove_element)
            que1.push(que.front());
        que.pop();
    }
    que1.push(insert_element);
    return que1;
}

下面是完整程序代码:

#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;

int array[100]; // 请求访问的内存地址数组,需要依此访问array[0], array[1], ....
int page[100]; // 请求访问的页面数,规定一个页面大小为100,也就是说,page[0]:0-99, 
			   // page[1]:100-199
// 因此,将第i个请求地址映射到对应的页面号的公式:page[i] = array[i]/100+1
int pageSize = 3, size; // 缓存中一共能够存储3个页面,size为请求访问的地址数目
bool bre; // 终端标志,如果缓存中发生缺页,那么bre=true

// 在
bool isEqual(queue<int> que, int num)
{
    while(que.size())
    {
        if(que.front() == num)
            return true;
        que.pop();
    }
    return false;
}


void print(queue<int> que, int p)
{
    printf("调用的页面为:%d", p);
    if(bre) cout << "    产生中断: ";
    else cout << "    不产生中断: ";
    while(que.size())
    {
        cout << que.front() << " ";
        que.pop();
    }
    cout << endl;
}

// Least Recently used
// make "num" the last element in queue
queue<int> LRU_update(queue<int> que, int num)
{
    queue<int> que1;
    while(que.size())
    {
        if(que.front() != num)
        {
            que1.push(que.front());
        }
        que.pop();
    }
    que1.push(num);
    return que1;
}

// optimal
// delete remove_element
// and push insert_element into the queue(tail)
queue<int> OPT_update(queue<int> que, int insert_element, int remove_element)
{
    queue<int> que1;
    while(que.size())
    {
        if(que.front() != remove_element)
            que1.push(que.front());
        que.pop();
    }
    que1.push(insert_element);
    return que1;
}

// find the remotest one in the requring page array
int select_most_far(int index, queue<int> que)
{
    int a = que.front();
    que.pop();
    int b = que.front();
    que.pop();
    int c = que.front();
    int dis1 = 10000000, dis2 = 10000000, dis3 = 10000000, i, max;
    index ++;
    for (int i = index; i < size; i ++)
    {
        if(page[i] == a){
            dis1 = i - index;
            break;
        }
    }
    for (int i = index; i < size; i ++)
    {
        if(page[i] == b){
            dis2 = i - index;
            break;
        }
    }
    for (int i = index; i < size; i ++)
    {
        if(page[i] == c){
            dis3 = i - index;
            break;
        }
    }
    int result;
    if(dis1 > dis2){
        max = dis1;
        result = a;
    }
    else{
        max = dis2;
        result = b;
    }
    if(max > dis3) return result;
    else return c;
}

void FIFO()
{
    int queye = 1, i;
    cout << "FIFO" << endl;
    queue<int> que;
    que.push(page[0]);
    bre = true;
    print(que, page[0]);
    for (i = 1; i < size; i ++)
    {
        if(!isEqual(que, page[i]))
        {
            bre = true;
            if(que.size() < 3)
            {
                que.push(page[i]);
                queye++;
            }
            else{
                que.pop();
                que.push(page[i]);
                queye++;
            }
            print(que, page[i]);
        }
        else
        {
            bre = false;
            print(que, page[i]);
        }
        
    }
    double queyelv = (double) queye / (double) size;
    cout << "缺页率:" << queyelv << endl;
}

void LRU()
{
    int queye = 1, i;
    cout << "LRU" << endl;
    queue<int> que;
    que.push(page[0]);
    bre = true;
    print(que, page[0]);
    for (i = 1; i < size; i ++)
    {
        if(!isEqual(que, page[i]))
        {
            bre = true;
            if(que.size() < 3)
            {
                que.push(page[i]);
                queye++;
            }
            else
            {
                que.pop();
                que.push(page[i]);
                queye++;
            }
            print(que, page[i]);
        }
        else
        {
            bre = false;
            que = LRU_update(que, page[i]);
            print(que, page[i]);
        }
    }
    double queyelv = (double) queye / (double) size;
    cout << "缺页率:" << queyelv << endl;
}

void OPT()
{
    int queye = 1;
    cout << "OPT" << endl;
    queue<int> que;
    que.push(page[0]);
    bre = true;
    print(que, page[0]);
    for (int i = 1; i < size; i ++)
    {
        if(!isEqual(que, page[i]))
        {
            bre = true;
            if(que.size() >= 3)
            {
                int remove_element = select_most_far(i, que);
                que = OPT_update(que, page[i], remove_element);
                print(que, page[i]);
            }
            else
            {
                que.push(page[i]);
                print(que, page[i]);
            }
            queye++;
        }
        else
        {
            bre = false;
            print(que, page[i]);
        }
    }
    double queyelv = (double) queye / (double) size;
    cout << "缺页率:" << queyelv << endl;
}

int main()
{
    int i, select;
    bool judge = true;
    cout << "输入地址总数和地址序列:" << endl;
    cin >> size;
    for (int i = 0; i < size; i ++)
    {
        cin >> array[i];
        page[i] = array[i] / 100 + 1;
    }
    while(judge)
    {
        cout << "1:FIFO" << endl;
        cout << "2:LRU" << endl;
        cout << "3:OPT" << endl;
        cin >> select;
        switch(select)
        {
            case 1: FIFO(); break;
            case 2: LRU(); break;
            case 3: OPT(); break;
        }
    }
    return 0;
}

效果截图:
输入
FIFO
LRU
OPT

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Victayria

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

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

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

打赏作者

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

抵扣说明:

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

余额充值