什么是FIFO
该算法总是淘汰最新进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰,该算法简单,只需把一个进程已调入内存的页面按先后次序链接成一个队列,并设置一个指针,称为替换指针,使它总是指向最老的页面。但该算法与进程实际运行的规律不相适应,因为在进程中没有写页面经常被访问,比如,含有全局变量、常用函数、例程等的页面,FIFO算法并不能保证这些页面不被淘汰。
基本思想
-
当进程访问一个页面时,会有三种情况:
(a)有空闲的内存页,且内存中没有该页面
(b)没有空闲的内存页,但是内存中已有该页面
(c)没有空闲的内存页,内存中也没有该页面,要进行页面置换
-
举例如下:
测试用例:页面队列为:7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1;分配的内存物理块数为3。
-
FIFO就是寻找在内存中存在时间最久的那一个页面,将之替换出去,我们可以设置一个countOldPoint变量,初始值为0,来指示呆在内存中最久的页面;
-
设置一个变量PRO_MEMORY来指示分配的内存物理块数。比如说,
-
此时内存可用的空间已满,那么countOldPoint初始值为0,也就是开始时指示7这个页面,当内存空间满时,且要调入内存空间的页面不在此时的内存中时,则要发生替换,则将7替换出去,然后,令countOldPoint++,此时countOldPoint指示的是页面0.所以实现时,即当发生页面替换时,就会令countOldPoint++,并且令countOldPoint % PRO_MEMORY(当countOldPoint指向内存中最后一个物理块时,下一次)。这样便实现了之前所说的“替换指针”的作用。下面用图解释这段话:
- 从(1)状态到(2)状态,是内存调入了页面2,并把页面7替换出去,接着替换指针便指向了第二个内存物理块中存的页面;
- 从(2)状态到(3)状态,是因为内存需要页面0,但此页面已在内存中,所以不发生页面置换,所以替换指针也不发生变化;
- 从(3)状态到(4)状态,是内存调入了页面3,并把当前替换指针指向的页面0替换出去了,接着替换指针指向了第三个内存物理块中存的页面;
- 从(4)状态到(5)状态,是内存调入了页面0,并把当前替换指针指向的页面1替换出去了,因为总共分配了三块物理块,所以现在替换指针便又开始指向第一个内存物理块中的页面;
- 依次循环,执行完后面所有的页面。
源代码:
1、工具类:Page
#include"Page.h"
intPage::getId()const{
returnthis->id;
}
voidPage::setId(int id){
this->id = id;
}
intPage::getCount()const{
return count;
}
voidPage::inc(){
count++;
}
voidPage::setCount(int count){
this->count = count;
}
Page::Page(int id){
this->id = id;
}
Page::~Page(){
}
2、核心算法
#include"Page.h"
#include<iostream>
#include<vector>
#include<iostream>
#include"FIFO.h"
#include<fstream>
#include<conio.h>
usingnamespace std;
typedefvector<Page> LISTPAGE;
typedefvector<int> USEPAGE;
LISTPAGE pages;
USEPAGE usePageNumList;
ofstream ofs("F:\\coodblock\\Test\\record.txt",ios::app);
void FIFO::init()
{
if(!ofs)return;
//初始化count
count =0;
cout <<"请输入分配的内存块数:";
cin >> PRO_MEMORY;
ofs <<"请输入分配的内存块数:"<< PRO_MEMORY <<"\n";
cout <<"请输入页面队列的长度:";
cin >> length;
cout <<"请输入页面使用列表,以空格分开:";
ofs <<"请输入页面使用列表,以空格分开:";
int da;
for(int i =0; i < length; i++)
{
cin >> da;
usePageNumList.push_back(da);
ofs << da <<" ";
}
ofs <<"\n页面置换过程如下:\n";
for(int j =0; j < PRO_MEMORY; j++)
{
Page*p =newPage(-1);
pages.push_back(*p);
}
}
/**
* 显示当前内存中保留的的页面
*/
void FIFO::display()
{
cout <<"当前内存保留的页面是:";
ofs <<"当前内存保留的页面是:";
for(int i =0; i < pages.size(); i++)
{
cout << pages[i].getId()<<" ";
ofs << pages[i].getId()<<" ";
}
ofs <<"\n";
cout << endl;
}
bool FIFO::search(int pageId)
{
for(int i =0; i < pages.size(); i++)
{
if(pages[i].getId()== pageId)
returntrue;
}
returnfalse;
}
void FIFO::replace(int pageId)
{
//置换在内存中呆的时间最久的页面
int outPageId =-1;
outPageId = pages[countOldPoint].getId();
pages[countOldPoint].setId(pageId);
cout <<"页号ID:"<< pageId <<"正在放入内存,页号ID:"<< outPageId <<"被替换出去"<< endl;
ofs <<"页号ID:"<< pageId <<"正在放入内存,页号ID:"<< outPageId <<"被替换出去\n";
}
void FIFO::running()
{
for(int i =0; i < length; i++)
{
countOldPoint = countOldPoint % PRO_MEMORY;
int inPageId = usePageNumList[i];
int key = getch();
if(key==13){
if(search(inPageId))
{
cout <<"内存中有ID为"<< inPageId <<",这个页面不能置换"<< endl;
ofs <<"内存中有ID为"<< inPageId <<",这个页面不能置换\n";
}
elseif(count < PRO_MEMORY)//有空闲内存页
{
pages[count++].setId(inPageId);
cout <<"页号ID:"<< inPageId <<"正在放入内存中"<< endl;
ofs <<"页号ID:"<< inPageId <<"正在放入内存中\n";
}
else//替换
{
replace(inPageId);
lackTime++;
countOldPoint++;
}
display();
}else{
i--;
cout<<"请按enter键"<<endl;
}
}
cout <<"缺页次数为:"<< lackTime <<",缺页率为:"<<(float) lackTime /(length - PRO_MEMORY)<< endl;
ofs <<"缺页次数为:"<< lackTime <<",缺页率为:"<<(float) lackTime /(length - PRO_MEMORY)<<"\n";
ofs <<"============================================================";
ofs.close();
}