应付学校实验报告的,通过简单的数组进行实现,当然这样时间效率太低,特别是OPT中时间复杂度达到了三次方,寄。其实可以用链表或者vector等其它的容器优化,但是作业要求只用数组,寄。
实验要求:
① 程序能按要求随机产生符合要求的地址流,并将其转换为对应页号流.
② 程序利用产生的页号流,模拟页面置换的三个算法——FIFO、LUR、OPT 算法,计算三个置换算法在页框号在 4-40 的范围内的命中率。
需要定义5个数组:
addressArr[] : 地址流数组,用于存放随机生成的 400 个范围在 0-399 的指令地址
pageArr[] : 页号流数组,用于存放 400 个由地址流转换过来的范围在 0-39 的页号
fifoArr[] : FIFO 算法的页框数组,用于存放 FIFO 算法置换过程中的页框
lruArr[] : LRU 算法的页框数组,用于存放 LRU 算法置换过程中的页框
optArr[] : OPT 算法的页框数组,用于存放 OPT 算法置换过程中的页框
需要包含以下几个函数:
random : 用于生成 400 个范围在 0-399 的地址流,并除10取商将其转换位 400 个范围在 0-39 的页号流。
FIFO、LRU、OPT
#include
#include
#include
#include
#include
using namespace std;
int fifoArr[40], lruArr[40], optArr[40];
int addressArr[400];
//int pageArr[400] = {0, 1, 2, 0, 1, 3, 0, 3, 1, 2, 1};
//int pageArr[400] = {1,2,3,4,1,2,5,1,2,3,4,5};
int pageArr[400];
//得到地址流数组和页号流数组
void random(){
srand(time(NULL)) ;
int t_ad = 0; // 地址流的序号
for(int i = 0; i < 100; i ++ )
{
int m = rand() % 200;
addressArr[t_ad++] = m; //产生一个【0,199】的随机数
addressArr[t_ad++] = m + 1;
m = (rand() % 200) + 200;
addressArr[t_ad++] = m; //产生一个【200,399】的随机数
addressArr[t_ad++] = m + 1;
}
for(int i = 0; i < 400; i ++ ) pageArr[i] = addressArr[i] / 10; //得到页号流
// for(auto t : addressArr) cout << addressArr[t] << " ";
// for(auto t : pageArr) cout << pageArr[t] << " ";
}
int FIFO_test(int pagek){ //传入页框长度,return返回命中次数
pagek--; //从0开始算,减一
memset(fifoArr, -1, sizeof fifoArr); //初始化fifoArr页框数组,全部赋值为-1
int hintCnt = 0; //命中次数
int pageTmp = 0; //页框使用的序号
for (int i = 0; i < 400; ++i) {
bool hintFlag = false; //命中标记
for (int j = 0; j <= pagek; ++j) {
if (pageArr[i] == fifoArr[j])
{
hintCnt ++, hintFlag = true;
break; //如果页框数组fifoArr中有重复的页号,则命中
}
}
if(pageTmp <= pagek && !hintFlag) //页框数组未满,未命中
fifoArr[pageTmp++] = pageArr[i]; //插入到页框数组中
else if (pageTmp > pagek && !hintFlag) //页框数组满,未命中
{
//页框数组内的页号依次往前移动一位
for (int k = 1; k <= pagek; ++k) fifoArr[k - 1] = fifoArr[k];
fifoArr[pagek] = pageArr[i]; //新页号插入最后
}
}
return hintCnt;
}
int LRU_test(int pagek){//传入页框长度,return返回命中次数
pagek--; //从0开始算,减一
memset(lruArr, -1, sizeof lruArr); //初始化lruArr页框数组,全部赋值为-1
int hintCnt = 0; //命中次数
int pageTmp = 0; //页框使用的序号
for (int i = 0; i < 400; ++i) {
bool hintFlag = false; //命中标记
for (int j = 0; j <= pagek; ++j) {
if (pageArr[i] == lruArr[j])
{
//LRU中,每次命中后将命中的页号从位置j移动到最后,即pageTmp - 1位置
for (int k = j + 1; k <= pageTmp - 1; ++k) lruArr[k - 1] = lruArr[k];
lruArr[pageTmp - 1] = pageArr[i];
hintCnt ++, hintFlag = true;
break; //如果页框数组fifoArr中有重复的页号,则命中
}
}
if(pageTmp <= pagek && !hintFlag) //页框数组未满,未命中
lruArr[pageTmp++] = pageArr[i]; //插入到页框数组中
else if (pageTmp > pagek && !hintFlag) //页框数组满,未命中
{
//页框数组内的页号依次往前移动一位,把最少最近使用的页号替换出去
for (int k = 1; k <= pagek; ++k) lruArr[k - 1] = lruArr[k];
lruArr[pagek] = pageArr[i]; //新页号插入最后
}
// for (int j = 0; j <= pagek; ++j) {
// cout << lruArr[j] << ' ' ;
// }
// cout << endl;
}
return hintCnt;
}
int OPT_test(int pagek){//传入页框长度,return返回命中次数
pagek--; //从0开始算,减一
memset(optArr, -1, sizeof optArr); //初始化optArr页框数组,全部赋值为-1
int hintCnt = 0; //命中次数
int pageTmp = 0; //页框使用的序号
for (int i = 0; i < 400; ++i) {
bool hintFlag = false; //命中标记
for (int j = 0; j <= pagek; ++j) {
if (pageArr[i] == optArr[j])
{
hintCnt ++, hintFlag = true;
break; //如果页框数组optArr中有重复的页号,则命中
}
}
if(pageTmp <= pagek && !hintFlag) //页框数组未满,未命中
optArr[pageTmp++] = pageArr[i]; //插入到页框数组中
else if (pageTmp > pagek && !hintFlag) //页框数组满,未命中
{
int cnt = 0; //记录未来出现的 不重复页号的数量,直到 pagek
bool usedoptArr[40]; //记录页框数组optArr中,true表示未来会再次使用
memset(usedoptArr, false, sizeof usedoptArr);
for (int j = i + 1; j < 400; ++j) {
for (int k = 0; k <= pagek; ++k) {
if (optArr[k] == pageArr[j] && !usedoptArr[optArr[k]]) //此页号存在于页框数组中,且未记录则cnt++
usedoptArr[optArr[k]] = true, cnt++;
if (cnt == pagek) break;
}
}
int tmp = 0; //将要被替换的页号在页框数组中的位置
//找出最远才使用的那个页号
for (; tmp <= pagek; ++tmp)
if (!usedoptArr[optArr[tmp]]) break;
optArr[tmp] = pageArr[i]; //实现替换
}
// for (int j = 0; j <= pagek; ++j) {
// cout << optArr[j] << ' ' ;
// }
// cout << endl;
}
return hintCnt;
}
int main(){
random();//调用random()函数获取页号流
// for(auto t : pageArr) cout << pageArr[t] << " ";
for(int i = 4; i <= 40; i ++ ) //页框从4到40
{
cout << "页框长度:" << i << endl;
int fifoHint = FIFO_test(i); //FIFO算法命中次数
int lruHint = LRU_test(i);//LRU算法命中次数
int optHint = OPT_test(i);//OPT算法命中次数
cout << "FIFO算法 命中次数:"<< fifoHint << " 命中率:" << ( float )fifoHint / 400 * 100<< "%";
cout << "\tLRU算法 命中次数:"<< lruHint << " 命中率:" << ( float )lruHint / 400 * 100<< "%";
// puts("");
cout << "\tOPT算法 命中次数:"<< optHint << " 命中率:" << ( float )optHint / 400 * 100<< "%" << endl<
测试结果
测试Belady的异常
将pageArr[]数组改成课本中的1,2,3,4,1,2,5,1,2,3,4,5
int pageArr[400] = {1,2,3,4,1,2,5,1,2,3,4,5};
再单独对FIFO和LRU测试页框长度3到5的结果,如下
对于Belady的异常,通过测试可知,FIFO的页框从3变成4后命中率反而下降,而LRU则不会出现这种情况。