操作系统实验五

页面置换算法

题目
设进程的逻辑地址空间共分为8个页面,进程运行时需引用的页面号引用串为7、0、1、2、0、3、0、4、2、3、0、3、2、1、2、0、1、7、0、1,现系统为该进程在内存中分配了三个物理存储块。请根据理论教材所授内容,采用C语言(也可采用自己熟悉的语言)分别模拟实现OPT、FIFO、LRU、NRU和LFU页面置换算法,对上述页面号引用串进行调度,并计算出各算法下的缺页率。

代码如下:

OPT页面置换算法
#include <iostream>  
#include<map>
#include<set>
#include <algorithm>
#include<cstdio>
#include<cstring> 
#include<cmath>
#define N 200
using namespace std;  
 
int page[N];//页面引用号 
int block[N];//物理块,内存 
int dist[N][N];//表示第i次访问内存的时候,内存中的页面j 在以后被访问的最小时间 

int n;//页面引用号个数 
int m;//物理块数目 
int page_max;//最大页面号 

int pre[N];//page[i]在page中的索引
int opt(){//最佳页面置换算法 
    int page_lack = 0;
    memset(pre, 0, sizeof(pre));
    memset(dist, 0x3f, sizeof(dist));
    memset(block, -1, sizeof(block));
    for(int i=n; i>=1; --i){
         for(int j=0; j<=page_max; ++j) 
             if(pre[j])
                dist[i][j] = pre[j] - i;
         pre[page[i]] = i; 
    }
    
    for(int i=1; i<=n; ++i){//开始访问页面 
        int j;
        int max_dist = 0, p; 
        for(j=1; j<=m; ++j){
            if(block[j] == -1){//该物理块中没有被放入页面,则直接放入, 产生缺页 
                block[j] = page[i]; 
                cout<<"页面"<<page[i]<<"不在内存,直接放入物理块"<<j<<"中!"<<endl;
                page_lack++;
                break;
            } else if(block[j] == page[i])//页面存在内存中 
                break;
            
            if(max_dist < dist[i][block[j]]){
                max_dist = dist[i][block[j]];//说明block[j] 对应的页面以后会长时间不会用到 
                p = j;//block[] 第j个页面会被替换掉 
            }
        }
        if(j > m){//此时物理块中被装满,且没有找到page[i]对应的分页,接下来进行页面替换 
             cout<<"页面"<<page[i]<<"不在内存,将物理块"<<p<<"中的页面" <<block[p]<<"替换掉!"<<endl;
             block[p] = page[i];
             page_lack++; 
        }
        cout<<endl<<"当前内存中页面的情况:"<<endl; 
        for(int k=1; k<=m; ++k)//内存中页面加载情况 
            cout<<block[k]<<" ";
        cout<<endl<<endl;
    }
    return page_lack;//返回缺页次数 
} 
int main(){
	int page_lack;
	float w;//w为缺页中断率 
	cout<<"请输入页面引用号个数" ;
    cin>>n;
	cout<<"请输入物理块个数";
	cin>>m;
	cout<<"输入页面引用序列"; 
    for(int i=1; i<=n; ++i){ 
        cin>>page[i];
        page_max = max(page_max, page[i]) ;
    } 
    page_lack=opt(); 
    w=(float)page_lack/n; 
     cout<<"OPT缺页中断次数:"<<page_lack<<endl;
     cout<<"缺页中断率:"<<w<<endl;
     return 0;
} 

运行截图:

FIFO页面置换算法

#include <iostream>  
#include<map>
#include<set>
#include <algorithm>
#include<cstdio>
#include<cstring> 
#include<cmath>
#define N 200
using namespace std;  
 
int page[N];//页面引用号 
int block[N];//物理块,内存 
int dist[N][N];//表示第i次访问内存的时候,内存中的页面j 在以后被访问的最小时间 

