操作系统页面置换算法(FIFO、LRU、OPT)

        应付学校实验报告的,通过简单的数组进行实现,当然这样时间效率太低,特别是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<

测试结果

操作系统页面置换算法(FIFO、LRU、OPT)_第1张图片

 操作系统页面置换算法(FIFO、LRU、OPT)_第2张图片

 操作系统页面置换算法(FIFO、LRU、OPT)_第3张图片

测试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的结果,如下

操作系统页面置换算法(FIFO、LRU、OPT)_第4张图片

对于Belady的异常,通过测试可知,FIFO的页框从3变成4后命中率反而下降,而LRU则不会出现这种情况。

你可能感兴趣的:(操作系统,c++)