实验四:页面置换算法

  • 1 实验简介
  • 2 实验原理
  • 2.1 页面替换算法
  • 2.2引用串的生成算法
  • 3 实验结果
  • 4 性能评测
  • 4.1 测试结果
  • a. F=3
  • b. F=5
  • 4.2 问题
  • 5 总结和感想
  • 附录 源代码


1 实验简介

本实验要求实现多种页面替换算法,然后利用随机产生的引用串测试其性能。

2 实验原理

2.1 页面替换算法

我们做如下假设:
• 虚拟内存页面总数为P,标号从謰到P−1
• 引用串RS(reference string)是一个整数序列,整数的取值范围为0到P−1。RS中的每个元素p表示对页面p的一次引用
• 物理内存由F帧组成,标号从0到F−1。我们引入一个数组M|F|,数组元素M[f]中包含数字p,它表示帧f中包含页面p
页面替换算法顺次读取RS中的每个元素。对于RS中的元素值p,算法搜索数组M[F],判断是否存在某个f,使得M[f]==p。如果未发现,则表示页面缺失。这时,算法必须根据其特定的替换规则,选择一帧M[i],用页面p替换其中的内容,即令M[i]=p。
下面讨论各种替换算法所需要的不同数据结构:
• 最佳替换算法和随机替换算法不需要其它的数据结构。对于最佳替换算法,通过搜索RS即足以确定应被替换的页面;对于随机替换算法,产生一个取值范围在0和F-1之间的随机数,该随机数即可表示应被替换的页面。
• FIFO需要一个指向最老页面的指针(数组索引)。每当该页面被替换的时候,把该指针加1(模F)即可。
• LRU算法则需要一个尺寸为F的数组,该数组用来实现排队功能:每次处理一个新的页面引用时,则把该页放置在队列的末尾。这样,每当需要淘汰一个页面时,从队首取到的即最长时间未被用到的页面。
• Clock算法(也叫second−chance算法)和FIFO算法一样,需要一个指针。此外,它还需要一个数组,用来记录每一帧的使用情况。

2.2引用串的生成算法

引用串可用如下算法产生:

  1. 确定虚拟内存的尺寸P,工作面的起始位置p,工作面中包含的页数e,工作面移动率m,以及一个范围在0和1之间的值t
  2. 生成m个取值范围在p和p+e间的随机数,并记录到引用串中
  3. 生成一个随机数r,0≤ r ≤1
  4. 如果r < t,则为p生成一个新值,否则p=(p+1)mod P
  5. 如果想继续加大引用串的长度,请返回第2步,否则结束

3 实验结果

  1. 物理内存F=5,页面总数P=20,起始位置p=1,e=16,m=4,t=0.64
  2. 物理内存F=5,页面总数P=50,起始位置p=1,e=16,m=4,t=0.64

4 性能评测

  • 使用同一物理内存和引用串,缺页中断次数可以代表缺页率来表明各个算法的效率。

4.1 测试结果

a. F=3

测试一:F=3,RS[12] = { 10,5,2,8,5,8,9,9,7,9,4,3 };

python实现操作系统的页面置换算法 页面置换算法实验_替换算法


测试二:F=3,RS[12] = { 8,4,2,7,8,9,9,9,7,9,4,3 };

python实现操作系统的页面置换算法 页面置换算法实验_python实现操作系统的页面置换算法_02


测试三:F=3,RS[12] = { 8,10,6,7,8,3,8,9,7,9,4,9 };

python实现操作系统的页面置换算法 页面置换算法实验_替换算法_03


测试四:F=3, RS[12] = { 3,10,4,7,6,3,8,9,7,8,4,9 };

python实现操作系统的页面置换算法 页面置换算法实验_数组_04


测试五:F=3,RS[12] = { 3,10,4,5,5,3,6,9,7,8,9,9 };

python实现操作系统的页面置换算法 页面置换算法实验_数组_05

F=3

最优

随机

FIFO

LRU

Clock

1

5

8

5

5

7

2

3

8

5

5

8

3

4

9

6

6

8

4

5

8

7

8

8

5

5

9

6

6

8

平均数

4.4

8.4

5.8

6

7.8

b. F=5

测试一:F=5,RS[12] = { 10,5,2,8,5,8,9,9,7,9,4,3 };

python实现操作系统的页面置换算法 页面置换算法实验_数组_06


