后台面试经典问题-手写LRU算法

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 LI;
    typedef pair PII;
    typedef unordered_map 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() };
    }
    
};

 

你可能感兴趣的:(c++后台面试知识点)