程序运行过程中,有时要访问的页面不在内存中,而需要将其调入内存。但是内存已经无空闲空间存储页面,为保证程序正常运行,系统必须从内存中调出一页程序或数据送到磁盘对换区,此时需要一定的算法来决定到低需要调出那个页面。通常将这种算法称为“页面置换算法”。
功能:当出现缺页异常,需调入新页面而内存已满时,置换算法选择被置换的物理页面
目标:尽可能减少页面的调入调出次数(即缺页中断次数),把未来不再访问或短期内不访问的页面调出
基本思路 : 当一个缺页中断发生时, 对于保存在内存当中的每一个逻辑页面, 计算在它的下一次访问之前, 还需等待多长时间, 从中选择等待时间最长的那个, 作为被置换的页面.
这是一种理想情况, 在实际系统中是无法实现的, 因为操作系统无法知道每一个页面要等待多长时间以后才会再次被访问.
可用作其他算法的性能评价的依据.(在一个模拟器上运行某个程序, 并记录每一次的页面访问情况, 在第二遍运行时即可使用最优算法)
基本思路 : 选择在内存中驻留时间最长的页面淘汰. 具体来说, 系统维护着一个链表, 记录了所有位于内存当中的逻辑页面. 从链表的排列顺序来看, 链首页面的驻留时间最长, 链尾页面的驻留时间最短. 当发生一个缺页中断时, 把链首页面淘汰出去, 并把新的页面添加到链表的末尾.
性能较差, 调出的页面有可能是经常要访问的页面. 并且有 belady现象. FIFO算法很少单独使用.
LRU(Least Recently Used),通过局部性原理反推,以历史推测未来
基本思路 : 当一个缺页中断发生时, 选择最久未使用的那个页面, 并淘汰.
它是对最优页面置换算法的一个近似, 其依据是程序的局部性原理, 即在最近一小段时间(最近几条指令)内, 如果某些页面被频繁地访问, 那么再将来的一小段时间内, 他们还可能会再一次被频繁地访问. 反过来说, 如果过去某些页面长时间未被访问, 那么在将来它们还可能会长时间地得不到访问.
LRU算法需要记录各个页面使用时间的先后顺序, 开销比较大.
两种可能的实现方法是 :
① 系统维护一个页面链表, 最近刚刚使用过的页面作为首节点, 最久未使用的作为尾结点. 再一次访问内存时, 找出相应的页面, 把它从链表中摘下来, 再移动到链表首. 每次缺页中断发生时, 淘汰链表末尾的页面.
② 设置一个活动页面栈, 当访问某页时, 将此页号压入栈顶, 然后, 考察栈内是否有与此页面相同的页号, 若有则抽出. 当需要淘汰一个页面时, 总是选择栈底的页面, 它就是最久未使用的.
#include
#include
using namespace std;
class replacePage
{
private:
int _phyBlockNum;
vector<int> _memoryList;
vector<int> _pageNumStrList;
public:
replacePage(int n,vector<int> &m,vector<int> &p):_phyBlockNum(n),_memoryList(m),_pageNumStrList(p){}
void Showlist()
{
int len = _pageNumStrList.size();
for (int i = 0; i < len; ++i)
{
cout << _pageNumStrList[i] <<" ";
}
cout << endl;
}
void ShowMemoryList()
{
for (int i = 0; i < _phyBlockNum; ++i)
{
if (_memoryList[i] == -1)
{
cout << " [ ]";
}
else cout << " [" << _memoryList[i] << "]";
}
cout << endl;
}
void FIFO()
{
//置换次数
int replaceCount = 0;
//缺页次数
int missingCount = 0;
//记录当前最早进入内存的下标
int pointer = 0;
int isVisited = 0;
Showlist();
for (int i = 0; i < _pageNumStrList.size(); ++i)
{
isVisited = 0;
for (int j = 0; j < _phyBlockNum; ++j)
{
if (_memoryList[j] == _pageNumStrList[i])
{
isVisited = 1;
cout << _pageNumStrList[i] << endl;
ShowMemoryList();
break;
}
if (_memoryList[j] == -1)
{
missingCount++; //缺页
isVisited = 1;
_memoryList[j] = _pageNumStrList[i];
cout << _pageNumStrList[i] << endl;
ShowMemoryList();
break;
}
}
if (!isVisited)// memoryList 中没有页面
{
_memoryList[pointer] = _pageNumStrList[i];
pointer++;
if (pointer == _phyBlockNum)
{
pointer = 0;
}
replaceCount++;
missingCount++;
cout << _pageNumStrList[i] << endl;
ShowMemoryList();
}
}
cout << "置换:" << replaceCount << endl;
cout << "缺页:" << missingCount << endl;
for (int i = 0; i < _phyBlockNum; ++i)
{
_memoryList[i] = -1;
}
}
void LRU()
{
//置换次数
int replaceCount = 0;
//缺页次数
int missingCount = 0;
vector<int> Times(_phyBlockNum, 0);
int isVisited = 0;
Showlist();
for (int i = 0; i < _pageNumStrList.size(); ++i)
{
isVisited = 0;
for (int j = 0; j < _phyBlockNum; ++j)
{
if (_pageNumStrList[i] == _memoryList[j])
{
isVisited = 1;
Times[j] = 0;
cout << _pageNumStrList[i] << endl;
ShowMemoryList();
break;
}
if (_memoryList[j] == -1)
{
isVisited = 1;
_memoryList[j] = _pageNumStrList[i];
missingCount++;
cout << _pageNumStrList[i] << endl;
ShowMemoryList();
break;
}
}
for (int k = 0; k < _phyBlockNum; ++k)
{
if(_memoryList[k] != -1)
Times[k]++;
}
if (!isVisited)
{
int k = 0;
int tmp_max = INT_MIN;
for (int i = 0; i < _phyBlockNum; ++i)
{
if (Times[i] > tmp_max)
{
tmp_max = Times[i];
k = i;
}
}
_memoryList[k] = _pageNumStrList[i];
Times[k] = 1;
replaceCount++;
missingCount++;
cout << _pageNumStrList[i] << endl;
ShowMemoryList();
}
}
cout << "置换:" << replaceCount << endl;
cout << "缺页:" << missingCount << endl;
for (int i = 0; i < _phyBlockNum; ++i)
{
_memoryList[i] = -1;
}
}
void OPT()
{
//置换次数
int replaceCount = 0;
//缺页次数
int missingCount = 0;
Showlist();
int isVisited = 0;
for (int i = 0; i < _pageNumStrList.size(); ++i)
{
isVisited = 0;
for (int j = 0; j < _phyBlockNum; ++j)
{
if (_memoryList[j] == _pageNumStrList[i])
{
isVisited = 1;
cout << _pageNumStrList[i] << endl;
ShowMemoryList();
break;
}
if (_memoryList[j] == -1)
{
isVisited = 1;
_memoryList[j] = _pageNumStrList[i];
missingCount++;
cout << _pageNumStrList[i] << endl;
ShowMemoryList();
break;
}
}
if (!isVisited)
{
vector<int> Times(_phyBlockNum, INT_MAX);
int isFind = 0;
for (int k = i; k < _pageNumStrList.size(); ++k)
{
for (int j = 0; j < _phyBlockNum; ++j)
{
if (_memoryList[j] == _pageNumStrList[k])
{
if (Times[j] == INT_MAX)
{
Times[j] = k;
}
}
}
}
int k = 0;
int tmp_max = INT_MIN;
for (int j = 0; j < _phyBlockNum; ++j)
{
if (Times[j] > tmp_max)
{
tmp_max = Times[j];
k = j;
}
}
_memoryList[k] = _pageNumStrList[i];
missingCount++;
replaceCount++;
cout << _pageNumStrList[i] << endl;
ShowMemoryList();
}
}
cout << "置换:" << replaceCount << endl;
cout << "缺页:" << missingCount << endl;
for (int i = 0; i < _phyBlockNum; ++i)
{
_memoryList[i] = -1;
}
}
};
int main()
{
int phyBlockNum = 3;
vector<int> memoryList(phyBlockNum, -1);
vector<int> pageNumStrList({7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1});
replacePage a(phyBlockNum, memoryList, pageNumStrList);
//a.FIFO();
//a.LRU();
a.OPT();
}