// PageSwitch.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
/*******************************************************************/
//请分别用FIFO、OPT算法实现“页面置换”的模拟。模拟程序的要求如下:
//
//输入:页面流文件,其中存储的是一系列页面号,用来模拟待换入的页面。
//
//输出:对于每一个页面流文件,标出所使用的算法,
//并且:每换入一个页面(即:每读入一个页面号),判断是否有页面需要被换出。
//若有,把被换出的页面号输出到屏幕;若没有,则要在输出中用特殊标记说明。
//
//初始条件:采用三个页框,初始时均为空。
//
//测试说明:测试教师将事先准备好一组文件,
//从中为每个程序随机指定一至三个作为输入文件
//(被测试者需从键盘输入指定文件的文件名),并查看程序输出结果。
//测试用例:书上p119页,在本地盘建立一个test.txt文件,内容为例中的页面号
//例如:test文本内容为:
// 4 3 2 1 4 3 5 4 3 2 1 5jjjjjjjjj
// kkkk
// jklilkjjj
/******************************************************************/
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "iostream.h"
#define MAX_POS 99 /* 页框表中相应项值在页面流中的相应的位置默认最大值 */
/* 先进先出算法FIFO
* int page[]:页面流存放的数组
* int n: 页面流数
*/
void FIFO(int page[],int n)
{
int mem[3]={0,0,0};
int flag = 0;
int i,j;
int d=0;
int count = 0;
cout<<endl<<"# 代表命中,无页面换出"<<" "<<"!后跟的数字代表被换出的页"<<endl;
cout<<endl<<"FIFO算法:"<<endl;
// mem[2]=page[0];
// mem[1]=page[1];
// mem[0]=page[2];
// cout<<mem[0]<<' '<<mem[1]<<' '<<mem[2]<<endl;
for(i = 0; i<n; i++)
{
flag = 0;
for(j = 0; j<3; j++)
{
if(mem[j] == page[i])
{
flag = 1;
}
}
if(flag)//命中
{
cout<<mem[0]<<' '<<mem[1]<<' '<<mem[2]<<" ->" << page[i] <<" #"<<endl;
}
else//没有命中,产生缺页中断
{
count++;
d = mem[2];
mem[2] = mem[1];
mem[1] = mem[0];
mem[0]=page[i];
cout<<mem[0]<<' '<<mem[1]<<' '<<mem[2]<<" ->" << page[i]<<" !"<<d<<endl;
}
}
cout<<endl<<"共产生缺页中断:"<<count<<"次!"<<endl;
};
int max(int a,int b)
{
return a>b?a:b;
}
/* 最佳置换算法(OPT)(理想置换算法):
所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,
这样可以保证获得最低的缺页率。
* int page[]:页面流存放的数组
* int n: 页面流数
*/
void OPT(int page[],int n)
{
int mem[3]={0,0,0};
int flag = 0;
int i,j,s;
int d=0;
int count = 0;
int c0=MAX_POS;
int c1=MAX_POS;
int c2=MAX_POS;
cout<<endl<<"# 代表命中"<<" "<<"!后跟的数字代表被换出的页"<<endl;
cout<<endl<<"OPT算法:"<<endl;
cout<< "[0] "<<" [1] "<<" [2] " <<" " << " 调入页面号 " <<" 调出页面号 " << "POS[0]" << " " << "POS[1]" << " " << "POS[2]" << endl;
mem[2]=page[0];
cout<< " " << mem[0]<<" "<<mem[1]<<" "<<mem[2]<<" ->" << page[0]<<" !"<<d << " " << c0 << " " << c1 << " " << c2 << endl;
mem[1]=page[1];
cout<< " " << mem[0]<<" "<<mem[1]<<" "<<mem[2]<<" ->" << page[1]<<" !"<<d << " " << c0 << " " << c1 << " " << c2 << endl;
mem[0]=page[2];
cout<< " " << mem[0]<<" "<<mem[1]<<" "<<mem[2]<<" ->" << page[2]<<" !"<<d << " " << c0 << " " << c1 << " " << c2 << endl;
for(i = 3; i<n; i++)
{
flag = 0;
for(j = 0; j<3; j++)
{
if(mem[j] == page[i])
{
flag = 1;//找到
}
}
if(flag)
{
cout<< " " << mem[0]<<" "<<mem[1]<<" "<<mem[2]<<" ->" << page[i] <<" #"<<endl;
}
else//在页面中没有找到,发生缺页中断
{
//判断当前页面流及以后的页面流中有无页面表中的页面号
//判断当前页表中有无页面流中的的项,有,则标记相应页面流中的的位轩信息
for(s = i; s<n; s++)
{
/*
页面表中第一个页面号在后面的页面流中有出现,记录下在页面流中的位置
*/
if (mem[0] == page[s])
{
c0 = s;
}
else
{
//页面表中第二个页面号在后面的页面流中有出现,记录下在页面流中的位置
if(mem[1] == page[s])
{
c1 = s;
}
else
{
//页面表中第三个页面号在后面的页面流中有出现,记录下在页面流中的位置
if(mem[2] == page[s])
{
c2 =s;
}
else if(c0!=99 && c1!=99 && c2!=99)
{
//cout << "------------" << page[s] << " " << c0 << " " << c1 << " " << c2 << endl;
break;
}
}
}
}
/*
*页面调度表中相应项的值在页面流中的位置(分两种情况:
* a.后面再也没有出现,为默认最大值99;
* b. 相应值在页面表中的位置比其它项大,即比其它项要靠后出现),
* 这个时候,我们将表项中该项调出,换入新的页面号
*/
if (c0 >= c1 && c0 >= c2)
{
d = mem[0];
mem[0] = page[i];
cout<< " " << mem[0]<<" "<<mem[1]<<" "<<mem[2]<<" ->" << page[i]<<" !"<<d << " " << c0 << " " << c1 << " " << c2 << endl;
}
else if (c1 >= c0 && c1 >= c2)
{
d = mem[1];
mem[1] = page[i];
cout<< " " << mem[0]<<" "<<mem[1]<<" "<<mem[2]<<" ->" << page[i]<<" !"<<d << " " << c0 << " " << c1 << " " << c2 << endl;
}
else
{
d = mem[2];
mem[2] = page[i];
cout<< " " << mem[0]<<" "<<mem[1]<<" "<<mem[2]<<" ->" << page[i]<<" !"<<d << " " << c0 << " " << c1 << " " << c2 << endl;
}
//中断计数
count++;
//每个页面号在页面调度时,将页面表中的值在页面流中的位置值置恢复为最大(这里为取99)
c0 = c1 = c2 = MAX_POS;
}
}
cout<<endl<<"共产生缺页中断:"<<count+3<<"次!"<<endl;
}
/* 最近最久未使用LRU
* int page[]:页面流存放的数组
* int n: 页面流数
*/
void LRU(int page[],int n)
{
}
void main()
{
FILE *fp;
char pt;
char str[10];
int i = 0;
int j = 0;
int page[50];
int flag = 1;
for(i=0; i<50; i++)
{
page[i] = -1;
}
//cout<<"请输入文件路径:" << endl; //题目要求读入文件路径,打开时有小错误,改成指定文件名方式
// gets(str);
fp = fopen("test.txt","r+");
if(fp==NULL)
{
cout<<endl<<"找不到该文件"<<endl;
exit(0);
}
//每次读入一个字符,将数字依次存放到数组中
while((pt = fgetc(fp)) != EOF)
{
i = 0;
if(pt>='0' && pt<='9')
{
str[i] = pt;
i++;
flag = 1;
str[i] = '\0';
page[j] = atoi(str);
j++;
// cout<<endl<<page[j++];
}
else//回车停止读入
{
if (pt == '\n') break;
}
}
cout<<"读入的页面流数:" << j<<endl;
i = 0;
cout<<"读入的页面流依次为:"<<endl;
while(page[i] != -1)
{
cout<<" "<<page[i];
i++;
}
//先进先出
FIFO(page,j);
//最近最久未使用算法
LRU(page,j);
//最佳置换算法
OPT(page,j);
}