模拟虚拟存储

本文详细介绍了虚拟存储器实验,重点对比了FIFO和LRU页面置换算法的实现及性能。实验中,通过访问序列模拟页面访问,计算在物理块数为3和4时的命中率。LRU算法寻找最近最久未使用的页面进行替换,而FIFO则简单地替换最早进入内存的页面。实验结果显示了两种算法在页面失效次数和命中率上的差异。
摘要由CSDN通过智能技术生成

实验:虚拟存储

一、实验目的
1 、加深对虚拟存储器的理解。
2 、熟练掌握常用页面置换算法的实现原理。

二、实验设备
微型计算机

三、实验说明
1、在FIFO置换算法的基础上,编写实现LRU页面置换算法;
按如下的访问序列:12560365365604270435,
2、在物理块数分别为3和4时,分别调用FIFO和LRU算法,计算并输出相应的命中率。

1、 数据结构

(1) 页面结构

typedef struct{
int pn, pfn, counter, time;
} pl_type ;

pl_type pl[total_vp];

其中pn为页面号(页号),pfn为页帧号(物理块号),counter为一个周期内访问该页面的次数,time为访问时间;pl[total_vp]为页面结构数组,由于共有320条指令,每页可装入10条指令,因此虚页长total_vp的值为32。

(2)页帧控制结构

struct pfc_struct{
int pn, pfn;
struct pfc_struct *next;
};

typedef struct pfc_struct pfc_type;

pfc_type pfc[total_vp], *freepf_head, *busypf_head, *busypf_tail;

其中pfc[total_vp]定义用户进程的页帧控制结构数组,在该实验中,用户内存工作区是动态变化的,最多可达到用户进程的虚页数目,即32个物理块。

*freepf_head为空闲页帧头的指针

*busypf_head为忙页帧头的指针

*busypf_tail忙页帧尾的指针

2、 变量定义

(1) int a[total_instruction]: 指令流数组

(2) int diseffect: 页面失效次数

(3) int page[total_instruction]: 每条指令所属页面号

(4) int offset[total_instruction]: 每页装入10条指令后取模运算得出的页内偏移地址

(5) int total_pf: 用户进程的内存页帧数

3、 主要函数

(1) void initialize(int): 初始化函数
该函数主要对页面结构数组pl和页帧结构数组pfc进行初始化,如置页面结构中的页面号pn,初始化页帧号pfn为空,访问次数counter为0,访问时间time为-1;同样对页帧数组进行初始化,形成一个空闲页帧队列。

(2) void FIFO(int): 计算使用先进先出页面置换算法时的命中率

(3) void LRU(int): 计算使用最近最久未使用页面置换算法时的命中率

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef  struct
{  
	int  pn, pfn, counter, time;
} pl_type ;


struct  pfc_struct
{  
	int  pn, pfn;
	struct  pfc_struct  *next;
};
typedef  struct pfc_struct  pfc_type;
#define INVALID -1

//total_vp页面个数
//pfc[total_vp]定义用户进程的页帧控制结构数组
static int a[320];			//指令流数组
int diseffect=0;					//页面失效次数
int page[320]={1,2,5,6,0,3,6,5,3,6,5,6,0,4,2,7,0,4,3,5};		// 每条指令所属页面号
int offset[320]={-1};		//每页装入10条指令后取模运算得出的页内偏移地址
int total_pf=0;						//用户进程的内存页帧数=块数
int total_vp=32;
int total_instruction;
pl_type pl[32];
pfc_type   *freepf_head, *busypf_head, *busypf_tail;//pfc[total_vp],