int n;//页面引用号个数 
int m;//物理块数目 
int page_max;//最大页面号 
set<int>page_set;
int fifo(){//先进先出页面置换算法
    int page_lack = 0; 
    memset(block, -1, sizeof(block));
    int index = 1;
    for(int i=1; i<=n; ++i){
        if(index > m) index = 1;
        set<int>::iterator it;
        it = page_set.find(page[i]);  
        if(it == page_set.end()){
            if(block[index] != -1)
                page_set.erase(block[index]);
            page_set.insert(page[i]);
            block[index++] = page[i];
            ++page_lack;
        } 
        for(int k=1; k<=m; ++k)
            cout<<block[k]<<" ";
        cout<<endl;
    } 
    return page_lack;
}

int main(){
	int v;//w为缺页率 ,v为缺页中断次数 
	float w;
	cout<<"请输入页面引用号个数" ;
    cin>>n;
	cout<<"请输入物理块个数";
	cin>>m;
	cout<<"请输入页面号引用次序"; 
    for(int i=1; i<=n; ++i){ 
        cin>>page[i];
        page_max = max(page_max, page[i]) ;
    } 
    v=fifo();
	w=(float)v/n; 
     cout<<"FIFO缺页中断次数:"<<v<<endl;
     cout<<"FIFO缺页中断率:"<<w<<endl;
     
     return 0;
} 

运行截图:

LRU算法

#include <iostream>  
#include<map>
#include<set>
#include <algorithm>
#include<cstdio>
#include<cstring> 
#include<cmath>
#define N 200
using namespace std;  
 
int page[N];//页面引用号 
int block[N];//物理块,内存 
int dist[N][N];//表示第i次访问内存的时候,内存中的页面j 在以后被访问的最小时间 

int n;//页面引用号个数 
int m;//物理块数目 
int page_max;//最大页面号 
int pre[N];//page[i]在page中的索引
int LRU(){
    int page_lack = 0;//page_back为缺页次数 
    memset(pre, 0, sizeof(pre));
    memset(dist, 0x3f, sizeof(dist));
    memset(block, -1, sizeof(block));
    for(int i=1; i<=n; ++i){
         for(int j=0; j<=page_max; ++j) 
             if(pre[j])
                dist[i][j] = i - pre[j];
         pre[page[i]] = i; 
    }
    
    for(int i=1; i<=n; ++i){//开始访问页面
        int j;
        int max_dist = 0, p; 
        for(j=1; j<=m; ++j){
            if(block[j] == -1){//该块没有放入页面,则直接放入, 产生缺页 
                block[j] = page[i]; 
                cout<<"页面"<<page[i]<<"不在内存,直接放入物理块"<<j<<"中!"<<endl;
                page_lack++;
                break;
            } else if(block[j] == page[i])//页面存在内存中 
                break;
            
            if(max_dist < dist[i][block[j]]){
                max_dist = dist[i][block[j]];
                p = j;//block[] 第j个页面会被替换掉 
            }
        }
        if(j > m){
             cout<<"页面"<<page[i]<<"不在内存,将物理块"<<p<<"中的页面" <<block[p]<<"替换!"<<endl;
             block[p] = page[i];
             page_lack++; 
        }
        cout<<endl<<"当前内存中页面的情况:"<<endl; 
        for(int k=1; k<=m; ++k)//内存中页面加载情况 
            cout<<block[k]<<" ";
        cout<<endl<<endl;
    }
    return page_lack;
} 


int main(){

	cout<<"请输入页面引用号个数" ;
    cin>>n;
	cout<<"请输入物理块个数";
	cin>>m;
	cout<<"请输入页面引用次序";
    for(int i=1; i<=n; ++i){ 
        cin>>page[i];
        page_max = max(page_max, page[i]) ;
    } 
   	int lack=LRU(); 
    float w;
	w=(float)lack/n; 	
     cout<<"LRU缺页中断次数:"<<lack<<endl;
      cout<<"缺页中断率"<<w<<endl;
     return 0;
} 

运行结果截图:

后续两个算法实验并未完成,因此给出老师所给的代码作为参考

