操作系統之LRU算法 C語言鏈表實現


LRU是Least Recently Used的縮寫,即最近最少使用,是一種常用的頁面置換算法,選擇最近最久未使用的頁面予以淘汰。該算法賦予每個頁面一個訪問字段,用來記錄一個頁面自上次被訪問以來所經歷的時間 t,當須淘汰一個頁面時,選擇現有頁面中其 t 值最大的,即最近最少使用的頁面予以淘汰。

為什么要使用鏈表實現呢,因為這個頁面不會很多,內存和資源開銷都小

在計算機中,開銷往往是需要考慮的,我們不希望占用過多的系統資源,動態路由小型網絡使用RIP(Bellman-Ford Routing Algorithm),大型網絡設備用的就是OSPF(dijkstra),當然也有很多方面的考慮,比如RIP配置和管理更簡單,RIP為了避免出現網絡延遲太高,也將路由器最大的允許跳數設為15

我們存儲的時候就按照時間吧,末尾為剛剛使用的,淘汰前面的

然后我們來考慮下這個算法,保證我們不使用無關變量。這個cache是空的

進行一次請求需要查看我當前的cache里是否存在這個數據

1存在

  存在就比較簡單了,直接取出數據,頁面數據不變,並把這個結點放在最后

2不存在

  2.1cache滿

  把最靠前的頁面用讀取數據的數據覆蓋,然后把它放到最后的cache

  2.2cache不滿

  直接去讀取數據,然后把他放在最后的頁面

我需要維護的是一個編號(或者說地址)還有后結點,然后查詢肯定是O(1)的,這是內部完成的,不需要我考慮(直接得到地址去取數據)

缺頁中斷都對應了一個硬件操作,就是去取這個數據

#include <stdio.h>
#include <stdlib.h>
struct node
{
    int id;
    struct node *next;
} * head, *tail, *p;
void PushBack()
{
    /* 
    pre沒有意義,僅需要多保留一個尾結點
    p->pre = tail; //使pre指向前一個節點,循環可得到反向鏈表
    */
    p->next = NULL;
    tail->next = p;
    tail = p;
}
void fun()
{
    struct node *q;
    q = head;
    while (q->next != NULL)
    {
        if (q->next->id == p->id)//不缺頁
        {
            PushBack();
            p = q->next;
            q->next = p->next;
            free(p);
            return; //執行完全部操作停掉
        }
        q = q->next;
    }
    printf("發生缺頁中斷 %d\n",p->id);
    PushBack();
    p = head->next;
    head->next = p->next;
    free(p);
}
int main()
{
    int sum, n, i;
    sum = 0;         //初始cache內沒有數據
    scanf("%d", &n); //讀入頁數
    head = (struct node *)malloc(sizeof(struct node));
    head->next = NULL;
    tail = head;
    while (1)
    {
        p = (struct node *)malloc(sizeof(struct node));
        scanf("%d", &p->id);
        if (p->id < 0)
        {
            break;
        }
        else
        {
            if (sum < n) //cache未滿,放至后面
            {
                PushBack();
                printf("發生缺頁中斷 %d\n",p->id);
                sum += 1; //並對cache+1
            }
            else
            {
                fun();
            }
        }
    }
    return 0;
}

事后來看,我說pre沒有意義是不對的,因為實際上並不是亂序的,往往我們先訪問的到的會被繼續訪問,並不是一個完全的均攤復雜度。

所以應該記錄pre進行倒序,有興趣的可以實現一下,不過我還是覺得c++好寫,但是內部肯定是更厲害的

c++實現就用list搞一下啊,把最近訪問的放到最前面

#include<iostream>
#include<list>
void fun(std::list<int>&L,int x)
{
    for(std::list<int>::iterator it=L.begin();it!=L.end();it++)
    {
        if(*it==x)
        {
            L.push_front(x);
            L.erase(it);
            return;
        }
    }
    std::cout<<"發生缺頁中斷 "<<x<<std::endl;
    L.pop_back();
    L.push_front(x);
}
int main()
{
    std::list<int>L;
    int sum, n, i,x;
    sum = 0;         //初始cache內沒有數據
    std::cin>>n; //讀入頁數
    while (true)
    {
        scanf("%d", &x);
        if (x < 0)
        {
            break;
        }
        else
        {
            if (sum < n) //cache未滿,放至后面
            {
                L.push_front(x);
                std::cout<<"發生缺頁中斷 "<<x<<std::endl;
                sum += 1; //並對cache+1
            }
            else
            {
                fun(L,x);
            }
        }
    }
    return 0;
}
C++ list 因為內部就是雙向鏈表

 

public class LRUCache{
    private int limit;
    private HashMap<String,Node> hashMap;
    private Node head;
    private Node end;
 
    public LRUCache(int limit)
    {
        this.limit = limit;
        hashMap = new HashMap<String,Node>();
    }
 
    public String get(String key){
        Node node = hashMap.get(key);
        if(node ==null)
            return null;
        refreshNode(node);
        return node.value;
    }
 
    public void put(String key,String value){
        Node node = hashMap.get(key);
        if(node == null){
            if(hashMap.size()>=limit)
            {
                String oldKey = removeNode(head);
                hashMap.remove(oldKey);
            }
            node = new Node(key,value);
            addNode(node);
            hashMap.put(key,node)
        }else{
            node.value = value;
            refreshNode(node);
        }
    }
 
    public void remove(String key){
        Node node = hashMap.get(key);
        removeNode(node);
        hashMap.remove(key);
    }
 
 
    private void refreshNode(Node node)
    {
        if(node == end)
            return;
        removeNode(node);
        addNode(node);
    }
 
 
    public String removeNode(Node node){
        if(node == end)
            end = end.pre;
        else if(node ==head)
            head = head.next;
        else
            {
                node.pre.next = node.next;
                node.next.pre = node.pre;
            }
        return node.key;
    }
     
     public void addNode(Node node)
     {
        if(end!=null)
        {
            end.next = node;
            node.pre = end;
            node.next = null;
        }
        end = node;
        if(head == null)
            head = node;
     }
 
}
Java實現(高並發線程安全使用ConcurrentHashMap

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM