LRU算法

2023-11-08

http://blog.csdn.net/Ackarlix/article/details/1759793

http://www.cnblogs.com/changweihua/archive/2012/05/13/2497903.html

文章一

什么是LRU算法? LRU是Least Recently Used的缩写,即最近最少使用页面置换算法,是为虚拟页式存储管理服务的。
关于操作系统的内存管理,如何节省利用容量不大的内存为最多的进程提供资源,一直是研究的重要方向。而内存的虚拟存储管理,是现在最通用,最成功的方式——在内存有限的情况下,扩展一部分外存作为虚拟内存,真正的内存只存储当前运行时所用得到信息。这无疑极大地扩充了内存的功能,极大地提高了计算机的并发度。虚拟页式存储管理,则是将进程所需空间划分为多个页面,内存中只存放当前所需页面,其余页面放入外存的管理方式。
然而,有利就有弊,虚拟页式存储管理减少了进程所需的内存空间,却也带来了运行时间变长这一缺点:进程运行过程中,不可避免地要把在外存中存放的一些信息和内存中已有的进行交换,由于外存的低速,这一步骤所花费的时间不可忽略。因而,采取尽量好的算法以减少读取外存的次数,也是相当有意义的事情。
对于虚拟页式存储,内外存信息的替换是以页面为单位进行的——当需要一个放在外存的页面时,把它调入内存,同时为了保持原有空间的大小,还要把一个内存中页面调出至外存。自然,这种调动越少,进程执行的效率也就越高。那么,把哪个页面调出去可以达到调动尽量少的目的?我们需要一个算法。
自然,达到这样一种情形的算法是最理想的了——每次调换出的页面是所有内存页面中最迟将被使用的——这可以最大限度的推迟页面调换,这种算法,被称为理想页面置换算法。可惜的是,这种算法是无法实现的。
为了尽量减少与理想算法的差距,产生了各种精妙的算法,最近最少使用页面置换算法便是其中一个。LRU算法的提出,是基于这样一个事实:在前面几条指令中使用频繁的页面很可能在后面的几条指令中频繁使用。反过来说,已经很久没有使用的页面很可能在未来较长的一段时间内不会被用到。这个,就是著名的局部性原理——比内存速度还要快的cache,也是基于同样的原理运行的。因此,我们只需要在每次调换时,找到最近最少使用的那个页面调出内存。这就是LRU算法的全部内容。
如何用具体的数据结构来实现这个算法?
首先,最容易想到,也最简单的方法:计时法。给页表中的每一页增加一个域,专门用来存放计时标志,用来记录该页面自上次被访问以来所经历的时间。页面每被访问一次,计时清0。要装入新页时,从内存的页面中选出时间最长的一页,调出,同时把各页的计时标志全部清0,重新开始计时。
计时法可以稍作改变,成为计数法:页面被访问,计数标志清0,其余所有内存页面计数器加1;要装入新页时,选出计数最大的一页调出,同时所有计数器清0。
这两种方法确实很简单,但运行效率却不尽如人意。每个时刻,或是每调用一个页面,就需要对内存中所有页面的访问情况进行记录和更新,麻烦且开销相当大。
另一种实现的方法:链表法。
操作系统为每个进程维护一条链表,链表的每个结点记录一张页面的地址。调用一次页面,则把该页面的结点从链中取出,放到链尾;要装入新页,则把链头的页面调出,同时生成调入页面的结点,放到链尾。
链表法可看作简单计时/计数法的改良,维护一个链表,自然要比维护所有页面标志要简单和轻松。可是,这并没有在数量级上改变算法的时间复杂度,每调用一个页面,都要在链表中搜寻对应结点并放至链尾的工作量并不算小。
 