测试二:F=5,RS[12] = { 8,4,2,7,8,9,9,9,7,9,4,3 };

python实现操作系统的页面置换算法 页面置换算法实验_数组_07


测试三:F=5,RS[12] = { 8,10,6,7,8,3,8,9,7,9,4,9 };

python实现操作系统的页面置换算法 页面置换算法实验_#include_08


测试四:F=5,RS[12] = { 3,10,4,7,6,3,8,9,7,8,4,9 };

python实现操作系统的页面置换算法 页面置换算法实验_python实现操作系统的页面置换算法_09


测试五:F=5,RS[12] = { 3,10,4,5,5,3,6,9,7,8,9,9 };

python实现操作系统的页面置换算法 页面置换算法实验_#include_10

F=3

最优

随机

FIFO

LRU

Clock

1

3

7

4

4

3

2

1

5

2

1

1

3

2

7

3

2

4

4

2

8

2

3

4

5

3

8

4

3

5

平均数

2.2

7.0

3.0

2.4

3.4

F=5 最优 随机 FIFO LRU Clock

4.2 问题

  1. FIFO算法是否比随机替换算法优越?LRU算法比FIFO 算法优越多少?
    FIFO算法比随机替换算法优越一些;LRU算法比FIFO算法的效率高5%~10%,由理论知识可知,页面访问序列具有局部性,而FIFO算法并不符合实际情况。
  2. LRU算法和最优算法有何差距?
    LRU算法是所有算法中效率最接近最优算法的算法,由理论知识可知,最优算法是理想的算法,现实中几乎不可能实现,只能作为一种测评标准,LRU算法是效率较高的可实现置换算法,但其硬件要求较高,如果规模较小,则略显麻烦。
    3.Clock算法和LRU算法有何差距?
    Clock算法和LRU算法从结果来看有些差距,Clock算法是使用软件的方式实现LRU算法中硬件的功能,从而在执行效率上会稍弱一些。

5 总结和感想

这次实验的题目是页面置换算法,属于存储器管理的内容。通过这次实验,我对页面置换算法的了解更为深刻。此次实验涉及到了常见的五种算法,包括OPT、随机置换、FIFO、LRU、Clock算法,每种算法都有各自的优缺点。实验中比较容易的是编写实现引用串的函数,比较困难是如何实现各种算法,需要我们掌握每个算法的流程和原理,通过查阅资料和向同学请教最终完成了这个实验,让我觉得受益匪浅。

附录 源代码

// 页面替换算法.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <time.h> 
#include <windows.h> 
double get_random_r()
{
	int x;
	x = rand();
	//printf("x:%d\n", x);
	double r = x / (RAND_MAX + 1.0);
	return r;
}
//确定虚拟内存的尺寸P,工作面的起始位置p,工作面中包含的页数e,工作面移动率m,以及一个范围在0和1之间的值t
void Get_RS(int *RS, int P, int p, int e, int m, float t)
{
	int i = 0, j = 0;
	int real_num = 0;
	while (real_num < P)
	{
		for (i = 0; i < m && real_num < P; i++, real_num++)
		{
			RS[real_num] = rand() % (p + e + 1) + p;
		}
		if (real_num >= P)
		{
			break;
		}
		double r = get_random_r();
		//printf("r:%f\n", r);
		if (r<t)
		{
			p = rand() % P;
		}
		else
		{
			p = (p + 1) % P;
		}
		for (j = 0; j<10; j++)
		{
			Sleep(60);
		}
	}
}
int OPT(int *RS, int R, int *M, int F)
{
	int P = 0;	//缺页中断的次数
	int m, m1;
	int r, r1;
	int flag, flag2;
	int fm, rmax;
	int num = 0;
	for (r = 0; r<R; r++)
	{
		flag = 0;
		for (m = 0; m<num; m++)
		{
			if (M[m] == RS[r])
			{
				flag = 1;
				break;
			}
		}
		if (num <F && flag == 0)
		{
			M[num] = RS[r];
			num++;
			continue;
		}
		if (flag == 0 && num == F)
		{
			P++;
			rmax = 0;
			fm = 0;
			for (m1 = 0; m1 < F; m1++)
			{
				flag2 = 0;
				for (r1 = r; r1 < R; r1++)
				{
					if (RS[r1] == M[m1])
					{
						break;
					}
				}
				if (r1 > rmax)
				{
					rmax = r1;
					fm = m1;
				}
			}
			//printf("fm:%d\n",fm);
			M[fm] = RS[r];
		}
	}
	return P;

}

