当前位置: 首页 > article >正文

FIFO和LRU算法实现操作系统中主存管理

FIFO,用数组实现

1和2都是使用nextReplace实现新页面位置的更新

1、不精确时间:用ctime输出运行时间都是0.00秒

#include <iostream>
#include <iomanip>
#include<ctime>//用于计算时间
using namespace std;

// 页访问顺序
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };

// FIFO算法
void fifo(int n) {
    int memory[5] = { -1, -1, -1, -1, -1 };  // 用于存储主存块,初始化为 -1 表示空
    int table[5][20] = { -1 };               // 用于记录每次访问的内存状态,初始化为 -1 表示空
    bool status[20];                         // 记录是否缺页

    int pageFaults = 0;                      // 缺页次数
    int nextReplace = 0;                     // 记录下一个要替换的位置

    // 获取开始时间(时钟周期数)
    clock_t start = clock();

    // 遍历每个页面访问
    for (int j = 0; j < 20; j++) {
        int page = pages[j];
        bool found = false;

        // 检查页面是否已在内存中
        for (int i = 0; i < n; i++) {
            if (memory[i] == page) {
                found = true;
                break;
            }
        }

        if (!found) {  // 缺页情况
            memory[nextReplace] = page;       // 替换页面
            nextReplace = (nextReplace + 1) % n; // 更新替换位置
            status[j] = false;                // 标记缺页
            pageFaults++;
        }
        else {
            status[j] = true;                 // 标记命中
        }

        // 记录当前内存状态到表格
        for (int i = 0; i < n; i++) {
            table[i][j] = memory[i];
        }
    }

    // 获取结束时间(时钟周期数)
    clock_t end = clock();

    // 输出结果表格
    cout << "主存块号 ";
    for (int j = 0; j < 20; j++) {
        cout << pages[j] << " ";
    }
    cout << endl;

    for (int i = 0; i < n; i++) {
        cout << "   " << i << "     ";
        for (int j = 0; j < 20; j++) {
            if (table[i][j] == -1) {
                cout << "  ";  // 空块显示为空格
            }
            else {
                cout << table[i][j] << " ";
            }
        }
        cout << endl;
    }

    // 输出缺页标记
    cout << "是否缺页 ";
    for (int j = 0; j < 20; j++) {
        if (status[j]) {
            cout << "\u221A ";  // Unicode "√"
        }
        else {
            cout << "\u00D7 ";  // Unicode "×"
        }
    }
    cout << endl;

    cout << "FIFO 缺页率: " << fixed << setprecision(2) << (float)pageFaults / 20 * 100 << "%" << endl;
    cout << "运行时间: " << (double)(end - start) / CLOCKS_PER_SEC << " 秒" << endl; // 输出运行时间
}

int main() {
    cout << "内存容量为 3 块:\n";
    fifo(3);
    cout << endl;

    cout << "内存容量为 4 块:\n";
    fifo(4);

    return 0;
}

2、精确时间:用chrono输出运行时间都是xx微秒,输出时间不定

#include <iostream>
#include <iomanip>
#include <chrono> // 引入chrono库

using namespace std;
using namespace std::chrono; // 使用chrono命名空间

// 页访问顺序
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };

