实验目的

加深对存储管理功能的理解;

了解存储管理如何合理分配空间;

掌握请求页式存储管理的页面置换算法。

实验内容

通过随机数产生200条的指令序列,指令的访问地址范围为8K。

方法:在[0,199]指令地址间存放的是0~8K-1之间的随机数,表示该指令要访问的地址。

得到200个地址后将其转换成[页号,页内地址]的格式输出,设置页面大小为1K。例如:地址2055->

[2,7],即2055=2x1024+7。

将指令序列变换成页地址流,即页面走向。设置物理块M。

计算并输出以下页面置换算法的命中率(1-

缺页率):

(1)先进先出置换算法(FIFO)

(2)最近最久未使用置换算法(LRU)

(3)最佳置换算法(OPT)。

随机数产生方法

利用srand()设好随机数种子,如:srand(10*getpid()),产生不同的随机数序列;如果未设随机数种子,rand()在调用时会自动设随机数种子为1,每次产生的随机数序列相同。

再利用rand()产生随机数,如:产生介于0到10

间的随机数值x=rand() mod 11;

4,代码(这里贴的代码缩进不好,可读性差,需要的话来直接点击下载page.c吧~)

#include
#include
#include
#defineBLOCK_MAX_SIZE 20//最大物理块大小
enum{FIFO=1,LRU,OPT};
structnode_page{
intaddress;//指令地址
intpage_num;//页面号
intnext_order;//下一次访问的次序
}*page;
//物理块定义
typedefstruct BlockNode{
intpage_index;//page数组的下标
structBlockNode * next;
}BlockNode;
struct{
intlength;//当前物理块长度
intmiss_flag;//缺页标志,若为1,则缺页
intmiss_count;//缺页次数
BlockNode*front;
BlockNode*rear;
}Block;
//本程序中全局变量名均由两个单词组成,且开头字母大写
intBlockSize = 5;//物理块大小
intPageCount = 200;//页面总数
intPageSize = 1024;//页面大小
intAddrRange = 8*1024;//访问地址范围
intget_num(int down,int
up)//得到一个down~up之间的整数
{
intnum;
charstr[111];
while(1){
fgets(str,111*sizeof(int),stdin);
num=atoi(str);//把字符串中的数字转换为整数
if(num>=down&&
num<=up)
break;
printf("输入范围有误,请重新输入:");
}//while
returnnum;
}
voidinit_block()//构造一个空的物理块队列
{
Block.rear=Block.front=(BlockNode*)malloc(sizeof(BlockNode));
if(!Block.front){
printf("内存分配失败!n");
exit(0);
}
Block.length=0;
Block.miss_count=0;
Block.rear->next=NULL;
}
voidenqueue(int page_index)//入队
{
BlockNode*node=(BlockNode*)malloc(sizeof(BlockNode));
if(!node){
printf("内存分配失败!n");
exit(0);
}
node->page_index=page_index;
node->next=NULL;
Block.length++;
Block.rear->next=node;
Block.rear=node;
}
voiddequeue()//出队
{
BlockNode*node;
node=Block.front->next;
Block.front->next=node->next;
if(node== Block.rear)
Block.rear=Block.front;
free(node);
Block.length--;
}
voidclear_block()//清空物理块
{
while(Block.rear=Block.front->next){
Block.front->next=Block.rear->next;
free(Block.rear);
Block.length--;
}
Block.rear=Block.front;
Block.length=0;
Block.miss_count=0;
}
voiddestroy_block()//销毁物理块
{
while(Block.rear=Block.front){
Block.front=Block.front->next;
free(Block.rear);
}
free(page);
}
voidinit_page()//初始化页面系列
{
inti,j;
srand(time(NULL));//用当前系统时间来初始化随机种子
page=(structnode_page*)malloc(PageCount*sizeof(struct
node_page));
for(i=0;i
page[i].address=rand()%AddrRange;
page[i].page_num=page[i].address/PageSize;
}
for(i=0;i
for(j=i+1;j
if(page[i].page_num== page[j].page_num){
page[i].next_order=j;
break;
}//if
}//for
if(j== PageCount)//说明page[i]以后都不会再访问
page[i].next_order= PageCount;
}//for
}
voidprint_page()//打印页面系列
{
inti;
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~n");
printf("页面系列为:n");
for(i=0;i
printf("[%-2d,%-4d]",page[i].page_num,page[i].address%PageSize);
if((i+1)%5== 0){
printf("n");
}//if
}
printf("n");
}
voidFIFO_Replace(int page_index)//FIFO置换
{
BlockNode*node;
if(!Block.length){
enqueue(page_index);
Block.miss_flag=0;
return;
}
node=Block.front;
while(node=node->next){
if(page[node->page_index].page_num==page[page_index].page_num){
Block.miss_flag=0;
return;
}
}
if(Block.length
enqueue(page_index);
Block.miss_flag=0;
return;
}
dequeue();
enqueue(page_index);
Block.miss_flag=1;
Block.miss_count++;
}
voidLRU_Replace(int page_index)//LRU置换
{
BlockNode*node,*last_node;
if(!Block.length){
enqueue(page_index);
Block.miss_flag=0;
return;
}
last_node=node=Block.front;
while(node=node->next){
if(page[node->page_index].page_num==
page[page_index].page_num){
last_node->next=node->next;
Block.length--;
if(node== Block.rear)
Block.rear=last_node;
enqueue(node->page_index);
free(node);
Block.miss_flag=0;
return;
}
last_node=node;
}
if(Block.length
enqueue(page_index);
Block.miss_flag=0;
return;
}
dequeue();
enqueue(page_index);
Block.miss_flag=1;
Block.miss_count++;
}
voidOPT_Replace(int page_index)//OPT置换
{
BlockNode*node;
BlockNode*max_node,*max_node_last;
if(!Block.length){
enqueue(page_index);
Block.miss_flag=0;
return;
}
node=Block.front;
while(node=node->next){
if(page[node->page_index].page_num==
page[page_index].page_num){
node->page_index=page_index;
Block.miss_flag=0;
return;
}
}
if(Block.length
enqueue(page_index);
Block.miss_flag=0;
return;
}
node=Block.front;
max_node=node->next;
while(node=node->next){//寻找Block中next_order值最大的节点
if(page[max_node->page_index].next_orderpage_index].next_order)
max_node=node;
}
node=Block.front;
max_node_last=node;
while(node=node->next){//寻找Block中next_order值最大的节点的上一个节点
if(node== max_node)
break;
max_node_last=node;
}
max_node_last->next=
max_node->next;
Block.length--;
if(max_node== Block.rear)
Block.rear=max_node_last;
free(max_node);
enqueue(page_index);
Block.miss_flag=1;
Block.miss_count++;
}
voidpage_replace(int num)
{
inti,j;
BlockNode*node;
charstr[3][5]={"FIFO","LRU ","OPT "};
printf("======================%s=========================n",str[num-1]);
printf("页面号*");
for(i=0;i< BlockSize;i++)
printf(" ");
printf("* 是否缺页 *n");
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~n");
for(i=0;i
printf(" %-4d*",page[i].page_num);
if(num== FIFO)
FIFO_Replace(i);
elseif(num == LRU)
LRU_Replace(i);
elseif(num == OPT)
OPT_Replace(i);
node=Block.front;
while(node=node->next)
printf("%-2d",page[node->page_index].page_num);
for(j=Block.length;j
printf(" ");
printf("* %s *nn",(Block.miss_flag==1 ? "Yes" : "No"));
}
printf("n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~n");
printf("缺页数:%d,缺页率:%%%.2fnn",Block.miss_count,(float)Block.miss_count/PageCount
*100);
printf("按回车键继续!nn");
getchar();
}
voidconfige()//程序设置
{
intnum;
while(1){
printf("n***************************************************n");
printf("* 程序设置 *n");
printf("***************************************************n");
printf("* 1,设置物理块大小(默认5) *n");
printf("* 2,设置访问地址范围 (默认8K) *n");
printf("* 3,设置页面大小(默认1K) *n");
printf("* 4,设置页面总数(默认200) *n");
printf("* 5,显示各项设置值 *n");
printf("* 6,返回 *n");
printf("***************************************************n");
printf("请输入您的选择:");
num=get_num(1,6);
if(num==6)
break;
if(num==1){
printf("请输入物理块大小(1~%d):",BLOCK_MAX_SIZE);
BlockSize=get_num(1,BLOCK_MAX_SIZE);
printf("设置成功!nn");
}//if
elseif(num==2){
printf("请输入访问地址范围(1~%d)K: ",999);
AddrRange=get_num(1,999)* 1024;
printf("设置成功!nn");
}//elseif
elseif(num==3){
printf("请输入页面大小(1~%d)K: ",AddrRange/1024);
PageSize=get_num(1,AddrRange/1024)* 1024;
printf("设置成功!nn");
}//elseif
elseif(num==4){
printf("请输入页面总数(1~%d):",32767);
PageCount=get_num(1,32767);
printf("设置成功!nn");
}//elseif
elseif(num==5){
printf("---------------------------------------------------n");
printf("*当前物理块大小:%dn",BlockSize);
printf("*当前访问地址范围:%d Kn",AddrRange/1024);
printf("*当前页面大小:%d Kn",PageSize/1024);
printf("*当前页面总数%dn",PageCount);
printf("---------------------------------------------------n");
}
}
free(page);
init_page();
}
voidbegin()
{
intnum;
print_page();
while(1){
printf("n***************************************************n");
printf("* 页面置换算法 *n");
printf("***************************************************n");
printf("* 1,先进先出置换算法(FIFO) *n");
printf("* 2,最近最久未使用置换算法(LRU) *n");
printf("* 3,最佳置换算法(OPT) *n");
printf("* 4,返回 *n");
printf("***************************************************n");
printf("请输入您的选择:");
num=get_num(1,4);
if(num== 4)
break;
page_replace(num);
clear_block();
}
free(page);
init_page();
}
intmain()
{
intnum;
init_block();
init_page();
while(1){
printf("n***************************************************n");
printf("* 存储器管理模拟系统 *n");
printf("***************************************************n");
printf("* 1,进入页面置换算法 *n");
printf("* 2,进入程序设置 *n");
printf("* 3,退出 *n");
printf("***************************************************n");
printf("请输入您的选择:");
num=get_num(1,3);
if(num== 3)
break;
if(num== 1)
begin();
elseif(num == 2)
confige();
}
destroy_block();
return0;
}