模拟实现FIFO,LRU,OPT内存淘汰策略
策略简介
在页式存储管理中,内存以页框为单位分配使用。程序运行时以页为单位装入内存,只把当前需要的若干页装入内存,且这些页占用的页框不必相邻。程序运行需要新的页时,按需从外存上调入内存。但当物理内存中的页不够用的时候,要装入新的页就必须淘汰物理内存中某些页框的内容.
FIFO:first input first output的缩写,很容易理解这种策略的思想.
这种算法的实质是:总是选择在主存中停留时间最长(即最老)的一页置换,即先进入内存的页,先退出内存.
理由是:最早调入内存的页,其不再被使用的可能性比刚调入内存的可能性大.
建立一个FIFO队列,收容所有在内存中的页。被置换页面总是在队列头上进行。当一个页面被放入内存时,就把它插在队尾上.
优点:实现简单:页面按进入内存的时间排序,淘汰队头页面.LRU:Least Recently Used,最久未使用.
LRU算法是与每个页面最后使用的时间有关的。当必须置换一个页面时,LRU算法选择过去一段时间里最久未被使用的页面。
LRU算法是经常采用的页面置换算法,,并被认为是相当好的,但是存在如何实现它的问题.1.硬件方法:
页面设置一个移位寄存器R。每当页面被访问则将其重置1.
周期性地(周期很短)将所有页面的R左移一位(右边补0)
当需要淘汰页面时选择R值最大的页.
R的位数越多且移位周期越小就越精确,但硬件成本高.2.计数器:
保存时间:最简单的情况是使每个页表项对应一个使用时间字段,并给CPU增加一个逻辑时钟或计数器。每次存储访问,该时钟都加1。每当访问一个页面时,时钟寄存器的内容就被复制到相应页表项的使用时间字段中。这样我们就可以始终保留着每个页面最后访问的“时间”。
在置换页面时,选择该时间值最小的页面。
这样做,不仅要查页表,而且当页表改变时(因CPU调度)要维护这个页表中的时间,还要考虑到时钟值溢出的问题。3.栈:
用一个栈保留页号。
每当访问一个页面时,就把它从栈中取出放在栈顶上。这样一来,栈顶总是放有目前使用最多的页,而栈底放着目前最少使用的页。
由于要从栈的中间移走一项,所以要用具有头尾指针的双向链连起来。
在最坏的情况下,移走一页并把它放在栈顶上需要改动6个指针。每次修改都要有开销,但需要置换哪个页面却可直接得到,用不着查找,因为尾指针指向栈底,其中有被置换页。OPT:optimal
该策略的思想是,淘汰不再需要或最远的将来才会使用到的页面。
特点:理论上最佳,但实践中无法实现。因为当缺页发生时,操作系统无法知道各个页面下一次是在什么时候被访问
虽然这个算法不可能实现,但是最佳页面置换算法可以用于对可实现算法的性能进行衡量比较。
模拟实现(C语言)
- 这里我们仅仅用简单的数组实现。假设一虚拟页中存放10条指令,虚拟页数为32,物理页数4-32
- 定义指令集合结构体
typedef struct commandList{
int command;//10条指令的集合,代表所在的虚拟页页号
int offset;//指令偏移地址
int lastTimeHit;//最后一次命中的时间
int enterNum;//模拟进入的顺序
};
- 定义物理内存页,这里简单的写入加载虚拟页的页号
typedef struct physicalPage{
int command;//装入的指令集,-1代表没有装入
};
- 虚拟页中存放些什么数据呢?这里我们用随机数模拟虚拟页中的指令.
其中COMMAND_NUM代表指令个数,这里将虚拟页装满取320
void initVirtualPage(int * vp){
srand((unsigned)time(NULL));
for (int i = 0; i < COMMAND_NUM; i++)
{
vp[i] = rand()% COMMAND_NUM;
// printf("%d ", vp[i]);
}
}
- 定义全局变量
//物理页数
int physicalPageNum;
//虚拟页,int存储的是虚拟页中的指令,该指令随机产生
int* mVirtualPages;
//物理页
physicalPage* mPhysicalPage;
//指令集
commandList* mCommandList;
//缺页次数
int disaffect = 0;
//缺页率
float disaffectRate;
- 初始化变量
//初始化指令集合
void initCommandList(commandList* cl){
for (int i = 0; i < COMMAND_NUM; i++)
{
//方便起见,指令集和下标即为该指令
(cl + i)->lastTimeHit = -1;
(cl + i)->command = i / PAGE_CONTENT;
(cl + i)->offse