操作系统OS-页面置换(FIFO,OPT,LRU)算法(c实现)

1. 算法原理

页面置换算法是操作系统内存管理的核心技术,当物理内存不足时,选择被替换页面的策略。目标是通过减少缺页中断提高系统性能。主要算法包括:
(1) 先进先出的算法(FIFO):选择在内存中驻留时间最久的页面予以替换。
(2) 最佳淘汰算法(OPT):选择永不使用或在未来最长时间内不再被访问的页面予以替换。
(3) 最近最久未使用算法(LRU):选择过去最长时间未被访问的页面予以替换。

2. 算法的数据结构

image

3. 算法和算法流程图

(1) 先进先出的算法(FIFO):
缺页中断 -> 选择最早进入的页面 -> 替换该页面
(2) 最佳淘汰算法(OPT):
缺页中断 -> 计算每个页面下次访问的时间 -> 选择最晚被访问的页面 -> 替换该页面
(3) 最近最久未使用算法(LRU):
缺页中断 -> 计算每个页面上次访问的时间 -> 选择最早被访问的页面 -> 替换该页面

4. 源程序

#include<stdio.h>
#define M 100

int mem[M]; //内存页面
int page[M] = {7,0,1,2,0,3,
0,4,2,3,0,3,2,1,2,0,1,7,0,1}; //读入页面

int memCap = 3; //内存容量
int pageNum = 20; //读入页面量
int lackNum; //缺页次数

void memInit(); //内存初始化
int isNeedSwap(int left,int right,int page); //检查是否需要置换
void show(int left,int right); //展示内存状态
void fifo(); //先进先出算法
int opt_getIndex(int currentNext); //opt获取被置换出的页面索引
void opt(); //最佳置换算法
int lru_getIndex(int currentPre); //lru获取被置换出的页面索引
void lru(); //最近最少使用算法

int main() {
    puts("------------FIFO------------");
    memInit();fifo();

    puts("------------OPT------------");
    memInit();opt();

    puts("------------LRU------------");
    memInit();lru();
}

void memInit() {
    for(int i=0; i<memCap; i++)
        mem[i] = -1;
}

int isNeedSwap(int left,int right,int page) {
    for(int i=left; i<right; i++) {
        if(mem[i] == page)
            return 0; //如果有,无需置换,返回0
    }
    return 1; //返回1,需要置换
}

void show(int left,int right) {
    printf("(");
    for(int i=left; i<right; i++)
        printf("<%d>", mem[i]);
    printf(")\n");
}

void fifo() {
    lackNum = 0;
    int left=0,right=memCap; //队列左右索引
    for(int i=0; i<pageNum; i++) {
        printf("%d次读入(%d)",i+1,page[i]);
        if(isNeedSwap(left,right,page[i])) {
            lackNum++;
            mem[right] = page[i];
            left++; //队列左索引右移
            right++; //队列右索引右移
        }
        printf("处理之后状态:");
        show(left,right);
    }
    printf("缺页次数%d,缺页率%.2f\n",lackNum,(float)lackNum/pageNum);
}

int opt_getIndex(int currentNext) {
    int nextTime[M]; //下次访问时间
    int isFutureUse,index;
    for(int i=0; i<memCap; i++) {
        if(mem[i] == -1) return i;
        else {
            isFutureUse = 0; //假设未来没有使用
            for(int j=currentNext; j<pageNum; j++) {
                if(mem[i] == page[j]) {
                    isFutureUse = 1;
                    nextTime[i] = j; //记录使用时间
                    break;
                }
            }
            if(!isFutureUse) nextTime[i] = M; //即未来未使用
        }
    }
    index = 0;
    //puts("");
    //printf("<%d下次使用为%d>", mem[index], nextTime[index]);
    for(int i=1; i<memCap; i++) {
        //printf("<%d下次使用为%d>", mem[i], nextTime[i]);
        if(nextTime[i] > nextTime[index])
            index = i;
    }
    //printf("即将取出%d  ",mem[index]);
    return index;
}

void opt() {
    lackNum = 0;
    int left=0,right=memCap;
    for(int i=0; i<pageNum; i++) {
        printf("%d次读入(%d)",i+1,page[i]);
        if(isNeedSwap(left,right,page[i])) {
            lackNum++;
            mem[opt_getIndex(i+1)] = page[i];
        }
        printf("处理之后状态:");
        show(left,right);
    }
    printf("缺页次数%d,缺页率%.2f\n",lackNum,(float)lackNum/pageNum);
}

int lru_getIndex(int currentPre) {
    int preTime[M]; //之前使用时间
    int isPreUse,index;
    for(int i=0; i<memCap; i++) {
        if(mem[i] == -1) return i;
        else {
            isPreUse = 0; //假设之前未使用
            for(int j=currentPre; j>-1; j--) {
                if(mem[i] == page[j]) {
                    isPreUse = 1;
                    preTime[i] = j; //记录之前使用时间
                    break;
                }
            }
            if(!isPreUse) preTime[i] = -M; //即之前未使用
        }
    }
    index = 0;
    //puts("");
    //printf("<%d上次使用为%d>", mem[index], preTime[index]);
    for(int i=1; i<memCap; i++) {
        //printf("<%d上次使用为%d>", mem[i], preTime[i]);
        if(preTime[i] < preTime[index])
            index = i;
    }
    //printf("即将取出%d  ",mem[index]);
    return index;
}

void lru() {
    lackNum = 0;
    int left=0,right=memCap;
    for(int i=0; i<pageNum; i++) {
        printf("%d次读入(%d)",i+1,page[i]);
        if(isNeedSwap(left,right,page[i])) {
            lackNum++;
            mem[lru_getIndex(i-1)] = page[i];
        }
        printf("处理之后状态:");
        show(left,right);
    }
    printf("缺页次数%d,缺页率%.2f\n",lackNum,(float)lackNum/pageNum);
}
posted @ 2025-08-01 10:41  57sd1  阅读(295)  评论(0)    收藏  举报