实验内容
理解请求分页式虚拟存储管理方案中的页面置换算法,理解缺页中断率的概念并可以进行正确地统计。具体要求如下:
- 使用数组存储一组页面请求,页面请求的数量要50个以上,访问的页面号可以用随机数生成(0~20):
- 设置为分配给进程的页框数(假定是5),使用LRU算法,模拟完成全部的页面请求,最后输出总共发生了多少次缺页;重新设置页框为10,模拟过程,完成输出,观察页框数量对缺页中断率的影响;
- 在相同页框的情况下,使用FIFO算法模拟全部的页面请求,以此来比对FIFO和LRU之间的差别。
实验源码
#include<iostream>
constexpr int PageTableLength = 20;//页表长度
constexpr int TotalFream = 5;//页框长度
//关于随机数生成频率的设置
constexpr int Frame_Locality_Frequence = 90;
constexpr int Frame_Locality_Begin = 5;
constexpr int Frame_Locality_End = 8;
//关于随机数生成频率的设置
struct PageItem
{
int PageFrame;
bool IsValid;
bool IsWritten;
};
//使用Rdrand指令提供的真随机数,该指令是Inter的IA32和AMD64架构特有的,并且需要在Ivy Bridge微架构之后该条指令才加入Inter标准,
//标准的使用用法应当判断架构类型和微架构类型,此处省略
unsigned int GetRand() {
__asm {
RdRand eax
}
}
//提供具有局部性的随机数,特点是返回的随机数中以MostFrequence的频率分布在BeginMostFrame至EndMostFrame中间
//参数需要满足:BeginFrame<BeginMostFrame<EndMostFrame<EndFrame
int Get_RequestFrame(int MostFrequence, int BeginMostFrame, int EndMostFrame, int BeginFrame, int EndFrame) {
if (GetRand() % 100 < MostFrequence) {
return GetRand() % (EndMostFrame - BeginMostFrame) + BeginMostFrame;
}
else {
if (GetRand() % 100 < 50) {
return GetRand() % (BeginMostFrame - BeginFrame) + BeginFrame;
}
else {
return GetRand() % (EndFrame - EndMostFrame) + EndMostFrame;
}
}
}
//本次实验采用了空间换时间策略,使用了反向页表
//MMU类模拟地址转换的一部分内容,提供基础的数据结构
class MMU
{
public:
void Run(int LoopNum,int FrameLocality=0) {
for (int loop_1 = 0; loop_1 < LoopNum; loop_1++)
{
unsigned int ThisLoop_RequestFrame;
if (FrameLocality) {
ThisLoop_RequestFrame = Get_RequestFrame(Frame_Locality_Frequence, Frame_Locality_Begin, Frame_Locality_End, 0, PageTableLength);
}
else {
ThisLoop_RequestFrame = GetRand() % PageTableLength;
}
if (PageTable[ThisLoop_RequestFrame].IsValid == 0) {
if (Used_Frame_Num < TotalFream) {
CallIn_Algorithm(ThisLoop_RequestFrame);
Used_Frame_Num++;
}
else {
Swap_Algorithm(ThisLoop_RequestFrame);
}
Page_Fault++;
}
Statistics_Algorithm(ThisLoop_RequestFrame);
}
}
void virtual Swap_Algorithm(int RequestFrame) { ; }
void virtual Statistics_Algorithm(int RequestFrame) { ; }
void virtual CallIn_Algorithm(int RequestFrame) {
Reversed_PageTable[Used_Frame_Num] = RequestFrame;
PageTable[RequestFrame].IsValid = 1;
PageTable[RequestFrame].PageFrame = Used_Frame_Num;
}
int Page_Fault=0;
int Used_Frame_Num=0;
int Reversed_PageTable[TotalFream];
PageItem PageTable[PageTableLength];
MMU() {
for (int i = 0; i < PageTableLength; i++)
{
PageTable[i].IsValid = 0;
PageTable[i].IsWritten = 0;
PageTable[i].PageFrame = 0;
}
}
};
//MMU类模拟地址转换的一部分内容,提供基础的数据结构
class FIFO:public MMU
{
public:
int Longest_PageFrame = 0;
void Swap_Algorithm(int RequestFrame) {
PageTable[Reversed_PageTable[Longest_PageFrame]].IsValid = 0;
PageTable[RequestFrame].IsValid = 1;
PageTable[RequestFrame].PageFrame = Longest_PageFrame;
Reversed_PageTable[Longest_PageFrame] = RequestFrame;
Longest_PageFrame = (Longest_PageFrame + 1) % TotalFream;
}
};
class LRU:public MMU
{
public:
LRU() {
for (int i = 0; i < PageTableLength; i++)
{
Counter_PageNum[i] = 0;
}
}
int Counter_PageNum[PageTableLength];
void Swap_Algorithm(int RequestFrame) {
int Min = -1;
int Min_Index = 0;
for (int loop_1 = 0; loop_1 < TotalFream; loop_1++)
{
if (Counter_PageNum[Reversed_PageTable[loop_1]] > Min)
Min_Index = loop_1;
}
PageTable[RequestFrame].IsValid = 1;
PageTable[RequestFrame].PageFrame = Min_Index;
PageTable[Reversed_PageTable[Min_Index]].IsValid = 0;
Counter_PageNum[RequestFrame] = 0;
Reversed_PageTable[Min_Index] = RequestFrame;
}
void Statistics_Algorithm(int RequestFrame) {
Counter_PageNum[RequestFrame]++;
}
};
int main() {
FIFO _FIFO;
LRU _LRU;
int RequestNum = 10000;
_FIFO.Run(RequestNum,1);
printf("FIFO算法运行%d次发生缺页的次数为%d,缺页发生率为:%.2f\n", RequestNum, _FIFO.Page_Fault,_FIFO.Page_Fault/(RequestNum*1.0));
_LRU.Run(RequestNum,1);
printf("LRU算法运行%d次发生缺页的次数为%d,缺页发生率为:%.2f\n", RequestNum, _LRU.Page_Fault, _LRU.Page_Fault / (RequestNum*1.0));
}
需要注意的是在LRU算法中并没有使用效率最高的老化算法,原因是在模拟中并不需要考虑LRU算法的实现效率问题。
另外还需要解释一下Get_RequestFrame
这个函数,该函数能够生成符合程序局部性原理的随机数集合,实现思路也并不复杂:生成一个(0,100)
范围内的随机数来决定当前生成数的范围。其生成的频率分布图大致如下所示(画工太渣,不要介意):
实验结果
在10000次请求中,实验结果如下所示:
页框数 | 缺页次数 | 缺页率 | 请求次数 |
---|---|---|---|
3 | 2745 | 0.27 | 10000 |
3 | 1769 | 0.18 | 10000 |
5 | 1640 | 0.16 | 10000 |
5 | 851 | 0.09 | 10000 |
10 | 725 | 0.07 | 10000 |
10 | 458 | 0.05 | 10000 |
对应的结果图片如下所示:
结果分析
从表格可以看到,在程序集中访问率为90%的情况下,能够较好的还原出课堂上的统计结果:
- 页框数越少,缺页率越严重,两种算法的差距越明显;
- 当页框数增加到一定程度后,两种算法的差距将可以忽略;