LRU页面置换

原理

LRU

LRU是一种页面置换算法,在对于内存中但是又不用的数据块,叫做LRU,操作系统会根据那些数据属于LRU而将其移出内存而腾出空间来加载另外的数据
LRU算法:最近最少使用,简单来说就是将数据块中,每次使用过的数据放在数据块的最前端,然后将存在的时间最长的,也就是数据块的末端的数据剔除掉这就是LRU算法
如果进程被调度,该进程需要使用的外存页(数据)不存在于数据块中,这个现象就叫做缺页。如果这个数据此时不在,就会将这个数据从加入到数据块首部
数据块插入与剔除:每次有新数据到来时,会将其放入数据块首部,当数据每次被访问时,将这个数据插入数据块的首部如果数据块满了,每次新进的数据都会将数据块尾部的数据挤出数据块

为什么要使用LRU

关于操作系统内存管理,如何节省利用容量不大的内存多的进程提供资源。而内存的虚拟存储管理是现在最通用,最成功的方式。在内存有限的情况下,扩展一部分外存作为虚拟内存,真正的内存只存储当前运行时所用到的信息,极大的扩充了内存的功能,极大提高计算机的并发度,虚拟页式存储管理,则是将进程所需空间划分为多个页面,内存中只存放当前所需页面,将其余页面放入外存的管理方式
虚拟页式存储管理增加了进程所需的内存空间,却也带来了运行时间变长这一缺点,运行过程中,需要将外存中存放的信息和内存中已有的进行交换,由于外存的低速,影响了运行时间因此,应当采取尽量好的算法以减少读取外存的次数
对于虚拟页式存储,内外存信息替换是以页面为单位进行的,当需要一个外存中的页面是 将它调入内存,同时为了保持原有空间大小,我们需要不断地剔除掉一些存页面。数据块大小有限,因此我们需要每次调用外存数据时,都能准确的命中。这时就需要一个较好的页面管理算法。

实现图例

LRU页面置换算法用双向队列实现,共有三个操作,插入,淘汰,删除,插入将页插到队列开始位置,淘汰淘汰队列末端页面,删除则直接删除特定某一页。

img

代码

抽象类

template <typename T> class Replacer {
public:
  Replacer() {}
  virtual ~Replacer() {}
  virtual void Insert(const T &value) = 0;
  virtual bool Victim(T &value) = 0;
  virtual bool Erase(const T &value) = 0;
  virtual size_t Size() = 0;
};

头文件

template <typename T> class LRUReplacer : public Replacer<T> {
  struct Node {
    Node() {};
    Node(T val) : val(val) {};
    T val;
    shared_ptr<Node> prev;
    shared_ptr<Node> next;
  };
public:
  // do not change public interface
  LRUReplacer();

  ~LRUReplacer();

  void Insert(const T &value);

  bool Victim(T &value);

  bool Erase(const T &value);

  size_t Size();

private:
  shared_ptr<Node> head;
  shared_ptr<Node> tail;
  unordered_map<T,shared_ptr<Node>> map;
  mutable mutex latch;
  // add your member variables here
};

实现

template <typename T> LRUReplacer<T>::LRUReplacer() {
  head = make_shared<Node>();
  tail = make_shared<Node>();
  head->next = tail;
  tail->prev = head;
}

template <typename T> LRUReplacer<T>::~LRUReplacer() {
  while( head ) {
    shared_ptr<Node> tmp = head->next;
    head->next = nullptr;
    head = tmp;
  }

  while (tail) {
    shared_ptr<Node> tmp = tail->prev;
    tail->prev = nullptr;
    tail = tmp;
  }
}

/*
 * Insert value into LRU
 */
template <typename T> void LRUReplacer<T>::Insert(const T &value) {
  lock_guard<mutex> lck(latch);
  shared_ptr<Node> cur;
  if (map.find(value) != map.end()) {
    cur = map[value];
    shared_ptr<Node> prev = cur->prev;
    shared_ptr<Node> succ = cur->next;
    prev->next = succ;
    succ->prev = prev;
  } else {
    cur = make_shared<Node>(value);
  }
  shared_ptr<Node> fir = head->next;
  cur->next = fir;
  fir->prev = cur;
  cur->prev = head;
  head->next = cur;
  map[value] = cur;
  return;
}

/* If LRU is non-empty, pop the head member from LRU to argument "value", and
 * return true. If LRU is empty, return false
 */
template <typename T> bool LRUReplacer<T>::Victim(T &value) {
  lock_guard<mutex> lck(latch);
  if (map.empty()) {
    return false;
  }
  shared_ptr<Node> last = tail->prev;
  tail->prev = last->prev;
  last->prev->next = tail;
  value = last->val;
  map.erase(last->val);
  return true;
}

/*
 * Remove value from LRU. If removal is successful, return true, otherwise
 * return false
 */
template <typename T> bool LRUReplacer<T>::Erase(const T &value) {
  lock_guard<mutex> lck(latch);
  if (map.find(value) != map.end()) {
    shared_ptr<Node> cur = map[value];
    cur->prev->next = cur->next;
    cur->next->prev = cur->prev;
  }
  return map.erase(value);
}

template <typename T> size_t LRUReplacer<T>::Size() {
  lock_guard<mutex> lck(latch);
  return map.size();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值