目的:陆续整理近一年的学习收获
虚拟内存页面置换算法
一:概念
- 最佳置换算法
OPT 策略选择置换下次访问距当前时间最长的那些页,可以看出该算法能导致最少的缺页中断,但是由于它要求操作系统必须知道将来的事件,显然这是不可能实现的。但它仍然能作为一种标准来衡量其他算法的性能。
- 最近最少使用算法
LRU 策略置换内存中上次使用距当前最远的页。根据局部性原理,这也是最不可能访问的页。实际上,LRU 策略的性能接近于 OPT 策略。该方法的问题在于比较难以实现。一种实现方法是给每一页添加一个最后访问的时间戳,并且必须每次访问内存时,都更新这个时间戳。即使有这种方案的硬件,开销仍然是非常大的。另外一种可选的方法是维护一个关于访问页的栈,但开销同样很大。
- 先进先出算法
FIFO 策略把分配给进程的页框视为一个循环缓冲区,按循环方式移动页。它所需的只是一个指针,这个指针在该进程的页框中循环。因此这是一种最简单的页面置换策略。除了它的简单性,这种选择方法所隐含的逻辑是置换驻留在内存中最长时间的页:一个很久以前取入内存的页,到现在可能已经不会再用了。这个推断是错误的,因为经常出现一部分程序或数据在整个程序的生命周期中使用频率很高的情况,如果使用 FIFO 算法,则这些页会被反复的换入换出,增加了系统开销。
二:测试举例
假定系统为某进程分配了三个物理块,并考虑有以下的页面号引用串:
2,3,2,1,5,2,4,5,3,2,5,2
- 分别执行三种页面置换算法后结果:
三:程序设计
- 变量及函数
#define MaxNumber 100
int MinBlockNum,PageNum,LackNum,LackPageNum; //物理块数,页面个数,缺页次数,缺页数
double LackPageRate; //缺页率
int PageOrder[MaxNumber]; //页面序列
int PageDisCount[MaxNumber]; //当前内存距离下一次出现的距离
int LRUtime[MaxNumber]; //存储队列中各个页面最近使用情况
int VirtualQueue[MaxNumber]; //虚拟队列
int Simulate[MaxNumber][MaxNumber];
int choose;
void Enter(); //输入物理块数、页面号顺序
void initial(); //模拟物理块顺序被填满,初始化物理块
void FIFO(); //先进先出FIFO
void OPI(); //最佳置换OPI
void LRU(); //最近最久未使用LRU
void display(); //显示执行结果
void choose_Algorithm();//选择算法
- 三个核心算法
void FIFO(){
cout<<endl;
int i,j,k;
cout<<"当前选择的算法:FIFO"<<endl;
initial();
bool isInQueue;
int point = 0; //指向队列中最老的
//从物理块数+1的地方开始继续分配内存
for (i = MinBlockNum;i<PageNum;i++){
isInQueue = false;
for (k = 0;k<MinBlockNum;k++){
if (VirtualQueue[k] == PageOrder[i]){ //页面在队列中
isInQueue = true;
}
}
if (!isInQueue){ //如果页面不在队列中,则进行相应的处理
LackPageNum++; //缺页数加1
VirtualQueue[point] = PageOrder[i];//页面替换队列中最老的
for(j=0;j<=MinBlockNum;j++){
Simulate[j][i]=VirtualQueue[j];//保存当前序列的值
}
point++;//后移
if (point == MinBlockNum)//当指向队尾时后,重新指向队首
point = 0;
}
}
display();//输出物理块状态
LackPageRate = (LackPageNum * 1.0)/PageNum;
cout<<"LackPageNum: "<<LackPageNum<<endl;
cout<<"LackPageRate: "<<LackPageRate<<endl;
}
void OPI(){
cout<<endl;
int i,j,k,m,s,t;
cout<<"当前选择的算法:OPI"<<endl;
initial();
bool isInQueue;
int distance; //表示队列每个值距离下一次访问的距离
int point; //指向最长时间未被访问的下标
for(i = MinBlockNum;i<PageNum;i++){
isInQueue = false;
for (k = 0;k<MinBlockNum;k++){
if (VirtualQueue[k] == PageOrder[i]){ //页面在队列中
isInQueue = true;
}
}
if (!isInQueue){
LackPageNum++;
//计算当前队列每一页对应的下一次出现的距离
for (s = 0;s < MinBlockNum;s++){
distance = 1;
for (t = i;t<PageNum;t++){ //向后找离他最远的
if (VirtualQueue[s] != PageOrder[t])
distance++;
else
break;
}
PageDisCount[s] = distance;//当前内存距离下一次出现的距离
}
//向后比较队列内最长时间不被访问的并淘汰,置换页面
point = 0;
for (m = 1;m < MinBlockNum;m++){
if (PageDisCount[point] < PageDisCount[m])
point = m;
}
VirtualQueue[point] = PageOrder[i];
for(j=0;j<=MinBlockNum;j++){
Simulate[j][i]=VirtualQueue[j];//保存当前序列的值
}
}
}
display();
LackPageRate = (LackPageNum*1.0)/PageNum;
cout<<"LackPageNum: "<<LackPageNum<<endl;
cout<<"LackPageRate: "<<LackPageRate<<endl;
}
void LRU(){
cout<<endl;
int i,j,s,k,z;
cout<<"当前选择的算法:LRU"<<endl;
initial();
int point;//指向最长时间未被访问的下标
bool isInQueue;
for(i = MinBlockNum;i<PageNum;i++){
isInQueue = false;
for (k = 0;k<MinBlockNum;k++){
if (VirtualQueue[k] == PageOrder[i]) //页面在队列中
isInQueue = true;
}
if (!isInQueue){
LackPageNum++;
//向前比较队列内最长时间不被访问的并淘汰,置换页面
point = 0;
for (j = 1;j<MinBlockNum;j++){
if (LRUtime[point]<LRUtime[j])
point = j;
}
for (s = 0;s<MinBlockNum;s++){//其余页面对应的时间要+1{
if (VirtualQueue[s] != VirtualQueue[point])
LRUtime[s]++;
}
VirtualQueue[point] = PageOrder[i];
for(j=0;j<=MinBlockNum;j++){
Simulate[j][i]=VirtualQueue[j];//保存当前序列的值
}
LRUtime[point] = 0;
}
else{ //负责更新当前对应页面的时间
for (s = 0;s<MinBlockNum;s++){//其余页面对应的时间要+1
if (VirtualQueue[s] != PageOrder[i])
LRUtime[s]++;
else
LRUtime[s] = 0;
}
}
}
display();
LackPageRate = (LackPageNum*1.0)/PageNum;
cout<<"LackPageNum: "<<LackPageNum<<endl;
cout<<"LackPageRate: "<<LackPageRate<<endl;
}
四:测试结果
- 为了方便采用文件流的形式读取数据(物理块数,页面个数,页面序列)
3
20
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
五:实验源码
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
using namespace std;
#define MaxNumber 100
int MinBlockNum,PageNum,LackNum,LackPageNum; //物理块数,页面个数,缺页次数,缺页数
double LackPageRate; //缺页率
int PageOrder[MaxNumber]; //页面序列
int PageDisCount[MaxNumber]; //当前内存距离下一次出现的距离
int LRUtime[MaxNumber]; //存储队列中各个页面最近使用情况
int VirtualQueue[MaxNumber]; //虚拟队列
int Simulate[MaxNumber][MaxNumber];
int choose;
void Enter(); //输入物理块数、页面号顺序
void initial(); //模拟物理块顺序被填满,初始化物理块
void FIFO(); //先进先出FIFO
void OPI(); //最佳置换OPI
void LRU(); //最近最久未使用LRU
void display(); //显示执行结果
void choose_Algorithm();//选择算法
int main(){
Enter();
choose_Algorithm();
return 0;
}
void Enter(){
ifstream readData;
readData.open("datainput.txt");
readData>>MinBlockNum;
readData>>PageNum;
for (int i=0;i<PageNum;i++)
{
readData>>PageOrder[i];
}
cout<<"读取数据结果如下:"<<endl;
cout<<"最小物理块数 = "<<MinBlockNum<<endl;
cout<<"页面个数 = "<<PageNum<<endl;
cout<<"页面序列如下:"<<endl;
for (int i = 0;i<PageNum;i++)
{
cout<<PageOrder[i]<<" ";
}
cout<<endl;
cout<<endl;
}
void initial(){//初始化将物理块填满
int i,j,k;
int moment=0;//判断初始化物理块是否填满
bool isInQueue;
LackPageNum = MinBlockNum;//缺页数=物理块数+缺页次数
LackPageRate = 0.0;
for(i = 0;i<PageNum;i++){
PageDisCount[i] = 0; //初始化距离
VirtualQueue[i] = -1; //初始化队列
}
for(i=0;i<MinBlockNum;i++){
for(j=0;j<PageNum;j++){
Simulate[i][j]=-1;//初始化
}
}
for (i = 0;i<PageNum;i++){//初始化物理块
isInQueue = false;
LRUtime[i] = 0;
for (j = 0;j<MinBlockNum;j++){
if (VirtualQueue[j] == PageOrder[i])//如果页面在队列中
{
isInQueue = true;
}
}
if (!isInQueue){ //当有新的进程进入到队列时,便计算其对应的距离
VirtualQueue[moment] = PageOrder[i];//小于物理块数时,页面顺序进入队列
for(j=0;j<=moment;j++){
Simulate[j][i]=VirtualQueue[j];//保存当前序列的值
}
moment++;
for (k = 0;k<i;k++){
LRUtime[k]++; //之前的页面对应的时间+1
}
}
else{
LRUtime[i] = 0; //重新更新为0,表示最近刚刚使用
}
if(moment==MinBlockNum){
break;
}
}
}
void display(){
int i,j;
for(i=0;i<PageNum;i++){
cout<<PageOrder[i]<<" ";
}
cout<<endl;
for(i=0;i<MinBlockNum;i++){
for(j=0;j<PageNum;j++){
if(Simulate[i][j]==-1){
cout<<" ";
}else{
cout<<" "<<Simulate[i][j];
}
}
cout<<endl;
}
}
void FIFO(){
cout<<endl;
int i,j,k;
cout<<"当前选择的算法:FIFO"<<endl;
initial();
bool isInQueue;
int point = 0; //指向队列中最老的
//从物理块数+1的地方开始继续分配内存
for (i = MinBlockNum;i<PageNum;i++){
isInQueue = false;
for (k = 0;k<MinBlockNum;k++){
if (VirtualQueue[k] == PageOrder[i]){ //页面在队列中
isInQueue = true;
}
}
if (!isInQueue){ //如果页面不在队列中,则进行相应的处理
LackPageNum++; //缺页数加1
VirtualQueue[point] = PageOrder[i];//页面替换队列中最老的
for(j=0;j<=MinBlockNum;j++){
Simulate[j][i]=VirtualQueue[j];//保存当前序列的值
}
point++;//后移
if (point == MinBlockNum)//当指向队尾时后,重新指向队首
point = 0;
}
}
display();//输出物理块状态
LackPageRate = (LackPageNum * 1.0)/PageNum;
cout<<"LackPageNum: "<<LackPageNum<<endl;
cout<<"LackPageRate: "<<LackPageRate<<endl;
}
void OPI(){
cout<<endl;
int i,j,k,m,s,t;
cout<<"当前选择的算法:OPI"<<endl;
initial();
bool isInQueue;
int distance; //表示队列每个值距离下一次访问的距离
int point; //指向最长时间未被访问的下标
for(i = MinBlockNum;i<PageNum;i++){
isInQueue = false;
for (k = 0;k<MinBlockNum;k++){
if (VirtualQueue[k] == PageOrder[i]){ //页面在队列中
isInQueue = true;
}
}
if (!isInQueue){
LackPageNum++;
//计算当前队列每一页对应的下一次出现的距离
for (s = 0;s < MinBlockNum;s++){
distance = 1;
for (t = i;t<PageNum;t++){ //向后找离他最远的
if (VirtualQueue[s] != PageOrder[t])
distance++;
else
break;
}
PageDisCount[s] = distance;//当前内存距离下一次出现的距离
}
//向后比较队列内最长时间不被访问的并淘汰,置换页面
point = 0;
for (m = 1;m < MinBlockNum;m++){
if (PageDisCount[point] < PageDisCount[m])
point = m;
}
VirtualQueue[point] = PageOrder[i];
for(j=0;j<=MinBlockNum;j++){
Simulate[j][i]=VirtualQueue[j];//保存当前序列的值
}
}
}
display();
LackPageRate = (LackPageNum*1.0)/PageNum;
cout<<"LackPageNum: "<<LackPageNum<<endl;
cout<<"LackPageRate: "<<LackPageRate<<endl;
}
void LRU(){
cout<<endl;
int i,j,s,k,z;
cout<<"当前选择的算法:LRU"<<endl;
initial();
int point;//指向最长时间未被访问的下标
bool isInQueue;
for(i = MinBlockNum;i<PageNum;i++){
isInQueue = false;
for (k = 0;k<MinBlockNum;k++){
if (VirtualQueue[k] == PageOrder[i]) //页面在队列中
isInQueue = true;
}
if (!isInQueue){
LackPageNum++;
//向前比较队列内最长时间不被访问的并淘汰,置换页面
point = 0;
for (j = 1;j<MinBlockNum;j++){
if (LRUtime[point]<LRUtime[j])
point = j;
}
for (s = 0;s<MinBlockNum;s++){//其余页面对应的时间要+1{
if (VirtualQueue[s] != VirtualQueue[point])
LRUtime[s]++;
}
VirtualQueue[point] = PageOrder[i];
for(j=0;j<=MinBlockNum;j++){
Simulate[j][i]=VirtualQueue[j];//保存当前序列的值
}
LRUtime[point] = 0;
}
else{ //负责更新当前对应页面的时间
for (s = 0;s<MinBlockNum;s++){//其余页面对应的时间要+1
if (VirtualQueue[s] != PageOrder[i])
LRUtime[s]++;
else
LRUtime[s] = 0;
}
}
}
display();
LackPageRate = (LackPageNum*1.0)/PageNum;
cout<<"LackPageNum: "<<LackPageNum<<endl;
cout<<"LackPageRate: "<<LackPageRate<<endl;
}
void choose_Algorithm()
{
cout<<"请选择算法“1-最佳(Optimal)置换算法,2-先进先出(FIFO)页面置换算法,3-最近最久未使用(LRU)页面置换算法,0-退出”"<<endl;
cout<<endl;
cin>>choose;
cout<<endl;
if (choose==1)
{
OPI();
choose_Algorithm();
}
else if(choose==2)
{
FIFO();
choose_Algorithm();
}
else if(choose==3){
LRU();
choose_Algorithm();
}
else if(choose==0){
exit(0);
}
else
{
cout<<"请输入正确的选择“1-首次适应算法FF,2-循环首次适应算法NF,3-最佳适应算法BF,4-最坏适应算法WF,0-退出”"<<endl;
cout<<"------------------------------------------------------"<<endl;
choose_Algorithm(); //递归
}
}