OS 页面置换算法模拟程序

2 篇文章 0 订阅

OS实验,记录一下

题目

模拟页面置换算法(FIFO/LRU/OPT)

实现

/*
* 题目:OS页面置换算法模拟程序
* 作者:公羽向阳 
* 时间:2020年6月3日 
* CentOS、Windows下g++编译通过
*/
#include <cstdio>
#include <ctime>
#include <cstdlib> 
#define VP 32
#define T 320
#define INVALID -1
#define MAX 32767

struct page_struct // 页面结构 
{
	int data; 
	
	int pnum; // 页面号 
	int pfacen; // 指向页面号 
	int time; // 使用次数 
}; 

struct page_control // 页面控制结构 
{
	int data;
	
	int pnum;
	int pfacen;
	page_control *next;
}; 

page_struct  vpage[VP]; // 虚拟内存页 
page_control pfc[VP]; // 页面控制 (4 - VP)
page_control *freepf_head, *busypf_head, *busypf_tail; 

int dp[T]; // dp 调度序列,取值:0-T
int page[T]; //进程页面号,由调度序列初始化,取值:0 - VP-1 
int diseffect; // 缺页计数 

int _rand()
{
	int rand_num = rand()%MAX;
	return (int)(float)(T-1)*rand_num/MAX+1;
}

void init(int pp)
{
	diseffect = 0;
	for(int i=0; i<VP; i++)
	{
		vpage[i].pnum = i; // 初始化页面号 
		vpage[i].pfacen = INVALID; // 设为无效 
		vpage[i].time = -1; // 设置关于页面控制的访问次数 
	}
	
	// 建立控制链表(长度:4-VP)
	for(int i=1; i<pp; i++)
	{
		pfc[i-1].next = &pfc[i]; // 前指向后
		pfc[i-1].pfacen = i - 1;  
	} 
	pfc[pp-1].next = NULL;
	pfc[pp-1].pfacen = pp - 1;
	freepf_head = &pfc[0]; // 空闲指针指向第一页 
}

float ans(int diseffect)
{
	return (1-(float)diseffect/T);
}

void fifo(int pp)
{
	page_control *p;
	init(pp);
	busypf_head = busypf_tail = NULL; // 0
	for(int i=0; i<T; i++)
	{
		if(vpage[page[i]].pfacen == INVALID) // 页面未被使用 
		{
			diseffect ++; // 页面中断次数
			if(freepf_head == NULL) // 控制页满了(内存占满) 
			{
				// 出链队,FIFO
				p = busypf_head->next;
				vpage[busypf_head->pnum].pfacen = INVALID; 
				freepf_head = busypf_head; // 将空闲指针指向出队元素所在内存 
				freepf_head->next = NULL;
				busypf_head = p; 
			} 
			
			// 调一个虚存页进内存 
			p = freepf_head->next;
			
			freepf_head->pnum = page[i];
			freepf_head->next = NULL;
			// 通过 pfacen 建立联系 (0 - pp-1)
			vpage[page[i]].pfacen = freepf_head->pfacen;  
			
			if(busypf_tail == NULL)
				busypf_head = busypf_tail = freepf_head;
			else
			{
				busypf_tail->next = freepf_head;
				busypf_tail = freepf_head; 
			}
			
			freepf_head = p; 
		} 
	}
	printf("FIFO: %.5f\t", ans(diseffect));
}

void lru(int pp)
{
	int present_time = 0; // 当前时间
	init(pp);
	for(int i=0; i<T; i++)
	{
		if(vpage[page[i]].pfacen == INVALID) // 页面未被使用 
		{
			diseffect ++; 
			if(freepf_head == NULL) // 控制页满(内存满) 
			{
				// 找最久未使用
				int min = MAX; // 初始 min为最大值 
				int min_index = 0;
				for(int j=0; j<VP; j++)
				{
					if(min>vpage[j].time && ~vpage[j].pfacen) // 找使用次数最少 
					{
						min = vpage[j].time;
						min_index = j;
					}
				} 
				
				//将空闲指针指向使用次数最少页,清除使用状态 
				freepf_head = &pfc[vpage[min_index].pfacen]; 
				freepf_head->next = NULL; 
				vpage[min_index].pfacen = INVALID;
				vpage[min_index].time = -1;
			}
			
			// 建立联系 
			vpage[page[i]].pfacen = freepf_head->pfacen;
			freepf_head = freepf_head->next; 
		}
		vpage[page[i]].time = present_time; 
		present_time ++;
	}
	printf("LRU: %.5f\t", ans(diseffect));
}

void opt(int pp)
{
	int vdistance[VP]; // 存储对应页所需间隔 
	init(pp);
	for(int i=0; i<T; i++)
	{
		if(vpage[page[i]].pfacen == INVALID) // 页面未被使用 
		{
			diseffect ++;
			if(freepf_head == NULL) // 控制页满(内存满)
			{
				// 初始间隔 
				for(int j=0; j<VP; j++)
				{
					if(~vpage[j].pfacen) // 当前页没有被使用 
						vdistance[j] = MAX;
					else vdistance[j] = 0;
				}
				int distance = 1; // 越大越不会被响应 
				
				// 更新间隔 
				for(int j=i+1; j<T; j++)
				{
					if((vdistance[page[j]]==MAX) && (~vpage[page[j]].pfacen))
						vdistance[page[j]] = distance;
					distance ++;
				}
				
				// 找最远 
				int max = -1;
				int max_index = 0;
				for(int j=0; j<VP; j++)
				{
					if(vdistance[j] > max)
					{
						max = vdistance[j];
						max_index = j;
					}
				}
				
				// 建立联系 
				freepf_head = &pfc[vpage[max_index].pfacen];
				freepf_head->next = NULL;
				vpage[max_index].pfacen = INVALID;
			}
			vpage[page[i]].pfacen = freepf_head->pfacen;
			freepf_head = freepf_head->next;
		}
	}
	printf("OPT: %.5f\t", ans(diseffect));
}

int main()
{
	srand((unsigned)time(NULL)); 
	int r = _rand();
	for(int i=0; i<T; i+=3)
	{
		dp[i] = r;
		dp[i+1] = dp[i]+1;

		dp[i+2] = _rand();
		dp[i+3] = dp[i+2]+1;
		r = _rand(); // 可改进处 
	}
	for(int i=0;i<T;i++) //将dp的指令序列变换成页地址流
	{
		page[i] = (dp[i]/10)%VP;
	}
	
	// test
	for(int i=4; i<VP+1; i++)
	{
		fifo(i);
		lru(i);
		opt(i); 
		printf("\n");
	}
	return 0;
}

参考书目

操作系统实验指导 — 基于Linux内核(第三版)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值