// FIFO算法
void fifo(int n) {
    int memory[5] = { -1, -1, -1, -1, -1 };  // 用于存储主存块,初始化为 -1 表示空
    int table[5][20] = { -1 };               // 用于记录每次访问的内存状态,初始化为 -1 表示空
    bool status[20];                         // 记录是否缺页

    int pageFaults = 0;                      // 缺页次数
    int nextReplace = 0;                     // 记录下一个要替换的位置

    // 获取开始时间
    auto start = high_resolution_clock::now();

    // 遍历每个页面访问
    for (int j = 0; j < 20; j++) {
        int page = pages[j];
        bool found = false;

        // 检查页面是否已在内存中
        for (int i = 0; i < n; i++) {
            if (memory[i] == page) {
                found = true;
                break;
            }
        }

        if (!found) {  // 缺页情况
            memory[nextReplace] = page;       // 替换页面
            nextReplace = (nextReplace + 1) % n; // 更新替换位置
            status[j] = false;                // 标记缺页
            pageFaults++;
        }
        else {
            status[j] = true;                 // 标记命中
        }

        // 记录当前内存状态到表格
        for (int i = 0; i < n; i++) {
            table[i][j] = memory[i];
        }
    }

    // 获取结束时间
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);

    // 输出结果表格
    cout << "主存块号 ";
    for (int j = 0; j < 20; j++) {
        cout << pages[j] << " ";
    }
    cout << endl;

    for (int i = 0; i < n; i++) {
        cout << "   " << i << "     ";
        for (int j = 0; j < 20; j++) {
            if (table[i][j] == -1) {
                cout << "  ";  // 空块显示为空格
            }
            else {
                cout << table[i][j] << " ";
            }
        }
        cout << endl;
    }

    // 输出缺页标记
    cout << "是否缺页 ";
    for (int j = 0; j < 20; j++) {
        if (status[j]) {
            cout << "\u221A ";  // Unicode "√"
        }
        else {
            cout << "\u00D7 ";  // Unicode "×"
        }
    }
    cout << endl;

    cout << "FIFO 缺页率: " << fixed << setprecision(2) << (float)pageFaults / 20 * 100 << "%" << endl;
    cout << "运行时间: " << duration.count() << " 微秒" << endl; // 输出运行时间
}

int main() {
    cout << "内存容量为 3 块:\n";
    fifo(3);
    cout << endl;

    cout << "内存容量为 4 块:\n";
    fifo(4);

    return 0;
}

3、数组模拟队列、类似滑动窗口

#include <iostream>
#include <iomanip>
#include <chrono>
#include <cstring>

using namespace std;
using namespace std::chrono;

const int N = 1010;
int memory[N];//每次查找页面进行记录的滑动窗口
int table[5][20]; // 最终输出的表格状态
// 页访问顺序
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };

// FIFO算法
void fifo(int n) {
    memset(memory, 0x3f, sizeof memory);
    bool status[20];  // 记录是否缺页

    int pageFaults = 0;       // 缺页次数
    int hh = 0, tt = -1;      // 队首和队尾指针
    auto start = high_resolution_clock::now(); // 获取开始时间

    for (int j = 0; j < 20; j++) {
        int page = pages[j];
        bool found = false;

        // 检查页面是否已在内存中
        for (int i = hh; i <= tt; i++) {
            if (memory[i] == page) {
                found = true;
                break;
            }
        }

        if (!found) {  // 缺页情况
            memory[++tt] = page; // 新页面加入队尾

            // 控制滑动窗口大小为 n
            if (tt - hh + 1 > n) {
                hh++; // 超过容量,队首出队
            }

            status[j] = false;  // 标记缺页
            pageFaults++;
        }
        else {
            status[j] = true;   // 标记命中
        }

        // 记录当前内存状态到表格
        for (int i = 0; i < n; i++) {
            //如果只写memory[hh]的话不就移动队首指针了吗,不可以,现在是赋值阶段,只需要控制负责赋值的滑动指针首先不能超过队尾指针,确保在滑动窗口范围内,
            //因为有可能这个滑动窗口不足n长,你就会多余赋值本来不能存在的页面号赋值成0x3f,其次需要满足当前检查是否缺页的一次记录memory,该位置是否有值
            if (i + hh <= tt && memory[i + hh] != 0x3f) {
                table[i][j] = memory[i + hh];
            }
            else {
                table[i][j] = -1; // 空位显示为 -1
            }
        }
    }

    auto stop = high_resolution_clock::now(); // 获取结束时间
    auto duration = duration_cast<microseconds>(stop - start);

    // 输出结果表格
    cout << "主存块号 ";
    for (int j = 0; j < 20; j++) {
        cout << pages[j] << " ";
    }
    cout << endl;

    for (int i = 0; i < n; i++) {
        cout << "   " << i << "     ";
        for (int j = 0; j < 20; j++) {
            if (table[i][j] == -1) {
                cout << "  ";  // 空块显示为空格
            }
            else {
                cout << table[i][j] << " ";
            }
        }
        cout << endl;
    }

    // 输出缺页标记
    cout << "是否缺页 ";
    for (int j = 0; j < 20; j++) {
        cout << (status[j] ? "\u221A " : "\u00D7 ");//unicode编码,前者代表true则不缺页是√标识,后者代表false是缺页×表示
    }
    cout << endl;

    cout << "FIFO 缺页率: " << fixed << setprecision(2) << (float)pageFaults / 20 * 100 << "%" << endl;
    cout << "运行时间: " << duration.count() << " 微秒" << endl;
}