以上是单纯使用软件实现的算法。不过,如果能有特殊的硬件帮忙,我们可以有更有效率的算法。
首先,如果硬件有一个64位的计数器,每条指令执行完后自动加1。在每个页表项里添加一个域,用于存放计数器的值。进程运行,每次访问页面的时候,都把计数器的值保存在被访问页面的页表项中。一旦发生缺页,操作系统检查页表中所有的计数器的值以找出最小的一个,那这一页就是最久未使用的页面,调出即可。
其次,另外一个矩阵算法:在一个有n个页框的机器中,LRU硬件可以维持一个n*n的矩阵,开始时所有位都是0。访问到第k页时,硬件把k行的位全设为1,之后再把k列的位置设为0。容易证明,在任意时候,二进制值最小的行即为最久未使用的页面,当调换页面时,将其调出。
以上的两种算法,无疑都要比纯粹的软件算法方便且快捷。每次页面访问之后的操作——保存计数器值和设置k行k列的值,时间复杂度都是O(1)量级,与纯软件算法不可同日而语。
那是否软件算法就毫无用处?当然不是,硬件算法有它致命的缺陷,那就是需要硬件的支持才能运行。如果机器上恰好有所需硬件,那无疑是再好不过;反之,若机器上没有这种硬件条件,我们也只能无奈地抛弃硬件算法,转而选取相对麻烦的软件算法了。
最后,让我们来谈论一下LRU算法。首先,这是一个相当好的算法,它是理想算法很好的近似。在计算机系统中应用广泛的局部性原理给它打造了坚实的理论基础,而在实际运用中,这一算法也被证明拥有极高的性能。在大规模的程序运行中,它产生的缺页中断次数已很接近理想算法。或许我们还能找到更好的算法,但我想,得到的收益与付出的代价恐怕就不成比例了。当然,LRU算法的缺点在于实现方法的不足——效率高的硬件算法通常在大多数机器上无法运行,而软件算法明显有太多的开销。与之相对的,FIFO算法,和与LRU相似的NRU算法,性能尽管不是最好,却更容易实现。所以,找到一个优秀的算法来实现LRU,就是一个非常有意义的问题。

文章二

#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <time.h>
  
 
#define Bsize 3
#define Psize 20
 
struct pageInfor
{
     int content; //页面号
     int timer; //被访问标记
};
 
class LRU
{
     public :
         LRU( int qstring[]);
         int findSpace( void ); //查找是否有空闲内存
         int findExist( int curpage); //查找内存中是否有该页面
         int findReplace( void ); //查找应予置换的页面
         void display( void ); //显示
         int  LRUpro( void ); //LRU算法
         void BlockClear( void ); //BLOCK恢复
         pageInfor * block; //物理块
         pageInfor * page; //页面号串
};
 
LRU::LRU( int qstring[])
{
     int i;
     block = new pageInfor[Bsize];
     for (i=0; i<Bsize; i++)
     {
         block[i].content = -1;
         block[i].timer = 0;
     }
 
     page = new pageInfor[Psize];
     for (i=0; i<Psize; i++)
     {
         page[i].content = qstring[i];
         page[i].timer = 0;
     }
}
 
 
int LRU::findSpace( void )
{
     for ( int i=0; i<Bsize; i++)
         if (block[i].content == -1)
             return i; //找到空闲内存,返回BLOCK中位置
     return -1;
}
 
int LRU::findExist( int curpage)
{
 
     for ( int i=0; i<Bsize; i++)
         if (block[i].content == page[curpage].content)
             return i; //找到内存中有该页面,返回BLOCK中位置
     return -1;
}
 
int LRU::findReplace( void )
{
     int pos = 0;
 
     for ( int i=0; i<Bsize; i++)
     if (block[i].timer >= block[pos].timer)
         pos = i; //找到应予置换页面,返回BLOCK中位置
     return pos;
}
 
void LRU::display( void )
{
     for ( int i=0; i<Bsize; i++)
     if (block[i].content != -1)
         cout<<block[i].content<< " " ;
     cout<<endl;
}
 
void LRU::BlockClear( void )
{
     for ( int i=0; i<Bsize; i++)
     {
         block[i].content = -1;
         block[i].timer = 0;
     }
}
 
 
int LRU::LRUpro( void )
{
     int exist,space,position ;
     int noscarBsize=0;
 
     for ( int i=0; i<Psize; i++)
     {
         exist = findExist(i);
         if (exist != -1)
         {
             noscarBsize++;
             cout<< "不缺页" <<endl;
             block[exist].timer = -1; //恢复存在的并刚访问过的BLOCK中页面TIMER为-1
         }
         else
         {
             space = findSpace();
             if (space != -1)
             {
                 block[space] = page[i];
                 display();
             }
             else
             {
                 position = findReplace();
                 block[position] = page[i]; 
                 display();
             }
         }
         for ( int j=0; j<Bsize; j++)
             block[j].timer++;
     }
     return noscarBsize;
}
 