NRU算法
void NRU (int ref_len, int vsize){
    int i, find, miss, rep, least;
    int flag[MEM_FRAME_SIZE];                   //访问位
    float rate = 0;

    printf("-------(4) NRU页面缺页算法-------\n");

    miss = 0;
    ini_mem ();                   //初始化内存循环页框
    for (i = 0; i < MEM_FRAME_SIZE; i ++)         //初始化内存循环页框的访问位
       flag[i] = 0;
    rep = 0;
    for (i = 0; i < ref_len; i ++) {
       find = search (MEM_FRAME_SIZE, reference[i]);
       if (find != FALSE && mem_frame[find] == -1) {    //内存循环页框未满
          miss ++;
          mem_frame[find] = reference[i];//页面缺页
          printf("页框未满,置入页面%d\n",reference[i]);
          flag[rep] = 1; // 置访问为1
          rep = (rep+1) % MEM_FRAME_SIZE;  //页面不在内存中,扫描指针下移
       }
       else if (find == FALSE) {          //内存循环页框已满且拟置入页面不在页框中
          miss ++;
          while (flag[rep] != 0) {       //最近被使用过,给第二次机会
             flag[rep] = 0;
             rep = (rep+1) % MEM_FRAME_SIZE;
          }
          printf("换出页面%d,换入页面%d\n",mem_frame[rep],reference[i]);
          mem_frame[rep] = reference[i];//页面缺页
          flag[rep] = 1; // 置访问为1
          rep = (rep+1) % MEM_FRAME_SIZE;  //页面不在内存中,扫描指针下移
       }
       else{//在内存循环页框中找到拟置入页面
          printf("内存页框中存在页面%d,无需置入\n",reference[i]);
          flag[find] = 1; //页面的内存中,扫描指针不动
       }
    }
    rate = (float)miss/(float)ref_len;          //计算页面缺页率
    printf("-----NRU页面缺页率为:%d/%d=%.2f-----\n\n",miss,ref_len,rate);
}

LFU算法
void LFU (int ref_len, int vsize){
    int i, j, find, miss, rep, least;
    int count[MEM_FRAME_SIZE];            //计数器:记录内存页框中页面的使用频率
    float rate = 0;

    printf("-------(5) LFU页面缺页算法-------\n");

    miss = 0;
    ini_mem ();                          //初始化内存页框
    for (i = 0; i < MEM_FRAME_SIZE; i ++)         //初始化内存页框中页面的使用频率
        count[i] = 0;
    for (i = 0; i < ref_len; i ++) {
        find = search (MEM_FRAME_SIZE, reference[i]);
        if (find != FALSE && mem_frame[find] == -1) {     //内存页框未满
           miss ++;
           mem_frame[find] = reference[i];//页面缺页
           printf("页框未满,置入页面%d\n",reference[i]);
        }
        else if (find == FALSE) {       //内存页框已满且拟置入页面不在页框中
           miss ++;
           least = count[0];
           rep = 0;
           for (j = 1; j < MEM_FRAME_SIZE; j ++) {//选择内存页框中使用频率最小的页面
              if (count[j] < least) {
                 least = count[j];
                 rep = j;
              }
           }
           printf("换出页面%d,换入页面%d\n",mem_frame[rep],reference[i]);
           mem_frame[rep] = reference[i];//页面缺页
           count[rep] = 0;
        }
        else{//在内存页框中找到拟置入页面
           printf("内存页框中存在页面%d,无需置入\n",reference[i]);
           count[find] ++;
        }
        if ((i+1) % 4== 0) {    //没有移位寄存器,用计数器定期衰减模拟移位,如果把4改成10,缺页率结果又如何?
           for (j = 0; j < MEM_FRAME_SIZE; j ++)
              count[j] /= 2; //移位
        }
    }
    rate = (float)miss/(float)ref_len;          //计算页面缺页率
    printf("-----LFU页面缺页率为:%d/%d=%.2f-----\n\n",miss,ref_len,rate);
}

OPT、FIFO、LRU、NRU和LFU页面置换算法优缺点分析

本次实验有一定的难度,尤其是后面两个算法的思想和如何实现,后续有时间还要再研究

posted @   星星盛开的地方  阅读(499)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示