LRU,Least Recently Used,最近最久未使用。常用于页面置换算法。是为虚拟页式存储管理服务的。
对于在内存中又不用的数据块,称为LRU,操作系统会根据哪些数据属于LRU而将其移出内存。
对于操作系统的内存管理,如何节省利用容量不大的内存为最多的进程提供资源,一直是研究的的热点。而内存的虚拟存储管理,是现在最通用最常见的方式–在内存有限的情况下,扩展一部分外存作为虚拟内存。虚拟页式存储管理,则是将进程所需空间划分为多个页面,内存中只存放当前所需页面,其余页面放入外存的管理方式。对于页面置换算法来讲,当发生缺页中断时,都是要从内存中找到一个不需要的块换出去(对应物理内存的释放),然后将需要页面从磁盘的交换区中换进来(虚拟内存的分配)。
对于系统的所有文件I/O请求,操作系统都是通过page cache机制实现的,对于操作系统而言,磁盘文件都是由一系列的数据块顺序组成,数据块的大小随系统不同而不同,x86 linux系统下是4KB(一个标准页面大小)。内核在处理文件I/O请求时,首先到page cache中查找(page cache中的每一个数据块都设置了文件以及偏移信息),如果未命中,则启动磁盘I/O,将磁盘文件中的数据块加载到page cache中的一个空闲块。之后再copy到用户缓冲区中。
LRU实现:map+双向链表
class LRUCache {
private:
typedef list<int> LI;
typedef pair<int, LI::iterator> PII;
typedef unordered_map<int, PII> HIPII;
void touch(HIPII::iterator it) {
int key = it->first;
used.erase(it->second.second);
used.push_front(key);
it->second.second = used.begin();
}
HIPII cache;
LI used;
int _capacity;
public:
LRUCache(int capacity) : _capacity(capacity) {}
int get(int key) {
auto it = cache.find(key);
if (it == cache.end()) return -1;
touch(it);
return it->second.first;
}
void put(int key, int value) {
auto it = cache.find(key);
if (it != cache.end()) touch(it);
else {
if (cache.size() == _capacity) {
cache.erase(used.back());
used.pop_back();
}
used.push_front(key);
}
cache[key] = { value, used.begin() };
}
};