/*在linux下用gcc编译时,使用gcc lru3.cpp -lstdc++*/
 
 
int main( void )
{
     cout<< "|----------页 面 置 换算法----------|" <<endl;
     cout<< "|---please seect:---|" <<endl;
     cout<< "|-----1:LRU--------|" <<endl;
     cout<< "|-------0 :exit------|" <<endl;
     cout<< "|-------------------------------------|" <<endl;
  
     int select;
     int i,scarBsize=0;
     float f;
     int qstring[20];
  
     while (select)
     {
         cin>>select;
         switch (select)
         {
             case 0:
                 break ;
             case 1:
             {
                 
                 cout<< "the amount of page block is 3:" <<endl;
                 cout<< "produce the sequence of 20 length randomly:" <<endl ;
                 srand ((unsigned) time (NULL));
                 for (i=0;i<Psize;i++)
                 {
                     if (!(i%10))
                         cout<<endl;
                         qstring[i]= rand () % 8;
                         cout<< "*" <<qstring[i];
                 }
                 cout<<endl;
                 LRU test(qstring);
                 cout<< "the result of LRU algorithm is" <<endl;
                 scarBsize=20-test.LRUpro();
                 cout<< "the amout of scarpage is" <<scarBsize<<endl;
                 f=scarBsize/20.0;
                 cout<< "the ratio of the  is" <<f<<endl;
                 test.BlockClear();
                 cout<< "----------------------" <<endl;
                 break ;
             }  
             default :
                 cout<< "请输入正确功能号" <<endl;
                 break ;
         }
     }
     return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LRU算法 的相关文章

  • 哈希表(散列表)原理详解

    什么是哈希表 哈希表 Hash table 也叫散列表 是根据关键码值 Key value 而直接进行访问的数据结构 也就是说 它通过把关键码值映射到表中一个位置来访问记录 以加快查找的速度 这个映射函数叫做散列函数 存放记录的数组叫做散列
  • 华中科技大学操作系统实验课 实验四

    一 实验目的 1 理解设备是文件的概念 2 掌握Linux模块 驱动的概念和编程流程 3 Windows Linux下掌握文件读写基本操作 二 实验内容 1 编写一个Linux内核模块 并完成模块的安装 卸载等操作 2 编写Linux驱动程
  • MySQL多表查询(8.0)

    文章目录 多表查询 1 多表关系 1 1 一对多 1 2 多对多 1 3 一对一 2 多表查询概述 2 1 数据准备 2 2 概述 2 3 分类 3 内连接 4 外连接 5 自连接 5 1 自连接查询 5 2 联合查询 6 子查询 6 1

随机推荐

  • chatGLM-Windows环境安装

    Windows系统下环境安装 一 概要 不同安装方式 安装python 安装Nvidia驱动 安装cuda与cuddn 安装PyTorch与TensorFlow 二 安装文件 百度网盘链接 https pan baidu com s 1lb
  • Prometheus部分监控项

    Metrics Chinese explanation English explanation node arp entries device的ARP表项 HELP node arp entries ARP entries by devic
  • Kaldi 入门详解

    train mono sh 是音素训练脚本 下面详细介绍各个功能 这部分是训练用参数 调用mono sh时可以通过 name value的方式改变这些参数 nj 4 并行个数 cmd run pl 处理程序 scale opts trans
  • 已知年月日利用公式求星期几模板

    在本文中 我们将使用C语言实现基于已知的年月日计算星期几的公式 这个公式被称为 蔡勒公式 Zeller s Congruence 是一种快速求解星期几的方法 代码分析 首先 我们需要对月份进行调整 如果月份小于3 即1月或2月 则将其视为上
  • 12个医学公共数据库

    01 NCDB 网址 https www facs org quality programs cancer ncdb 美国国家癌症数据库 National Cancer Database NCDB 是经国家认证的 由美国外科医师学会和美国癌
  • DBA_Oracle Table Partition表分区概念汇总(概念)

    一 摘要 有关表分区的一些维护性操作 注 分区根据具体情况选择 表分区有以下优点 1 数据查询 数据被存储到多个文件上 减少了I O负载 查询速度提高 2 数据修剪 保存历史数据非常的理想 3 备份 将大表的数据分成多个文件 方便备份和恢复
  • MySQL5.7保姆级安装教程

    环境 Linux版本 Mysql版本 待安装 CentOS 7 5 7 1 配置YUM源 在MySQL官网中下载YUM源rpm安装包 http dev mysql com downloads repo yum 目前MySQL官网下载的MyS
  • C++ 的string类学习

    一 string类型变量构造赋值方法 1 构造 1 用等号直接赋值S0 2 定义一个空白变量S1 3 定义一个新变量S2 内容完全等于S0 4 定义一个新变量S3 内容是S0从第八个字符开始的三个字符 5 定义一个新变量S4 用括号赋值 和
  • Python并发编程之线程池/进程池

    转载 http python jobbole com 87272 引言 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程 多进程代码 但是当项目达到一定的规模 频繁创建 销毁进程或者线程是
  • 任意宽度灰度BMP图像读写 V1

    一般BMP图像读写程序只能正确读写宽度为4的倍数的图像 而在图像处理领域所用到的图像宽度不一定满足4的倍数 我在一般BMP图像读写程序基础上进行了改进 使得程序可以读写任意宽度的灰度BMP图像 特分享给大家 希望能够给大家带来帮助 头文件
  • mysql版本5.5.*升级为5.7.*,遇到的问题和解决方法都来看看吧,最终升级成功~

    背景 由于项目比较老 用的数据库版本也是相当低 现在业务需求需要做数据同步 使用FlinkCDC的时候报数据库版本低 查询FlinkCDC要求的最低版本后果断升级mysql FlinkCDC对mysql最低版要求如下图 从 2 2 版本开始
  • 大疆云台和华为P30_超全,一篇文章搞清楚大疆Osmo三款产品区别!

    超全 一篇文章搞清楚大疆Osmo三款产品区别 2020 06 06 17 23 07 33点赞 179收藏 13评论 先说结论吧 Mobile 3适合日常用手机作为主力拍摄工具的人群 手机的拍摄能力以及符合你对画面的要求 另外你还可以接受每
  • code runner 中文使用指南

    Code Runner 用法 运行代码 使用快捷键 Ctrl Alt N 按F1然后选择 键入 Run Code 右键单击文本编辑器 然后在编辑器上下文菜单中单击 Run Code 命令 单击编辑器标题菜单中的 Run Code 按钮 单击
  • 车载毫米波雷达信号处理中的模糊问题仿真分析

    车载毫米波雷达信号处理中的模糊问题仿真分析 概述 车载毫米波雷达在现代汽车领域中扮演着重要的角色 用于实现自动驾驶 智能巡航控制和碰撞警报等功能 然而 在车载毫米波雷达信号处理中 存在各种模糊问题 这些问题可能会影响雷达系统的性能和准确性
  • MySQL数据库之DCL命令

    一 DCL命令 GRANT 授予访问权限 REVOKE 撤销访问权限 COMMIT 提交事务处理 ROLLBACK 事务处理回退 SAVEPOINT 设置保存点 LOCK 对数据库的特定部分进行锁定 查看用户权限 SHOW GRANTS F
  • vue学习笔记(三)

    1 vue开发存在SEO问题 前端开发采用vue开发后是单页面 单页面里面 前后端分离 渲染过程是js写的 在js调用接口返回数据之前 页面已经被打开了 实际上就是空白页面 这个时候右键点击查看源代码 实际上是都看不到内容的 对SEO不太有
  • 什么是节点光端机?总线型光端机有哪些优势?

    节点式光端机又称总线型光端机 其准确的定义是采用单 双纤链路式组网形式的图像传输系统 也被称为链路式光端机 那么 节点式光端机具体是什么呢 总线型光端机又有哪些优势呢 接下来我们就跟随飞畅科技的小编一起来详细了解下吧 什么是节点光端机 节点
  • Android动画+自定义Dialog实现闲鱼发布页面动态效果

    先来看一下效果图 一 新建一个项目DialogView 在layout文件夹下创建一个anmi的文件夹用于存放动画资源 1 首先创建进入Dialog和关闭Dialog时候的主题背景动画 进入Dialog时的动画 main go in xml
  • Ubuntu18 安装ssh

    1 安装ssh 在终端输入命令 sudo apt get install openssh server 2 查看SSH服务是否启动 输入命令 sudo ps e grep ssh
  • LRU算法

    http blog csdn net Ackarlix article details 1759793 http www cnblogs com changweihua archive 2012 05 13 2497903 html 文章一