int main() {
    cout << "内存容量为 3 块:\n";
    fifo(3);
    cout << endl;

    cout << "内存容量为 4 块:\n";
    fifo(4);

    return 0;
}

朴素版算缺页率

#include <iostream>
#include <ctime>
#include <cstring>

using namespace std;


const int N = 1010;
int memory[N];//每次查找页面进行记录的滑动窗口
int table[5][20]; // 最终输出的表格状态
// 页访问顺序
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };

// FIFO算法
void fifo(int n) {
    memset(memory, 0x3f, sizeof memory);
    bool status[20];  // 记录是否缺页

    int pageFaults = 0;       // 缺页次数
    int hh = 0, tt = -1;      // 队首和队尾指针
    clock_t start=clock(); // 获取开始时间

    for (int j = 0; j < 20; j++) {
        int page = pages[j];
        bool found = false;

        // 检查页面是否已在内存中
        for (int i = hh; i <= tt; i++) {
            if (memory[i] == page) {
                found = true;
                break;
            }
        }

        if (!found) {  // 缺页情况
            memory[++tt] = page; // 新页面加入队尾

            // 控制滑动窗口大小为 n
            if (tt - hh + 1 > n) {
                hh++; // 超过容量,队首出队
            }

            status[j] = false;  // 标记缺页
            pageFaults++;
        }
        else {
            status[j] = true;   // 标记命中
        }

        // 记录当前内存状态到表格
        for (int i = 0; i < n; i++) {
            //如果只写memory[hh]的话不就移动队首指针了吗,不可以,现在是赋值阶段,只需要控制负责赋值的滑动指针首先不能超过队尾指针,确保在滑动窗口范围内,
            //因为有可能这个滑动窗口不足n长,你就会多余赋值本来不能存在的页面号赋值成0x3f,其次需要满足当前检查是否缺页的一次记录memory,该位置是否有值
            if (i + hh <= tt && memory[i + hh] != 0x3f) {
                table[i][j] = memory[i + hh];
            }
            else {
                table[i][j] = -1; // 空位显示为 -1
            }
        }
    }

    clock_t end = clock(); // 获取结束时间

    // 输出结果表格
    cout << "主存块号 ";
    for (int j = 0; j < 20; j++) {
        cout << pages[j] << " ";
    }
    cout << endl;

    for (int i = 0; i < n; i++) {
        cout << "   " << i << "     ";
        for (int j = 0; j < 20; j++) {
            if (table[i][j] == -1) {
                cout << "  ";  // 空块显示为空格
            }
            else {
                cout << table[i][j] << " ";
            }
        }
        cout << endl;
    }

    // 输出缺页标记
    cout << "是否缺页 ";
    for (int j = 0; j < 20; j++) {
        cout << (status[j] ? "\u221A " : "\u00D7 ");//unicode编码,前者代表true则不缺页是√标识,后者代表false是缺页×表示
    }
    cout << endl;

    cout << "FIFO 缺页率: " << (float)pageFaults / 20 * 100 << "%" << endl;
    cout << "运行时间: " << (double)(end-start)/CLOCKS_PER_SEC << " 秒" << endl;

}

