在操作系统中,我们有的时候内存中的空间不够了,这个时候我们有新的作业要进入内存中,被调度运行,那该怎么办呢,我们有几种策略。
其一是随机置换策略,即当新的作业到来的时候,随机选择物理内存中的某个没有正在进行的作业,然后将其置换出去
其二是选择后面的某一段时间内,最久不会涉及到的内存块,可能是在1k条指令后才会访问,可能是1w条指令后才访问的块等
其三是先进先出的策略,即最先进入内存块的作业,在发生内存不足的情况下就最先离开。
其四是我们这一次要贴代码的LRU算法,他的策略是选择前面一段时间内最久没有被使用的物理页面,将其置换出去。因此我们需要给其加上一个时间戳。详情戳下面链接
百度百科–页面置换算法
下面是我贴上的代码,我采用的数据结构是链表形式,比较自由方便
LRU源代码:
#include <iostream>
#include <stdio.h>
#include <queue>
#include <ctime>
#include <set>
#include <stdlib.h>
#define MAX 10//十个物理内存块
#define N 20
using namespace std;
class block
{
public:
int id;
clock_t last_time;
block* next;
block();
block(int ID,clock_t c)
{
id=ID;
last_time=c;
next = NULL;
}
};
class link
{
public:
int size;
block* head;
block* tail;
block* curr;
link()
{
size=0;
head = new block(0,(clock_t)0);
tail = head;
curr = head;
}
block* remove();
void add(block* b);
block* find(int id);
void print(clock_t);
};
//移出最久未访问的作业
block* link::remove()
{
block* min = head->next;
int i;
curr = head->next;
for(i=0;i<size;i++)
{
if(min->last_time>curr->last_time)min=curr;
curr = curr->next;
}
return min;
}
//初始化的时候添加作业
void link::add(block* b)
{
tail->next = b;
tail = tail->next;
size++;
}
//查找在当前链表里面有没有某个作业
block* link::find(int id)
{
block* index;
for(index=head->next;index!=NULL;index=index->next)
{
if(index->id==id)
return index;
}
return NULL;
}
//打印操作,将物理内存块的情况打印出来
void link::print(clock_t st)
{
curr = head->next;
int i=0;
cout<<"编号: 页号 上一次访问时间"<<endl;
while(curr!=NULL)
{
cout<<" "<<i<<" "<<curr->id<<" "<<(curr->last_time-st)/CLOCKS_PER_SEC<<endl;
i++;
curr=curr->next;
}
cout<<"规模为: "<<size<<endl;
}
set<int> my_set;
//查找某个作业是否在里边,我们可以用set来查找,set底层是RB-Tree,查找会比较快
//初始化的时候用的
bool search(int x,set<int> my_set)
{
set<int>::iterator iter;
iter = my_set.find(x);
if(iter!=my_set.end())
return true;
return false;
}
int main()
{
srand(time(NULL));
int i,j,k;
link* mylink = new link();
clock_t st = clock();
//Init
int tmp_init=rand()%MAX;//随机产生tmp_init个作业
int tmp_rand;
for(i=0;i<tmp_init;i++)
{
tmp_rand=rand()%N; //随机产生作业号并且要查重,防止同样的作业
while(search(tmp_rand,my_set)==true)
{
tmp_rand=rand()%N;
}
my_set.insert(tmp_rand); //将作业ID插入集合
mylink->add(new block(tmp_rand,clock())); //将作业装入链表里面进行管理
}
mylink->print(st);
int n,tmp_id;
block* tmp_block1;
block* tmp_block2;
cout<<"请输入需要操作的次数n"<<endl;
cin>>n;
for(i=0;i<n;i++)
{
cout<<"请输入需要访问的逻辑页面tmp_id"<<endl;
cin>>tmp_id; //输入你需要访问的id
tmp_block1=mylink->find(tmp_id);
if(tmp_block1!=NULL) //如果找到,即不为空,那就修改那个块的最后一次时间
{
tmp_block1->last_time=clock();
}
else if(tmp_block1==NULL) //如果为空,说明链表里没这个作业
{
if(mylink->size>=MAX)//如果作业量已经超过最大容量,就按照LRU剃掉一个
{
tmp_block2=mylink->remove();
tmp_block2->id=tmp_id;
tmp_block2->last_time=clock();
}
else //如果没有超过最大容量,就添加一个作业放在后面
{
mylink->add(new block(tmp_id,clock()));
}
}
mylink->print(st);
}
return 0;
}
以上是我写的C++的LRU页面置换算法,有bug或者不对的地方欢迎指正
另外,后期应该会推出关于内存分配与内存管理的博文以及相关代码。包含内存分配,分页式管理,多层索引等等,有需要的可以联系下面邮箱。
------------------------------1124397151@qq.com-------------------------------------