【C语言编程6】LRU替换算法

一、设计思路

LRU替换算法,是在cache的一个组已经被填满的时候,而且在发生miss的情况下,选择最近最不常用的地址来替换为新的地址。
基于基本原理,我们通过c语言模型进行设计实现,当需要访问一个地址的时候,有下面三种情况,成功命中,未命中但是组中的物理块并没有填满,未命中且组中的物理块已经全部被填满。
对于最后一种情况,我们需要对其进行替换。那就需要寻找最近最不常用的地址所在的物理块的位置,所以我们需要一个时间表来记录每个物理块中存储的地址的最近使用时间与当前时间的时间差,在每次访问一个地址之后,我们对时间表中存储的时间更新。找到最近最不常用的地址之后,将其替换为最新的地址。
将LRU替换算法写成了一个函数,在源代码中已经有详细的过程。

#include<stdio.h>
#define N 4 //N-way组相连 
#define Nl 10//输入的要访问的地址的序列长度  

void LRU(int block[],int blockN,int list[],int listN)//LRU替换算法
{
    int rep = 0, miss = 0, i, j, flag;//定义替换次数与失效次数
    int time[blockN];//各个物理块最近一次访问至现在的时间
    for(int i = 0;i < blockN;i++)//初始化 
        time[i] = 0;
 
    for(i = 0;i < listN; i++)
	{   
		for(j = 0; j < blockN; j++) //更新时间记录 
			if(block[j] != -1)
                time[j]++;
        for(j = 0; j < blockN; j++)
            if(block[j] == list[i]) //命中 
			{
                time[j] = 0;
                break;
            }
            else if(block[j] == -1) //未命中但块中为空 
            	break;
		if(j < blockN && block[j] == -1)//未命中且物理块未满,直接存入
		{
            block[j] = list[i];
            time[j] = 0; 
            miss++;
        }
        else if(j == blockN)//需要替换 
		{
            int max = 0;
            for(int k = 0;k < blockN;k++)//寻找最久未访问的地址所在的物理块的位置
			{
                if(time[max] < time[k])
                    max = k;
            }
            block[max] = list[i];
            time[max] = 0;
            miss++;
            rep++;
        }
        
        printf("%d\n",list[i]);
    	for(int m = 0;m < blockN;m++)//显示当前物理块的状态 
		{
        	if(block[m] == -1)
            	break;
        	printf("|%d| ",block[m]);
    	}
    	printf("\n");
    }
    
    printf("失效次数:%d   失效率:%d/%d=%.2f\n", miss, miss, listN, (float)miss/(float)listN);
    printf("替换次数:%d  替换率:%d/%d=%.2f\n", rep, rep, listN, (float)(listN - miss)/(float)listN);
}

int main()
{
	int block[N], list[Nl];//定义的是一个组的N个块 
    for(int i = 0;i < N;i++)//初始化 
    {
		block[i] = -1;
        list[i] = -1;
    }  
    printf("要访问的地址序列:\n");
    for(int i = 0;i < Nl;i++)
        scanf("%d", &list[i]);
	
	printf("%d-way组相联\n", N);
    LRU(block, N, list, Nl);//调用LRU替换算法的函数 

	return 0;
} 

二、实验测试与结果

这里通过三组数据进行了测试,改变了一个组中的物理块的个数,分别为2,3,4个,输入的地址序列长度都是用的10。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里每一行“||”格式表示的是当前物理块中存储的地址。为了方便分析,这里使用的地址输入序列为1,2,3,4,5,5,4,3,2,1。

三、实验分析

首先要说明的一点是,对于这三组的失效次数和替换次数并没有对比意义,因为这个LRU替换策略的模型仅仅使用了一个组,每个组的块数不同也就相当于整个cache的大小不同了,这里仅为了展示数据。
然后因为物理块个数的多少并不会改变这个策略本身,所以我们使用N=3的模型进行分析,分析如下图所示。

四、实验总结

