页面置换算法之FIFO、LRU、OPT和Clock算法及其实现

页面置换算法之FIFO、LRU、OPT和Clock算法及其实现

页面置换

页面置换:页面置换是请求调页的基础,它完成了逻辑内存和物理内存之间的分离,采用这种机制,较小的物理内存能为程序员提供巨大的虚拟内存。

在页码被调入的时候,会有三种情况发生:
a. 类似初始化状态,内存未满,但是没有该页码,需要从磁盘中直接引入。
b. 内存已满,产生缺页错误,需要请求调页。
c. 内存已满,但是存在改页码,可以直接使用,不需要调页,也不会产生缺页错误。

所以针对这三种情况,设计如下四种页面置换算法:

FIFO页面置换

FIFO 是最简单的页面置换算法,它为每一个页面记录了调到内存的时间,当必须置换页面时,将选择最旧的页面。具体实现的话,我们并不需要记录调入页面的具体时间,只需要创建一个FIFO队列,来管理所有的内存页面,置换的是队列的首个页面,当需要调入页面到内存时,就将它加入到队列的尾部。

OPT页面置换

这个算法具有所有算法的最低的缺页错误率。并且不会遭受Belady异常,被称为OPT或者MIN。
OPT为置换最长时间不使用的页面,他与LRU算法不同的是需要向后看,寻找最不经常使用的页码,所以我们只需要向后看,有两种情况则可以结束前进:

  1. 找到了(最大帧数-1)个页码号,则剩下的那一个页码即为我们要替换的页码
  2. 找到了最后,都没有找到(最大帧数-1)个页码,这就按FIFO算法将没有找到的页码踢掉。

LRU页面置换

同为采用队列实现,LRU与FIFO不同的地方,需要更新不断出现的元素,将它重新插入一遍,所以对应于上面的三种情况中的c,这时所需要的页码在内存中已经存在,不能只是简单的直接调用进程,还需要将该页码更新一下,以证明最近使用过(找到页码所对应的位置,将它在队列中删掉,重新插入一遍)。

Clock算法

Clock又叫第二次机会算法,通过一个visit数组来实现第二次访问,利用循环队列相应的知识,在FIFO的基础上,在开辟一个与之对应的数组,其索引必须相呼应,两者具体关系如下:
a. 页码刚被调入,设置其页码对应的visit为1;
b. 访问过一次,则将其visit设置为0;
c. 页码被替换,对应的visit也要更新为1。
总之,将visit与队列实现同步操作即可。

具体代码如下:

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<stack>
#include<queue>
#include<vector>
#include<cmath>
#include<time.h>

using namespace std;

#define N 20    //Page_Name
#define M 3     //Frame_Max_name

int in(vector<int> map,int num){             //判断新进来的元素是否已经存在与内存里面
    int flag = 0; 
    vector<int>::iterator v = map.begin();
    while( v != map.end()) {
        if(num == *v){
            flag = 1;
            break;
        }
        v++;
    }
    return flag;
}