int Random(int *RS, int R, int *M, int F)
{
	int P = 0;
	int m, r;
	int flag;
	for (r = 0; r<R; r++)
	{
		flag = 0;
		for (m = 0; m<F; m++)
		{
			if (M[m] == RS[r])
			{
				flag = 1;
				break;
			}
		}
		if (!flag)
		{
			P++;
			int Page = rand() % F;
			M[Page] = RS[r];
		}
	}
	return P;

}

int FIFO(int *RS, int R, int *M, int F)
{
	int P = 0;
	int m, r, flag, pos;
	for (m = 0; m<F; m++)
	{
		M[m] = RS[m];
	}
	pos = 0;
	for (r = 0; r<R; r++)
	{
		flag = 0;
		for (m = 0; m<F; m++)
		{
			if (M[m] == RS[r])
			{
				flag = 1;
				break;
			}
		}
		if (!flag)
		{
			P++;
			M[pos] = RS[r];
			pos++;
			pos = pos%F;
		}
	}
	return P;

}

int LRU(int *RS, int R, int *M, int F)
{
	int P = 0;	//缺页中断的次数
	int m, r, i, flag;
	int num = 0;
	int *temp;
	temp = (int *)malloc(sizeof(int) * F);
	for (r = 0; r < R; r++)
	{
		flag = 0;
		for (m = 0; m < num; m++)
		{
			if (RS[r] == M[m])
			{
				flag = 1;
				break;
			}
		}

		if (flag == 1)
		{

			for (i = 0; i < num; i++)
			{
				temp[i] ++;
			}

			temp[m] = 0;

		}

		if (num == F && flag == 0)
		{

			P++;
			int max = -1, max_i;
			for (i = 0; i < F; i++)
			{
				if (temp[i] > max)
				{
					max_i = i;
					max = temp[i];
				}
				temp[i] ++;
			}

			M[max_i] = RS[r];
			temp[max_i] = 0;

		}

		if (num < F && flag == 0)
		{
			for (i = 0; i < num; i++)
			{
				temp[i] ++;
			}

			M[num] = RS[r];
			temp[num] = 0;
			num++;
		}

	}
	return P;
}


int Clock(int *RS, int R, int *M, int F)
{
	int P = 0;	//缺页中断的次数
	int m, r, flag, pos, num;
	int *temp;
	int i;
	temp = (int*)malloc(sizeof(int)*F);
	num = 0;
	for (r = 0; r<R; r++)
	{
		flag = 0;

		for (m = 0; m<num; m++)
		{
			if (M[m] == RS[r])
			{
				flag = 1;
				break;
			}
		}

		if (flag == 0 && num == F)
		{
			P++;
			pos = 0;

			for (i = 0; i < F; i++)
			{

				if (temp[i] == 1)
				{
					temp[i] = 0;
				}
				else
				{
					pos = i;
					break;
				}

			}

			M[pos] = RS[i];
			temp[pos] = 1;

		}
		if (flag == 0 && num < F)
		{
			M[num] = RS[r];
			temp[num] = 1;
			num++;
		}

	}
	return P;
}

int main()
{
	int *M;
	int F = 5;
	M = (int*)malloc(sizeof(int)*F);
	int *RS;
	int P,p,e,m;
	float t;
	P = 20 ;//虚拟内存页面总数
	p = 1 ;
	e = 10 ;
	m = 4 ;
	t = 0.64 ;
	RS = ( int * ) malloc ( sizeof ( int ) * P ) ;

	Get_RS(RS,P,p,e,m,t);
	printf("生成的引用串RS:");
	for( int i = 0 ; i < P ; i ++ )
	{
	printf("%d ",RS[i]);
	}
	printf("\n");
/*	int RS[10] = { 5,2,10,8,5,8,9,9,7,9 };
	int P = 10;*/
	printf("--------------------------\n");
	printf("页面替换次数如下\n");
	printf("最优:%d\n", OPT(RS, P, M, F));
	printf("随机:%d\n", Random(RS, P, M, F));
	printf("FIFO:%d\n", FIFO(RS, P, M, F));
	printf("LRU:%d\n", LRU(RS, P, M, F));
	printf("Clock:%d\n", Clock(RS, P, M, F));
	return 0;
}