【随笔系列】C语言实现LRU置换算法

LRU置换算法

  1. LRU 缓存淘汰算法就是一种常用策略。LRU 的全称是 Least Recently Used,也就是说我们认为最近使用过的数据应该是是「有用的」,很久都没用过的数据应该是无用的,内存满了就优先删那些很久没用过的数据。

实验要求

1. 实验描述:

假设系统中有1个进程,其大小总共有n=10页,而操作系统仅分配了m=3个页面的物理内存空间供其运行。用随机函数随机产生包含有k=20个页面的访问序列。

2. 实验输出:

(1)每处理页面访问序列中的1个页面请求时,操作系统分配给该进程的m=3个页面空间的被占用情况;

(2)最后输出命中次数,缺页次数,以及缺页率。

3. 实验要求:

(1)根据参数n=10,m=3, k=20,编程实现LRU页面置换算法,计算缺页率。

简易分析

根据题意,需要实现的算法在整体上分为InitLRUPrint

  1. Init:初始化相关数据结构。

  2. LRU:即实现算法的主体部分。

  3. Print:穿插在上面几个部分之中,根据具体需要设计即可。

Init部分

由于实现起来相对简单,故不做对具体实现的讲解。

void Init(int Seq[], int PageAcc[], int PageArr[]);

LRU部分

这次实验较为简单,不用划分子函数也可快速的进行编程解题。

void LRU(int Seq[], int PageAcc[], int PageArr[]);

Print部分

由于实现起来相对简单,故不做对具体实现的讲解。

void Print_Seq(int Seq[]);
void Print_State(int idx, int PageArr[], bool hit);
void Print_Result(int Hit, int Miss);

整体代码实现

代码量较小,有问题看注释。

#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

#define SequenceLen 20
#define MaxNumPages 10
#define NumAllocatedPages 3

void Init(int Seq[], int PageAcc[], int PageArr[]);
void LRU(int Seq[], int PageAcc[], int PageArr[]);

void Print_Seq(int Seq[]);
void Print_State(int idx, int PageArr[], bool hit);
void Print_Result(int Hit, int Miss);

int main() {
    srand((unsigned)time(NULL));    //刷新随机数种子
    int Sequence[SequenceLen] = {};
    int PageAccessTime[MaxNumPages] = {};
    int PageArray[NumAllocatedPages] = {};

    Init(Sequence, PageAccessTime, PageArray);
    LRU(Sequence, PageAccessTime, PageArray);
    return 0;
}

void Init(int Seq[], int PageAcc[], int PageArr[]) {
    for (int i = 0; i < NumAllocatedPages; i++)
        PageArr[i] = -1;

    for (int i = 0; i < MaxNumPages; i++)
        PageAcc[i] = 0;

    for (int i = 0; i < SequenceLen; i++)
        Seq[i] = rand() % MaxNumPages;

    Print_Seq(Seq);
    return;
}

void LRU(int Seq[], int PageAcc[], int PageArr[]) {
    bool hit = false;
    bool in = false;
    int numHit = 0;
    int numMiss = 0;

    for (int i = 0; i < SequenceLen; i++) {
        if (i == 0)printf("\tSeqID\tWorking Set\n");  //图方便
        
        for (int j = 0; j < NumAllocatedPages; j++) {   //看看能不能装,能装则直接输出状态,不能就进行下一个操作
            if (PageArr[j] == -1) {
                numMiss++;
                PageArr[j] = Seq[i];
                for (int k = 0; k < j; k++) {   //最抽象的一步,将之前已装入工作集的页计时+1
                    PageAcc[PageArr[k]]++;
                }
                in = true;
                break;
            }
        }

        if (!in) {  //不能装的话,又分两种情况:1.新来的工作集里面有,hit;2.新来的工作集里面没有,换掉计时最长的页
            for (int j = 0; j < NumAllocatedPages; j++) {
                if (PageArr[j] == Seq[i]) {
                    hit = true;
                    numHit++;

                    for (int k = 0; k < NumAllocatedPages; k++) {   //最抽象的一步,将除hit页之外已装入工作集的页计时+1
                        PageAcc[PageArr[k]]++;
                    }
                    PageAcc[Seq[i]] = 0;    //hit页计时归零
                    break;
                }
            }
            if (!hit) {
                numMiss++;
                int big_idx = PageArr[0];
                for (int j = 0; j < NumAllocatedPages; j++) {   //图方便,快速找到计时最长的页号
                    if (PageAcc[PageArr[j]] > PageAcc[big_idx])big_idx = PageArr[j];
                }
                for (int k = 0; k < NumAllocatedPages; k++) {   //找到相应的页号,换掉它
                    if (PageArr[k] == big_idx) {
                        PageArr[k] = Seq[i];
                        PageAcc[Seq[i]] = 0;    //计时归零
                    }
                    else PageAcc[PageArr[k]]++; //最抽象的一步,将除hit页之外已装入工作集的页计时+1
                }
            }
        }

        Print_State(i + 1, PageArr, hit);
        hit = false;    //重置
        in = false;
    }
    Print_Result(numHit, numMiss);
    return;
}

void Print_Seq(int Seq[]) {
    printf("Page sequence:");
    for (int i = 0; i < SequenceLen; i++) {
        printf("%d ", Seq[i]);
    }
    printf("\n");
    return;
}

void Print_State(int idx, int PageArr[], bool hit) {
    printf("\t%d\t",idx);
    for (int i = 0; i < NumAllocatedPages; i++) {
        printf("%2d ", PageArr[i]);
    }
    if (hit)printf("  *hit*");

    printf("\n");
    return;
}

void Print_Result(int Hit, int Miss) {
    double rate = double(Miss) / double(SequenceLen);   //强制转换,不然输出有问题
    printf("Hit = %d, Miss = %d\n", Hit, Miss);
    printf("Page fault Rate = %d/%d = %lf\n", Miss, SequenceLen, rate);
    return;
}

结果展示
在这里插入图片描述
在这里插入图片描述

总结及心得

  1. 加急写的,没有什么难点,主要是费时间。
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值