int return_index(vector<int> map,int num){     //因为栈、队列等数据结构没有遍历的功能,所以写这个函数来直接定位某个元素的索引
    int index = 0;
    vector<int>::iterator v = map.begin();
    while( v != map.end()) {
        if(num == *v){
            break;
        }
        v++;
        index++;
    }
    return index;
}
int main(){
    int arr[N];//= {7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1};
    vector<int> map;   //判断是否在stack or queue中
    int num = 0;       //缺页数
    int num1,num2,num3,num4,num5;
    srand((unsigned int)(time(NULL)));
    for(int i=0;i<N;i++){ //随机生成arr数组 表示接下来要应用的页码
        
        arr[i] = rand()%10;
        //cout << arr[i] << " ";
    }
    cout << endl;
    queue<int> FIFO;
    stack<int> LRU;

    //FIFO alforithm :
    cout << "FIFO序列如下: " << endl;
    map.clear();
    for(int i=0;i<N;i++){
        if(in(map,arr[i])){          //如果页码在内存中已经存在,输出true
            cout << "true" << endl;
            continue;
        }
            
        else{
            if(map.size()>=M){       //如果页码在内存中不存在,并且不是刚开始帧什么都没有的情况
                //int index = return_index(map,arr[i]);
                //cout << "index : " << index << endl;
                //FIFO.pop();
                //FIFO.push(arr[i]);
                map.erase(map.begin());   //头部出队列
                map.push_back(arr[i]);    //尾插
            }
            else{                    //初始状态,帧里面什么都没有,直接入队即可
                //FIFO.push(arr[i]);
                map.push_back(arr[i]);
            }
            num++;
            vector<int>::iterator v = map.begin();
            while( v != map.end()) {
                cout << *v << " ";
                v++;
            }
            cout << endl;
        }
    }
    num1 = num;
    cout << "总页数为: " << N << endl << "FIFO算法缺页数: " << num << endl;


    //LRU alaorithm :
    cout << endl << "LRU序列如下: " << endl;
    map.clear();
    num = 0;
    for(int i=0;i<N;i++){
        if(in(map,arr[i])){
            int index = return_index(map,arr[i]);   //与FIFO不同的地方,需要更新不断出现的元素,将它重新插入一遍
            map.erase(map.begin()+index);
            map.push_back(arr[i]);
            cout << "true" << endl;
            continue;
        }
        else{
            if(map.size()>=M){
                map.erase(map.begin());
                map.push_back(arr[i]);
            }
            else{
                map.push_back(arr[i]);
            }
            num++;
            vector<int>::iterator v = map.begin();
            while( v != map.end()) {
                cout << *v << " ";
                v++;
            }
            cout << endl;
        }
    }
    num2 = num;
    cout << "总页数为: " << N << endl << "LRU算法缺页数: "  << num << endl;



    //OPT alaorithm :
    cout << endl << "OPT序列如下: " << endl;
    map.clear();
    num = 0;
    
    for(int i=0;i<N;i++){
        if(in(map,arr[i])){
            // int index = return_index(map,arr[i]);
            // map.erase(map.begin()+index);
            // map.push_back(arr[i]);
            cout << "true" << endl;
            continue;
        }
        else{
            if(map.size()>=M){
                int pass = 0;
                int vis[M];
                for(int x=0;x<M;x++){
                    vis[x] = 0;
                }
                for(int j=i+1;j<N;j++){
                    for(int k=0;k<M;k++){
                        if(arr[j] == map[k]){
                            //cout << "i am " << arr[j] << endl;
                            int ind = return_index(map,arr[j]);
                            //cout << "index : " << ind << endl;
                            //cout << "arr : " << arr[j]  << endl;
                            if(vis[ind] == 1){
                                break;
                            }
                            else{
                                vis[ind] = 1;
                            }
                            pass++;
                            if(pass==M-1){
                                //cout << "pass = " << pass << "  goto !" << endl; 
                                goto This;
                            }
                            continue;
                        }
                    }
                }
This:           for(int j=0;j<M;j++){
                    if(vis[j] == 0){
                        //cout << "j == : " << j << endl;
                        map.erase(map.begin()+j);
                        map.push_back(arr[i]);
                        break;
                    }
                }
                
            }
            else{
                map.push_back(arr[i]);
            }
            num++;
            vector<int>::iterator v = map.begin();
            while( v != map.end()) {
                cout << *v << " ";
                v++;
            }
            cout << endl;
        }
    }
    num3 = num;
    cout << "总页数为: " << N << endl << "OPT算法缺页数: "  << num << endl;



    

    //Clock alaorithm 2.0 版本(循环队列) :
    cout << endl << "Clock序列如下: " << endl;
    map.clear();
    num = 0;
    vector<int> visit;
    
    int index = 0;
    for(int i=0;i<N;i++){
        if(in(map,arr[i])){
            int ind = return_index(map,arr[i]);
            //map.erase(map.begin()+index);
            visit[ind] = 1;
            //map.push_back(arr[i]);
            cout << "true" << endl;
            continue;
        }
        else{
            if(map.size()>=M){
                //int x = 0;
                while(1){
                    if(visit[index] == 0){
                        map[index] = arr[i];
                        visit[index] = 1;
                        index = (index+1) % M;
                        // map.erase(map.begin()+x);
                        // map.push_back(arr[i]);
                        // visit.erase(visit.begin()+x);
                        // visit.push_back(1);
                        break;
                    }
                    else{
                        visit[index] = 0;
                        index = (index+1) % M;
                    }
                }
            }
            else{
                map.push_back(arr[i]);
                visit.push_back(1);
            }
            num++;
            //cout << "元素 : ";
            vector<int>::iterator v = map.begin();
            while( v != map.end()) {
                cout << *v << " ";
                v++;
            }
            //cout << endl;
            //cout << "visit : "; 
            // vector<int>::iterator y = visit.begin();
            // while( y != visit.end()) {
            //     cout << *y << " ";
            //     y++;
            // }
            
            cout << endl;
        }
    }
    num4 = num;
    cout << "总页数为: " << N << endl << "Clock算法缺页数: "  << num << endl << endl;



    //Clock alaorithm 2.0 (FIFO为基础):
    cout << endl << "自创Clock序列如下: " << endl;
    map.clear();
    num = 0;
    visit.clear();
    for(int i=0;i<N;i++){
        if(in(map,arr[i])){
            int index = return_index(map,arr[i]);
            //map.erase(map.begin()+index);
            visit[index] = 1;
            //map.push_back(arr[i]);
            cout << "true" << endl;
            continue;
        }
        else{
            if(map.size()>=M){
                int x = 0;
                while(1){
                    if(visit[x] == 0){
                        map.erase(map.begin()+x);
                        map.push_back(arr[i]);
                        visit.erase(visit.begin()+x);
                        visit.push_back(1);
                        break;
                    }
                    else{
                        visit[x] = 0;
                        x = (x+1) % M;
                    }
                }
            }
            else{
                map.push_back(arr[i]);
                visit.push_back(1);
            }
            num++;
            //cout << "元素 : ";
            vector<int>::iterator v = map.begin();
            while( v != map.end()) {
                cout << *v << " ";
                v++;
            }
            //cout << endl;
            //cout << "visit : "; 
            // vector<int>::iterator y = visit.begin();
            // while( y != visit.end()) {
            //     cout << *y << " ";
            //     y++;
            // }
            
            cout << endl;
        }
    }
    num5 = num;
    cout << "总页数为: " << N << endl << "自创Clock算法缺页数: "  << num << endl << endl;



    cout << "综上所述 :" << endl;
    cout << "页码进入顺序为:" <<endl;
    for(int i=0;i<N;i++){ 
        cout << arr[i] << " ";
    }
    cout << endl;
    cout << "总页数为:" << N << endl;
    cout << "FIFO算法缺页数: "  << num1 << endl;
    cout << "LRU算法缺页数: "  << num2 << endl;
    cout << "OPT算法缺页数: "  << num3 << endl;
    cout << "Clock算法缺页数: "  << num4 << endl;
    cout << "自创Clock算法缺页数: "  << num5 << endl;

    return 0;
}
由于回答中无法提供完整的源代码,这里提供一个简单的C++代码示例,展示如何实现请求页式存储管理中的页面置换算法: ```c++ #include <iostream> #include <vector> #include <algorithm> // 页面结构体,包含页面号访问时间戳 struct Page { int id; int timestamp; }; // 页面访问顺序数组 std::vector<int> page_order; // 物理内存页表,每个元素表示一个物理内存块,0表示空闲,1表示占用 std::vector<int> physical_memory; // 虚拟内存页表,每个元素表示一个虚拟内存页,0表示不在内存中,1表示在内存中 std::vector<int> virtual_memory; // 页面置换算法OPT void opt_algorithm(int num_blocks) { std::vector<Page> pages(num_blocks); // 页面数组,记录每个页面的访问情况下一次访问时间 for (int i = 0; i < num_blocks; i++) { pages[i].id = page_order[i]; pages[i].timestamp = 0; } for (int i = num_blocks; i < page_order.size(); i++) { // 遍历物理内存中的页面,计算每个页面下一次访问的时间 for (auto& page : pages) { if (physical_memory[page.id] && page.timestamp == 0) { int next_index = i + 1; while (next_index < page_order.size() && page_order[next_index] != page.id) { next_index++; } page.timestamp = next_index; } } // 选择下一次访问时间最远的页面进行置换 auto page_to_replace = std::max_element(pages.begin(), pages.end(), [](const Page& a, const Page& b) { return a.timestamp < b.timestamp; }); // 将选择的页面从物理内存中换出,并将新的页面换入 physical_memory[page_to_replace->id] = 0; virtual_memory[page_to_replace->id] = 0; physical_memory[page_order[i]] = 1; virtual_memory[page_order[i]] = 1; // 更新页面数组,将新的页面加入物理内存 page_to_replace->id = page_order[i]; page_to_replace->timestamp = 0; } } // 页面置换算法FIFO void fifo_algorithm(int num_blocks) { int head = 0; // 页面队列头部指针 for (int i = 0; i < page_order.size(); i++) { if (physical_memory[page_order[i]]) { // 页面已经在物理内存中,无需进行置换 continue; } // 选择队列头部的页面进行置换 int page_to_replace = head; // 将选择的页面从物理内存中换出,并将新的页面换入 physical_memory[page_to_replace] = 0; virtual_memory[page_to_replace] = 0; physical_memory[page_order[i]] = 1; virtual_memory[page_order[i]] = 1; // 更新页面队列头部指针 head = (head + 1) % num_blocks; } } // 页面置换算法LRU void lru_algorithm(int num_blocks) { std::vector<Page> pages(num_blocks); // 页面数组,记录每个页面的访问情况时间戳 for (int i = 0; i < num_blocks; i++) { pages[i].id = i; pages[i].timestamp = 0; } for (int i = 0; i < page_order.size(); i++) { if (physical_memory[page_order[i]]) { // 页面已经在物理内存中,更新页面的访问时间戳 auto page = std::find_if(pages.begin(), pages.end(), [&](const Page& p) { return p.id == page_order[i]; }); page->timestamp = i; continue; } // 选择最久未被访问的页面进行置换 auto page_to_replace = std::min_element(pages.begin(), pages.end(), [](const Page& a, const Page& b) { return a.timestamp < b.timestamp; }); // 将选择的页面从物理内存中换出,并将新的页面换入 physical_memory[page_to_replace->id] = 0; virtual_memory[page_to_replace->id] = 0; physical_memory[page_order[i]] = 1; virtual_memory[page_order[i]] = 1; // 更新页面数组,将新的页面加入物理内存 page_to_replace->id = page_order[i]; page_to_replace->timestamp = i; } } int main() { int num_blocks; std::cout << "请输入程序需要占用的内存块数:"; std::cin >> num_blocks; std::cout << "请按顺序输入程序需要访问的页面编号,以空格分隔:"; for (int i = 0; i < num_blocks; i++) { int page_id; std::cin >> page_id; page_order.push_back(page_id); } physical_memory.resize(num_blocks); virtual_memory.resize(page_order.size()); int algorithm_choice; std::cout << "请选择页面置换算法:1.OPT 2.FIFO 3.LRU:"; std::cin >> algorithm_choice; switch (algorithm_choice) { case 1: opt_algorithm(num_blocks); break; case 2: fifo_algorithm(num_blocks); break; case 3: lru_algorithm(num_blocks); break; default: std::cout << "无效的选择,请重新运行程序!"; break; } std::cout << "物理内存状态:"; for (auto& block : physical_memory) { std::cout << block << " "; } std::cout << std::endl; std::cout << "虚拟内存状态:"; for (auto& page : virtual_memory) { std::cout << page << " "; } std::cout << std::endl; return 0; } ``` 这个代码示例实现OPTFIFOLRU三种页面置换算法,并支持用户指定程序需要占用的内存块数、自由设置程序的页面访问顺序以及选择页面置换算法。用户可以根据自己的需求进行修改扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值