浅谈分页置换算法

本文探讨了操作系统中的分页置换算法,它允许运行超出物理内存大小的程序。通过虚拟内存和demand paging,只有实际需要的页面才会被加载到内存,有效地解决了内存限制问题。当发生页错误时,系统会进行检查、调入所需页面、分配空闲帧、从磁盘加载页面等操作。这种方法依赖于有效位和无效位来区分内存和磁盘上的页面。
摘要由CSDN通过智能技术生成

这是最近做完上学期的操作系统的课程设计,想起可以上BLOG写点什么,以防自己学无所获,弄完就忘记。

首先回忆一下,为什么会有分页置换算法?



分页置换算法是基于虚拟内存而言,由于在一般的内存管理算法中,执行指令必须是在物理内存中,满足这一条件就必须将整个进程放入内存中,这就会对进程的大小进行限制,跑不了超出物理内存的程序,当然动态载入能够减轻这一限制,但这是远远不够的,于是引出了新的方案:虚拟内存






所以我们就不用担心进程或者程序的大小,只需要关心要解决的问题。


于是就引出了demand paging,它是虚拟内存系统采用的方法之一,即只有程序执行需要时才载入页,那些没有用到的页不会调入到物理内存。
对于这种方案,需要一定形式的硬件来支持区分哪些页在内存哪些在disk上。
所以有有效位与无效(valid-invalid bit)位来区分。
而当进程试图访问那些未调入到内存的页(invalid bit),会产生页错误陷阱(page-fault trap)
处理这种错误一般会进行如下操作:
1检查进程的内存页表,以确定该引用是合法还是非法的地址访问。
2如果是引用非法,则终止进程,若是合法的引用于是现在应调入。
3找一个空闲的帧(free frame)
4从磁盘中将所需要的页调入到刚刚分配的free frame 中
5修改进程内部表和页表,说明所需要的页已经在内存中
6重新启动刚刚因陷阱而中断的指令
 










#include<iostream>
#include<fstream>
 
using namespace std;
 
//定义页面和页框的总容量
const int PAGESIZE = 20;
const int FRAMESIZE = 10;
 
int page[PAGESIZE];                                   //定义 page数组 存放页面
int frame[FRAMESIZE];                                 //定义 frame数组
int result[PAGESIZE][FRAMESIZE];                      //用来存放页框和页面二维数组 保存页面置换结果用来输出
int pageLength = 0;                                   //用户实际使用的页面数目
int frameLength = 0;                                  //用户实际使用的页框数目
int frameFlag[FRAMESIZE];                             //用于LRU与OPT算法中,辅助、判断换出的页面
 
int noPageCount = 0;
int pageReplaceCount = 0;
 
//****************************************************************************************************
 
