实验六:页面置换算法
一、 实验目的( 页面置换 )
在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断。当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法。
二、 实验内容( 常用的 页面置换算法 )
1. 最佳置换算法(OPT )
这是一种理想情况下的页面置换算法,但实际上是不可能实现的。
该算法的基本思想是:发生缺页时,有些页面在内存中,其中有一页将很快被访问(也包含紧接着的下一条指令的那页),而其他页面则可能要到 10、100 或者 1000 条指令后才会被访问,每个页面都可以用在该页面首次被访问前所要执行的指令数进行标记。最佳页面置换算法只是简单地规定:标记最大的页应该被置换。这个算法唯一的一个问题就是它无法实现。当缺页发生时,操作系统无法知道各个页面下一次是在什么时候被访问。虽然这个算法不可能实现,但是最佳页面置换算法可以用于对可实现算法的性能进行衡量比较。
2. 先进先出置换算法(FIFO )最简单的页面置换算法是先入先出(FIFO)法。
这种算法的实质是,总是选择在主存中停留时间最长(即最老)的一页置换,即先进入内存的页,先退出内存。理由是:最早调入内存的页,其不再被使用的可能性比刚调入内存的可能性大。建立一个 FIFO 队列,收容所有在内存中的页。被置换页面总是在队列头上进行。当一个页面被放入内存时,就把它插在队尾上。这种算法只是在按线性顺序访问地址空间时才是理想的,否则效率不高。因为那些常被访问的页,往往在主存中也停留得最久,结果它们因变“老”而不得不被置换出去。
FIFO 的另一个缺点是,它有一种异常现象,即在增加存储块的情况下,反而使缺页中断率增加了。当然,导致这种异常现象的页面走向实际上是很少见的。
3. 最近最久未使用(LRU )算法FIFO 算法和 OPT 算法之间的主要差别是,FIFO 算法利用页面进入内存后的时间长短作为置换依据,而 OPT 算法的依据是将来使用页面的时间。如果以最近的过去作为不久将来的近似,那么就可以把过去最长一段时间里不曾被使用的页面置换掉。它的实质是,当需要置换一页时,选择在之前一段时间里最久没有使用过的页面予以置换。这种算法就称为最久未使用算法(Least Recently Used,LRU)。LRU 算法是与每个页面最后使用的时间有关的。当必须置换一个页面时,LRU 算法选择过去一段时间里最久未被使用的页面。LRU 算法是经常采用的页面置换算法,并被认为是相当好的,但是存在如何实现它的问题。LRU 算法需要实际硬件的支持,其问题是怎么确定最后使用时间的顺序。
三、实验参考代码
#include "stdio.h"
#include "stdlib.h"
typedef struct item
{
int num; //页号
int time; //等待时间,LRU算法会用到这个属性
}Pro;
int pageNum; //系统分配给作业的主存中的页面数
int memoryNum; //可用内存页面数
void print(Pro *page1); //打印当前主存中的页面
int Search(int num1, Pro *memory1); //在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1
int Max(Pro *memory1);
int optimal(int num,int tag,Pro *memory1,Pro *page1);
int main(void)
{
int i;
int curmemory; //调入主存中的页面个数
int missNum; //缺页次数
float missRate; //缺页率
char c; //得到用户的输入字符,来选择相应的置换算法
Pro *page; //作业页面集
Pro *memory; //内存页面集
printf("输入系统分配给作业的主存中的页面数:");
scanf("%d", &pageNum);
printf("输入内存页面数:");
scanf("%d", &memoryNum);
page= (Pro*)malloc(sizeof(Pro)*pageNum);
memory= (Pro*)malloc(sizeof(Pro)*memoryNum);
for(i=0;i<pageNum;i++)
{
printf("第 %d 个页面号为:", i);
scanf("%d", &page[i].num);
page[i].time=0; //等待时间开始默认为0
}
do{
for(i=0;i<memoryNum;i++) //初始化内存中页面
{
memory[i].num=-1; //页面为空用-1表示
memory[i].time=-1; //
}
printf("*****f:FIFO页面置换*****\n");
printf("*****o:OPT页面置换*****\n");
printf("*****l:LRU页面置换*****\n");
printf("*****请选择操作类型(f,o,l),按其它键结束******\n");
fflush(stdin);
scanf("%c", &c);
i = 0;
curmemory = 0;
if(c=='f') //FIFO页面置换
{
missNum = 0;
printf("FIFO页面置换情况: \n");
for(i=0;i<pageNum;i++)
{
if(Search(page[i].num,memory)<0)//若在主存中没有找到该页面
{
missNum ++;
memory[curmemory].num=page[i].num;
print(memory);
curmemory = (curmemory+1)%memoryNum;
}
}//end for
missRate = (float)missNum/pageNum;
printf("缺页次数:%d 缺页率: %f\n", missNum, missRate);
}//end if
if(c=='o') //OPT页面置换
{
missNum = 0;
printf("OPT页面置换情况: \n");
for(i=0;i<pageNum;i++)
{
if(Search(page[i].num,memory)<0)//若在主存中没有找到该页面
{
if(i<memoryNum)
curmemory = i;
else
curmemory = optimal(page[i].num,i,memory,page);
missNum ++;
memory[curmemory].num=page[i].num;
print(memory);
curmemory = (curmemory+1)%memoryNum;
}
}//end for
missRate = (float)missNum/pageNum;
printf("缺页次数:%d 缺页率: %.2f%%\n", missNum, missRate*100);
}//end if
if(c=='l') //LRU页面置换
{
missNum = 0;
printf("LRU页面置换情况: \n");
for(i=0;i<pageNum;i++)
{
for(int j=0;j<memoryNum;j++)
{
if(memory[j].num>=0)
memory[j].time++;
}
if(Search(page[i].num,memory)<0)//若在主存中没有找到该页面
{
missNum ++;
// printf("%d \n",curmemory);
if(i<3)
curmemory = i;
else
curmemory = Max(memory);
memory[curmemory].num=page[i].num;
memory[curmemory].time = 0;
print(memory);
curmemory = (curmemory+1)%memoryNum;
}
else
{
curmemory = Search(page[i].num,memory);
memory[curmemory].time=0;
curmemory = (curmemory+1)%memoryNum;
}
}//end for
missRate = (float)missNum/pageNum;
printf("缺页次数:%d 缺页率: %.2f%%\n", missNum, missRate*100);
}//end if
}while(c=='f'||c=='l'||c=='o');
return 0;
}
void print(Pro *memory1)//打印当前的页面
{
int j;
for(j=0;j<memoryNum;j++)
printf("%d ", memory1[j].num);
printf("\n");
}
//在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1
int Search(int num1,Pro *memory1 )
{
int j;
for(j=0;j<memoryNum;j++)
{
if(num1==memory1[j].num)
return j;
}
return -1;
}
int Max(Pro *memory1)
{
int max = 0;
for(int k=1;k<memoryNum;k++)
{
if(memory1[k].time > memory1[max].time)
max = k;
}
return max;
}
int optimal(int num,int tag,Pro *memory1,Pro *page1)
{
int k,j,min[100],min_k;
for(k=0;k<memoryNum;k++)
min[k] = 500;
for(k=0;k<memoryNum;k++)
{
j = tag;
do{
j++;
if(j>20)
break;
}while(page1[j].num!=memory1[k].num);
if(j<min[k])
{
min[k] = j;
}
}
int max = 0;
for(int t=1;t<memoryNum;t++)
{
if(min[t]>min[max])
max = t;
}
return max;
}