int main() {
    cout << "内存容量为 3 块:\n";
    fifo(3);
    cout << endl;

    cout << "内存容量为 4 块:\n";
    fifo(4);

    return 0;
}

FIFO,用链表实现

LRU,用计数器实现

#include <iostream>
#include <ctime>
#include <cstring>
#include <unordered_map>

using namespace std;

const int N = 1010;
int table[5][20]; // 最终输出的表格状态
unordered_map<int, int> m; // 键为page号,值为count值
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };

void lru(int n) {
    memset(table, -1, sizeof table);
    m.clear();
    bool status[20]; // 记录是否缺页

    int pageFaults = 0; // 缺页次数

    clock_t start = clock(); // 获取开始时间

    for (int j = 0; j < 20; j++) {
        int page = pages[j];

        if (!m.count(page)) { // 没命中就要加入或者替换页面
            if (m.size() >= n) {
                // 找到count最大的页面进行替换
                int maxpage = -1, maxcounts = -1;
                for (auto p : m) {
                    if (p.second > maxcounts) {
                        maxpage = p.first;
                        maxcounts = p.second;
                    }
                }
                m.erase(maxpage);
            }
            m[page] = 0;//没命中且主存没满则直接加入页面
            pageFaults++;
            status[j] = false; // 标记缺页
        }
        else {
            status[j] = true; // 标记命中
            m[page] = 0;
        }

        // 更新所有页面的count值:命中则置0,没命中加入新页面——满足条件则不加1即可,不管加不加入新页面,其他没中的页面都是要count+1的
        for (auto& p : m) {
            if (p.first != page) {
                p.second += 1;
            }
        }

        // 更新当前主存块内存在的页面
        int i = 0;
        for (auto p : m) {
            if (i < n) {//用一个i去便利贮存块,而不用for
                table[i][j] = p.first;
                i++;
            }
        }
        //一开始写错了:
        /*for (int i = 0; i < n; i++) {
            for (auto p : m) {
                table[i][j] = p.first;
            }
        }*/
    }

    clock_t end = clock(); // 获取结束时间

    // 输出结果表格
    cout << "主存块号 ";
    for (int j = 0; j < 20; j++) {
        cout << pages[j] << " ";
    }
    cout << endl;

    for (int i = 0; i < n; i++) {
        cout << "   " << i << "     ";
        for (int j = 0; j < 20; j++) {
            if (table[i][j] == -1) {
                cout << "  "; // 空块显示为空格
            }
            else {
                cout << table[i][j] << " ";
            }
        }
        cout << endl;
    }

    // 输出缺页标记
    cout << "是否缺页 ";
    for (int j = 0; j < 20; j++) {
        cout << (status[j] ? "\u221A " : "\u00D7 ");
    }
    cout << endl;

    cout << "LRU 缺页率: " << (float)(pageFaults) / 20 * 100 << "%" << endl;
    cout << "运行时间: " << (double)(end - start) / CLOCKS_PER_SEC << " 秒" << endl;
}

int main() {
    cout << "内存容量为 3 块:\n";
    lru(3);
    cout << endl;

    cout << "内存容量为 4 块:\n";
    lru(4);

    return 0;
}

LRU,用堆栈实现

两个算法综合在一起看运行速率

#include <iostream>
#include <ctime>
#include <cstring>
#include <unordered_map>
#include <chrono> // 引入chrono库

using namespace std;
using namespace std::chrono; // 使用chrono命名空间

const int N = 1010;
int table[5][20]; // 最终输出的表格状态
unordered_map<int, int> m; // 键为page号,值为count值
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };
int memory[N];//每次查找页面进行记录的滑动窗口