void inputData()
{
    cout<<"请输入页框(物理块)数(1<=F<="<<FRAMESIZE<<')'<<endl;
     cin>>frameLength;
     cout<<"请输入页面数(1<=p<="<<PAGESIZE<<')'<<endl;
     cin>>pageLength;
     while(frameLength<=0||frameLength>FRAMESIZE||pageLength<=0||pageLength>PAGESIZE){//判断用户输入是否在范围内
         cout<<"输入范围错误,请从新输入:"<<endl;
         cout<<"请输入页框(物理块)数(1<=F<="<<FRAMESIZE<<')'<<endl;
         cin>>frameLength;
         cout<<endl<<"请输入页面数(1<=p<="<<PAGESIZE<<')'<<endl;
         cin>>pageLength;
     }
     cout<<"请依次输入要引用的页面"<<endl;
     for(int i = 0;i<pageLength;i++){
         cin>>page[i];
     }
}
//****************************************************************************************************
//初始化page数组
void initPage()
{
    for(int i = 0;i<PAGESIZE;i++){
       page[i] = -1;                     
     }
}
//****************************************************************************************************
//初始化frame与result数组
void initFrameResult()
{
     int i = 0;
     for(i = 0;i<FRAMESIZE;i++)
         frame[i] = -1;
    
     for(i = 0;i < PAGESIZE;i++){
          for(int j = 0; j <FRAMESIZE;j++){
              result[i][j] = -1;
          }
     }
}
//****************************************************************************************************
//判断页框中是否已存在 要调用的页面
bool isexist(int i)
{
     for(int j = 0;j < frameLength;j++)
         if(frame[j] == i)returntrue;
     return false;
}
//****************************************************************************************************
//用于返回页框中存在的 要引用的页面的下标
//输入参数i为要引用的页面
int existFlag(int i)
{
    for(int j = 0;j < frameLength;j++)
         if(frame[j] == i)
             return j;
}
//****************************************************************************************************
//LRU算法中,用于返回最近最久未使用的页面对应的页框的下标
int lastestUnused()
{
    int min = frameFlag[0];
    int j = 0;
    for(int i = 0;i <frameLength;i++){
        if(min < frameFlag[i]){
            min = frameFlag[i];
            j = i;
        }
    }
    return j;
}
//****************************************************************************************************
//在最佳置换算法中,用于判断将来最长时间未使用的页面对应的页框的下标
int optimalPosition()
{
    int j = 0;
    int max = frameFlag[0];
    for(int i = 0;i <frameLength;i++)
        if(max < frameFlag[i]){
            max = frameFlag[i];
            j = i;
        }
    return j;
}
//****************************************************************************************************
//用于显示  保存在result数组中的结果
void showResult()
{
//  char ch = '0';
     for(int i =0 ;i <pageLength;i++){
         cout<<"  "<<page[i]<<"    ";
         for(int j = 0;j <frameLength;j++){
                 if(-1 ==result[i][j])
                     break;
                 elsecout<<'['<<result[i][j]<<']'<<' ';
         }
    system("pause");
         cout<<endl;
     }
}
//****************************************************************************************************
//FIFO
void FIFO()
{
     int frameFlag = 0;                          //页框的标记,用于确定该换出的页框的下标
     int pageFlag = 0;                           //页面标记(下标),指向下一个页面
     int resultFlag = 0;                         //结果标记,表示结果的行,即result数组的行标
    
     noPageCount = 0;                        //缺页次数
     pageReplaceCount = 0;                   //置换页面次数
     int i = 0;                                  //i,j为for循环中的 循环变量
     int j = 0;
     int position = 0;                           //指示页框,通过与页框实际总大小来判断有无空白的页框
   
     while (pageFlag < pageLength){              
         if(isexist(page[pageFlag]))             //判断页面是否已经存在
             resultFlag++;
         else{
             if(position < frameLength){                    //判断可用的frame
                 frame[position] = page[pageFlag];        
                 position++;
                 noPageCount++;
                 for(i = 0;i <= position;i++)              //每置换一次页面后,将页框情况存入result二维数组中
                     result[resultFlag][i] = frame[i];     
                 resultFlag++;
             }
             else{
                 frame[frameFlag] = page[pageFlag];        //frameFlag指示的就是要换出的页面
                 noPageCount++;
                 pageReplaceCount++;
                 for(i = 0;i <frameLength;i++)            //每置换一次页面后,将页框情况存入result数组中
                     result[resultFlag][i] = frame[i];
                 resultFlag++;
                 frameFlag++;
                 frameFlag = frameFlag % frameLength;
             }
         }
         pageFlag++;
     }
     
     showResult();
     cout<<"*********************************************************"<<endl;
     cout<<"缺页次数为:"<<noPageCount<<endl;                 //计算缺页次数、置换次数、缺页率
     cout<<"置换页面次数为:"<<pageReplaceCount<<endl;
     cout<<"缺页率为:"<<((double)pageReplaceCount/pageLength)*100<<'%'<<endl;
     cout<<"*******************************************************"<<endl;
     return;
}
//****************************************************************************************************
//Least-Recently-Used
void LRU()
{
    int i = 0;
    noPageCount = 0;
    pageReplaceCount = 0;
    int pageFlag = 0;
    int resultFlag = 0;
    int position = 0;                                    //用于判断是否有空页框
    for(i = 0;i <FRAMESIZE;i++)                         //初始化 时间记录数组 用来判断最久未用的页面
        frameFlag[i] = 0;
    while(pageFlag < pageLength){
        if(isexist(page[pageFlag])){                     //判断页面 是否 已经在页框中
        resultFlag++;
            frameFlag[existFlag(page[pageFlag])]= 0;    //如果在,则将时间记录数组对应位置为0
        }
        else{
            if(position <frameLength){                  //如果有空白页框,则将页面放入空白页框中
                frame[position] = page[pageFlag];
                frameFlag[position] =0;
                position++;
                noPageCount++;
           
            for(i= 0;i <= position;i++)
                     result[resultFlag][i]= frame[i];
             resultFlag++;
            }
            else{
                frame[lastestUnused()]= page[pageFlag];       //置换出最久未使用的页面
                frameFlag[lastestUnused()]= 0;
                noPageCount++;
                pageReplaceCount++;
                for(i = 0;i <frameLength;i++)
                    result[resultFlag][i]= frame[i];
                resultFlag++;
            }
        }
        for(i = 0;i <frameLength;i++)
            frameFlag[i]++;
        pageFlag++;
    }
    showResult();
    cout<<"**********************************************************"<<endl;
    cout<<"缺页次数为:"<<noPageCount<<endl;
    cout<<"置换页面次数为:"<<pageReplaceCount<<endl;
    cout<<"缺页率为:"<<((double)pageReplaceCount/pageLength)*100<<'%'<<endl;
    cout<<"***********************************************************"<<endl;
    return;
}
//****************************************************************************************************
//Optimal page-replacement algorithm
 