int initialize(int total_pf)
{
	int i;
	pfc_type *pf;
	for(i=0;i<total_vp;i++)
	{
		pl[i].pn=i;
		pl[i].pfn=INVALID;
		pl[i].counter=0;
		pl[i].time=-1;
	}
	freepf_head=(pfc_type *) malloc(sizeof(pfc_type));
	if(freepf_head==NULL)
		return -1;
	else
	{
		freepf_head->pfn=0;
		freepf_head->next=NULL;
		pf=freepf_head;
		for(i=1;i<total_pf;i++)
		{
			pf->next=(pfc_type *) malloc(sizeof(pfc_type));
			pf=pf->next;
			pf->pfn=i;
			pf->next=NULL;
		}
	}
	busypf_head=busypf_tail=NULL;
	return 0;
}
void LRU(int total_pf)
{
	int i,farthest,j;
	pfc_type *p,*q,*a;
	initialize(total_pf);
	for(i=0;i<total_instruction;i++)
	{
	    if(pl[page[i]].pfn==INVALID) /*页面失效*/
		{  
	        diseffect=diseffect+1;
			if(freepf_head==NULL) /*无空闲页帧则把换出页面作为空闲页帧*/
			{  
				
				p=busypf_head;
				q=p;
				farthest=p->pn;
				while(p!=NULL)
				{
					if(pl[p->pn].time<pl[farthest].time)
						farthest=p->pn;
					p=p->next;
				}
		
				p=busypf_head;
				q=p;
				while(p->pn!=farthest&&p!=NULL)
				{
					q=p;
					p=p->next;
				}
				if(p==busypf_head)
				{
					busypf_head=busypf_head->next;
					pl[p->pn].pfn=INVALID;  //将忙页帧队首原来页面作为换出页面
					freepf_head=p; 
					freepf_head->next=NULL;
				}
				else if(p!=busypf_tail)
				{
					q->next=p->next;
					pl[p->pn].pfn=INVALID;  //将忙页帧上次被调用时间最早的页面作为换出页面
					freepf_head=p; 
					freepf_head->next=NULL;
				}
				else
				{
					busypf_tail=q;
					pl[p->pn].pfn=INVALID;  //将忙页帧队尾的页面作为换出页面
					freepf_head=p; 
					freepf_head->next=NULL;
				}
			}
			p=freepf_head->next;   //有空闲页帧
			freepf_head->next=NULL;	//将这个将被征用的空闲页帧和后面的断开
			freepf_head->pn=page[i]; 	/* 将所需页面调入空闲页帧 */
			pl[page[i]].pfn=freepf_head->pfn;//标注页表中此页对应的块号
			pl[page[i]].time=time(NULL)+i;
			if(busypf_head==NULL)  /* 若忙页帧队列为空,则将其头尾指针都指向刚调入页面所在的页帧 */	
			{
				busypf_head=busypf_tail=freepf_head;
				busypf_tail->next=NULL;
			}
			else
			{ //否则,将刚调入页面所在的页帧挂在忙页帧队列尾部
				busypf_tail->next=freepf_head;
				busypf_tail=busypf_tail->next;
				busypf_tail->next=NULL;
			}
			freepf_head=p; //空闲页帧头指针后移
	    }
		else
		{
			pl[page[i]].time=time(NULL)+i;
		}
    }
	printf("未命中数:%d\n\n",diseffect);
	printf("LRU命中率:%6.4f \n",1-(float)diseffect/20);
}
void FIFO(int total_pf) /*先进先出页面置换算法*/
{    
	int i;
    pfc_type *p;
    initialize(total_pf);
    busypf_head=busypf_tail=NULL;
	for(i=0;i<total_instruction;i++)
	{
	    if(pl[page[i]].pfn==INVALID) /*页面失效*/
		{  
	        diseffect=diseffect+1;
			if(freepf_head==NULL) /*无空闲页帧则把换出页面作为空闲页帧*/
			{  
				p=busypf_head->next;
				pl[busypf_head->pn].pfn=INVALID;  //将忙页帧队首原来页面作为换出页面
				freepf_head=busypf_head; 
				freepf_head->next=NULL;
				busypf_head=p; //忙页帧头指针后移
			}
			p=freepf_head->next;   //有空闲页帧
			freepf_head->next=NULL;	//将这个将被征用的空闲页帧和后面的断开
			freepf_head->pn=page[i]; 	/* 将所需页面调入空闲页帧 */
			pl[page[i]].pfn=freepf_head->pfn;		//标注页表中此页对应的块号
			if(busypf_tail==NULL)  /* 若忙页帧队列为空,则将其头尾指针都指向刚调入页面所在的页帧 */
				busypf_head=busypf_tail=freepf_head;
			else
			{ //否则,将刚调入页面所在的页帧挂在忙页帧队列尾部
				busypf_tail->next=freepf_head;
				busypf_tail=freepf_head;
			}
			freepf_head=p; //空闲页帧头指针后移
	    }
    }
	printf("未命中数:%d\n",diseffect);
   printf("FIFO命中率:%6.4f \n",1-(float)diseffect/20);
}
int main()
{
	int i,ch;
	printf("请输入指令个数:\n");
	scanf("%d",&total_instruction);
	printf("指令序列所在页面号如下\n");
	for(i=0;i<total_instruction;i++)
		printf("->  %d",page[i]);
	printf("\n请输入内存块数:\n");
	scanf("%d",&total_pf);
	printf("************Page replacement algorithm************\n\n");
	printf("\t\t\t1.FIFO\n\n");
	printf("\t\t\t2.LRU\n\n");
	printf("choose the algorithm:\n");
	scanf("%10d",&ch);
	switch(ch)
	{
		case 1:
				FIFO(total_pf);
				break;
		case 2:
				LRU(total_pf);
				break;
		default:printf("enter error data!\n");
	}
}

对于FIFO页面置换算法,每次置换时只需换出忙队列对手的页面,新加入的页面放到队尾;对于LRU页面置换算法,每次都要找到忙队列中上次调用距今最久的页面,因此要被换出的页面在队头、队尾和队中的操作不同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值