在这里插入图片描述

通过实验结果可以看出来,设计的c语言模型是比较成功的,能够较好的实验LRU替换算法模型的功能。通过本实验,我进一步了解了LRU替换算法,进一步熟悉了cache的替换。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是实现请求分页存储管理页面Optimal、FIFO、LRU置换算法C语言代码,它们都在一个主函数中体现: ```c #include <stdio.h> #define FRAME_NUM 3 // 物理块数 #define PAGE_NUM 12 // 页面数 // 定义页面结构体 struct Page { int id; // 页面号码 int counter; // 计数器 int flag; // 标记是否在内存中 }; // 初始化页面数组 void init_pages(struct Page pages[PAGE_NUM]) { for (int i = 0; i < PAGE_NUM; i++) { pages[i].id = i; pages[i].counter = 0; pages[i].flag = 0; } } // 打印页面数组 void print_pages(struct Page pages[PAGE_NUM]) { for (int i = 0; i < PAGE_NUM; i++) { printf("Page %d: ", pages[i].id); if (pages[i].flag == 1) { printf("in memory\n"); } else { printf("not in memory\n"); } } } // Optimal算法实现 int optimal(struct Page pages[PAGE_NUM], int memory[FRAME_NUM], int current) { int max = -1, index = -1; for (int i = 0; i < FRAME_NUM; i++) { int found = 0; for (int j = current; j < PAGE_NUM; j++) { if (memory[i] == pages[j].id) { found = 1; if (j > max) { max = j; index = i; } break; } } if (found == 0) { index = i; return index; } } return index; } // FIFO算法实现 int fifo(struct Page pages[PAGE_NUM], int memory[FRAME_NUM], int current) { static int index = 0; int temp = memory[index]; memory[index] = pages[current].id; index = (index + 1) % FRAME_NUM; return temp; } // LRU算法实现 int lru(struct Page pages[PAGE_NUM], int memory[FRAME_NUM], int current) { int min = 9999, index = -1; for (int i = 0; i < FRAME_NUM; i++) { if (pages[memory[i]].counter < min) { min = pages[memory[i]].counter; index = i; } } pages[memory[index]].counter = current; return index; } int main() { int requests[PAGE_NUM] = {0, 1, 2, 3, 2, 4, 5, 3, 4, 6, 5, 3}; // 请求序列 struct Page pages[PAGE_NUM]; // 页面数组 int memory[FRAME_NUM] = {-1, -1, -1}; // 内存数组 int page_faults = 0; // 缺页数 // 初始化页面数组 init_pages(pages); // 遍历请求序列 for (int i = 0; i < PAGE_NUM; i++) { int current = requests[i]; // 如果页面不在内存中 if (pages[current].flag == 0) { printf("Page %d is not in memory, page fault occurs\n", current); int index = optimal(pages, memory, i); //int index = fifo(pages, memory, i); //int index = lru(pages, memory, i); memory[index] = current; pages[current].flag = 1; page_faults++; } else { printf("Page %d is already in memory\n", current); } // 打印当前内存中的页面情况 print_pages(pages); printf("\n"); } printf("Total page faults: %d\n", page_faults); return 0; } ``` 在这个程序中,我们定义了一个 `Page` 结构体来表示页面,其中包括页面号码、计数器和标记是否在内存中。我们还定义了三个函数来实现 Optimal、FIFO 和 LRU 算法。在主函数中,我们首先定义了一个请求序列,然后初始化页面数组和内存数组。接着遍历请求序列,如果当前请求的页面不在内存中,我们就使用三种算法中的一种来选择替换页面,并将选中的页面放入内存中。如果当前请求的页面已经在内存中,我们就不需要进行任何操作。最后,我们打印出所有页面的状态以及缺页数。 请注意,在这个程序中,我们只是简单地使用了一个静态的请求序列和一个固定的物理块数。在实际应用中,请求序列和物理块数都是动态变化的,需要根据实际情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逍遥xiaoy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值