// FIFO算法
void fifo(int n) {
    memset(memory, 0x3f, sizeof memory);
    memset(table, -1, sizeof table);
    bool status[20];  // 记录是否缺页

    int pageFaults = 0;       // 缺页次数
    int hh = 0, tt = -1;      // 队首和队尾指针
    //clock_t start = clock(); // 获取开始时间
     // 获取开始时间
    auto start = high_resolution_clock::now();

    for (int j = 0; j < 20; j++) {
        int page = pages[j];
        bool found = false;

        // 检查页面是否已在内存中
        for (int i = hh; i <= tt; i++) {
            if (memory[i] == page) {
                found = true;
                break;
            }
        }

        if (!found) {  // 缺页情况
            memory[++tt] = page; // 新页面加入队尾

            // 控制滑动窗口大小为 n
            if (tt - hh + 1 > n) {
                hh++; // 超过容量,队首出队
            }

            status[j] = false;  // 标记缺页
            pageFaults++;
        }
        else {
            status[j] = true;   // 标记命中
        }

        // 记录当前内存状态到表格
        for (int i = 0; i < n; i++) {
            //如果只写memory[hh]的话不就移动队首指针了吗,不可以,现在是赋值阶段,只需要控制负责赋值的滑动指针首先不能超过队尾指针,确保在滑动窗口范围内,
            //因为有可能这个滑动窗口不足n长,你就会多余赋值本来不能存在的页面号赋值成0x3f,其次需要满足当前检查是否缺页的一次记录memory,该位置是否有值
            if (i + hh <= tt && memory[i + hh] != 0x3f) {
                table[i][j] = memory[i + hh];
            }
            else {
                table[i][j] = -1; // 空位显示为 -1
            }
        }
    }

    //clock_t end = clock(); // 获取结束时间
    // 获取结束时间
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);

    // 输出结果表格
    cout << "主存块号 ";
    for (int j = 0; j < 20; j++) {
        cout << pages[j] << " ";
    }
    cout << endl;

    for (int i = 0; i < n; i++) {
        cout << "   " << i << "     ";
        for (int j = 0; j < 20; j++) {
            if (table[i][j] == -1) {
                cout << "  ";  // 空块显示为空格
            }
            else {
                cout << table[i][j] << " ";
            }
        }
        cout << endl;
    }

    // 输出缺页标记
    cout << "是否缺页 ";
    for (int j = 0; j < 20; j++) {
        cout << (status[j] ? "\u221A " : "\u00D7 ");//unicode编码,前者代表true则不缺页是√标识,后者代表false是缺页×表示
    }
    cout << endl;

    cout << "FIFO 缺页率: " << (float)pageFaults / 20 * 100 << "%" << endl;
    //cout << "运行时间: " << (double)(end - start) / CLOCKS_PER_SEC << " 秒" << endl;
    cout << "运行时间: " << duration.count() << " 微秒" << endl; // 输出运行时间

}
void lru(int n) {
    memset(table, -1, sizeof table);
    m.clear();
    bool status[20]; // 记录是否缺页

    int pageFaults = 0; // 缺页次数

    //clock_t start = clock(); // 获取开始时间
     // 获取开始时间
    auto start = high_resolution_clock::now();

    for (int j = 0; j < 20; j++) {
        int page = pages[j];

        if (!m.count(page)) { // 没命中就要加入或者替换页面
            if (m.size() >= n) {
                // 找到count最大的页面进行替换
                int maxpage = -1, maxcounts = -1;
                for (auto p : m) {
                    if (p.second > maxcounts) {
                        maxpage = p.first;
                        maxcounts = p.second;
                    }
                }
                m.erase(maxpage);
            }
            m[page] = 0;//没命中且主存没满则直接加入页面
            pageFaults++;
            status[j] = false; // 标记缺页
        }
        else {
            status[j] = true; // 标记命中
            m[page] = 0;
        }

        // 更新所有页面的count值:命中则置0,没命中加入新页面——满足条件则不加1即可,不管加不加入新页面,其他没中的页面都是要count+1的
        for (auto& p : m) {
            if (p.first != page) {
                p.second += 1;
            }
        }

        // 更新当前主存块内存在的页面
        int i = 0;
        for (auto p : m) {
            if (i < n) {//用一个i去便利贮存块,而不用for
                table[i][j] = p.first;
                i++;
            }
        }
        //一开始写错了:
        /*for (int i = 0; i < n; i++) {
            for (auto p : m) {
                table[i][j] = p.first;
            }
        }*/
    }

    //clock_t end = clock(); // 获取结束时间
    // 获取结束时间
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);

    // 输出结果表格
    cout << "主存块号 ";
    for (int j = 0; j < 20; j++) {
        cout << pages[j] << " ";
    }
    cout << endl;

    for (int i = 0; i < n; i++) {
        cout << "   " << i << "     ";
        for (int j = 0; j < 20; j++) {
            if (table[i][j] == -1) {
                cout << "  "; // 空块显示为空格
            }
            else {
                cout << table[i][j] << " ";
            }
        }
        cout << endl;
    }

    // 输出缺页标记
    cout << "是否缺页 ";
    for (int j = 0; j < 20; j++) {
        cout << (status[j] ? "\u221A " : "\u00D7 ");
    }
    cout << endl;

    cout << "LRU 缺页率: " << (float)(pageFaults) / 20 * 100 << "%" << endl;
    //cout << "运行时间: " << (double)(end - start) / CLOCKS_PER_SEC << " 秒" << endl;
    cout << "运行时间: " << duration.count() << " 微秒" << endl; // 输出运行时间
}