void OPT()
{
    int i = 0;
    int j = 0;
    int position = 0;
    noPageCount = 0;
    pageReplaceCount = 0;
    int pageFlag = 0;
    int resultFlag = 0;
 
    for(i = 0;i < FRAMESIZE;i++)
        frameFlag[i] = 0;
    while(pageFlag < pageLength){
        if(isexist(page[pageFlag]))
            resultFlag++;
        else{
            if(position <frameLength){
                frame[position] =page[pageFlag];
                position++;
                noPageCount++;
                for(i = 0;i <position;i++)
                    result[resultFlag][i]= frame[i];
                resultFlag++;
            }
            else{
                for(i = 0;i <frameLength;i++){
                    for(j =pageFlag+1;j < pageLength;j++){
                        if(frame[i]== page[j]){
                            frameFlag[i]= j;
                            break;
                        }
                    }
                    if(j ==pageLength)frameFlag[i] = 99999;
                }
                frame[optimalPosition()]= page[pageFlag];
                noPageCount++;
                pageReplaceCount++;
                for(i = 0;i <frameLength;i++)
                    result[resultFlag][i]= frame[i];
                resultFlag++;
            }
        }
        pageFlag++;
    }
    showResult();
    cout<<"******************************************************"<<endl;
    cout<<"缺页次数为:"<<noPageCount<<endl;             计算缺页次数、置换次数、缺页率
    cout<<"置换页面次数为:"<<pageReplaceCount<<endl;
    cout<<"缺页率为:"<<((double)pageReplaceCount/pageLength)*100<<'%'<<endl;
    cout<<"*****************************************************"<<endl;
    return;
 
}
 
//****************************************************************************************************
 
//保存result数组中的数据
void saveResult()
{
    ofstream outfile;       //申请变量名为outfile的文件输出流
    outfile.open("result.txt",ios::out);   //输出文件,写
    if(!outfile){
        cout<<"没有保存成功 !"<<endl;
    }
    for(int i = 0;i <pageLength;i++){
        outfile<<"  "<<page[i]<<"  ";
        for(int j = 0;j <frameLength;j++){
            if(-1 == result[i][j])
               break;
            elseoutfile<<'['<<result[i][j]<<']'<<' ';
        }
        outfile<<endl;
    }
    outfile<<"**********************************************************"<<endl;
    outfile<<"缺页次数为:"<<noPageCount<<endl;             计算缺页次数、置换次数、缺页率
    outfile<<"置换页面次数为:"<<pageReplaceCount<<endl;
    outfile<<"缺页率为:"<<((double)pageReplaceCount/pageLength)*100<<'%'<<endl;
    outfile<<"**********************************************************"<<endl;
    outfile.close();
    //cout<<"保存成功!";
}
//****************************************************************************************************
//保存页面
void savePage()
{
    ofstream outfile;
    outfile.open("page.txt",ios::out);
    if(!outfile){
        cout<<"没有保存成功 !"<<endl;
    }
    outfile<<frameLength<<''<<pageLength<<' ';
    for(int i =0;i<pageLength;i++)
        outfile<<page[i]<<'';
    outfile.close();
    cout<<"***********************(:**保存成功!**:)**********************************"<<endl;
}
//****************************************************************************************************
//打开文件page.txt
void openPage()
{
    ifstreaminfile("page.txt",ios::in);  //输入文件读
    if(!infile){
        cout<<"没有打开成功!";
    }
    infile>>frameLength;
    infile>>pageLength;
    for(int i = 0;i <pageLength;i++)
        infile>>page[i];
    infile.close();
    cout<<"************打开成功!请继续选择用哪种置换算法来显示:*************"<<endl;
}
 
//****************************************************************************************************
//主函数main()
int main()
{
    initPage();
    initFrameResult();
    int choice = 'a';
   
   
    while(choice !=7){
    cout<<"页面置换"<<endl
               <<"     *******************************************************"<<endl
              <<"      **        请选择所需要的功能:                     **"<<endl
               <<"      **        1.输入数据                               **"<<endl
               <<"      **        2.先进先出(FIFO)置换算法                **"<<endl
               <<"      **        3.最近最久未使用(LRU)置换算法           **"<<endl
               <<"      **        4.最佳(optimal)置换算法                 **"<<endl
               <<"      **        5.保存这次的数据                         **"<<endl
               <<"      **        6.打开保存的数据                         **"<<endl
               <<"      **        7.退出:                                 **"<<endl
               <<"     *******************************************************"<<endl;
        switch(choice)
        {
        case 1:
            inputData();
            break;
        case 2:
            initFrameResult();
            FIFO();
            break;
        case 3:
            initFrameResult();
            LRU();
            break;
        case 4:
            initFrameResult();
            OPT();
            break;
        case 5:
            saveResult();
            savePage();
            break;
        case 6:
            openPage();
            break;
        case 7:break;
        }
        cout<<"请选择功能:";
        cin>>choice;
        system("cls");
    }
    return 0;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值