实验四:页面置换算法
- 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引用串的生成算法
引用串可用如下算法产生:
- 确定虚拟内存的尺寸P,工作面的起始位置p,工作面中包含的页数e,工作面移动率m,以及一个范围在0和1之间的值t
- 生成m个取值范围在p和p+e间的随机数,并记录到引用串中
- 生成一个随机数r,0≤ r ≤1
- 如果r < t,则为p生成一个新值,否则p=(p+1)mod P
- 如果想继续加大引用串的长度,请返回第2步,否则结束
3 实验结果
- 物理内存F=5,页面总数P=20,起始位置p=1,e=16,m=4,t=0.64
- 物理内存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 };
测试二:F=3,RS[12] = { 8,4,2,7,8,9,9,9,7,9,4,3 };
测试三:F=3,RS[12] = { 8,10,6,7,8,3,8,9,7,9,4,9 };
测试四:F=3, RS[12] = { 3,10,4,7,6,3,8,9,7,8,4,9 };
测试五:F=3,RS[12] = { 3,10,4,5,5,3,6,9,7,8,9,9 };
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 };
测试二:F=5,RS[12] = { 8,4,2,7,8,9,9,9,7,9,4,3 };
测试三:F=5,RS[12] = { 8,10,6,7,8,3,8,9,7,9,4,9 };
测试四:F=5,RS[12] = { 3,10,4,7,6,3,8,9,7,8,4,9 };
测试五:F=5,RS[12] = { 3,10,4,5,5,3,6,9,7,8,9,9 };
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 问题
- FIFO算法是否比随机替换算法优越?LRU算法比FIFO 算法优越多少?
FIFO算法比随机替换算法优越一些;LRU算法比FIFO算法的效率高5%~10%,由理论知识可知,页面访问序列具有局部性,而FIFO算法并不符合实际情况。 - 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;
}