int main() {
    cout << "内存容量为 3 块:\n";
    fifo(3);
    cout << endl;
    lru(3);
    cout << endl;

    cout << "内存容量为 4 块:\n";
    fifo(4);
    cout << endl;
    lru(4);

    return 0;
}

1)主存块数越多的,不论哪个算法,运行时间都更长一些,用的时chrono精确时间微妙

但是同样的,运行每次的时间不定

2)主存块数越多的,不论哪个算法,缺页率都更低一些


http://www.kler.cn/a/405717.html

相关文章:

  • 【企业级分布式系统】ZooKeeper集群
  • HTML5 SVG
  • 如何给 Apache 新站点目录配置 SELinux ?
  • 冲破AI 浪潮冲击下的 迷茫与焦虑
  • 「甲子光年」对话黄翔:从电子签回望中国SaaS“黄金十年”
  • FileProvider高版本使用,跨进程传输文件
  • Vue.js 性能优化指南:掌握 keep-alive 的使用技巧
  • 面向对象-接口的使用
  • Spring框架特性及包下载(Java EE 学习笔记04)
  • SpringBoot与knife4j的整合使用
  • Spark RDD 的宽依赖和窄依赖
  • 2024年亚太数学建模竞赛问题C宠物产业及相关产业发展分析与对策
  • CEF127编译指南 Windows篇-安装Git和Python(三)
  • C语言深度剖析:定义与声明
  • Go-RPC关键指标分析与企业实践
  • Unity 编辑器下 Android 平台 Addressable 加载模型粉红色,类似材质丢失
  • 金融量化交易模型的突破与前景分析
  • PostGIS创建空间数据库步骤
  • .net6 使用 FreeSpire.XLS 实现 excel 转 pdf - docker 部署
  • 中国省级新质生产力发展指数数据(任宇新版本)2010-2023年
  • 单词的分类(二)冠词和数词
  • ANSYS HFSS仿真回流路径与跨分割布线
  • Go语言使用 kafka-go 消费 Kafka 消息教程
  • QA|使用 MapleSim 模拟卷料生产 (Converting)和卷对卷系统 (R2R)
  • Paper -- 洪水深度估计 -- 基于计算机视觉, 根据被淹车辆图像进行洪水深度估计
  • nginx 配置lua执行shell脚本