操作系统 页面置换算法FIFO与LRU的实现

简介: 操作系统 页面置换算法FIFO与LRU的实现

FIFO

FIFO算法是最早出现的置换算法。该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。

image.png

LRU

最近最久未使用(LRU)的页面置换算法是根据页面调入内存后的使用情况做出决策的,需要记录页面的访问时间。每当进程访问某页面时, 便将该页面的页面号从栈中移出,将它压入栈顶。因此,栈顶始终是最新被访问页面的编号,而栈底则是最近最久未使用页面的页面号。

image.png

代码实现

#include<conio.h> 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Myprintf printf("|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|\n") //表格控制
#define bsize 4     //物理块大小
#define psize 16     //进程大小
typedef struct page{ 
       int num;  //记录页面号
       int time;  //记录调入内存时间
}Page;                   //页面逻辑结构,结构为方便算法实现设计
Page b[bsize];            //内存单元数 
int c[bsize][psize];   //暂保存内存当前的状态:缓冲区
int queue[100];      //记录调入队列
int K;              //调入队列计数变量 
int phb[bsize] = {0};   //物理块标号
int pro[psize] = {0};     //进程序列号
int flag[bsize] = {0};  //进程等待次数(存放最久未被使用的进程标志)
int i = 0, j = 0, k = 0;   //i表示进程序列号,j表示物理块号
int m = -1, n = -1;       //物理块空闲和进程是否相同判断标志
int max = -1,maxflag = 0; //标记替换物理块进程下标
int count = 0;            //统计页面缺页次数
int* build(){
  //随机产生序列号函数
  printf("随机产生一个进程序列号为:\n");
  int i = 0;
    for(i=0; i<psize; i++){
    pro[i] = 10*rand()/(RAND_MAX+1)+1;
        printf("%d  ",pro[i]);
    }
    printf("\n");
  return(pro);
}
int searchpb(){
  //查找空闲物理块
  for(j=0; j<bsize; j++){
    if(phb[j] == 0){
           m = j; 
       return m;     
           break;
        } 
  }
  return -1;
}
int searchpro(){
  //查找相同进程
  for(j = 0; j < bsize; j++){
       if(phb[j] == pro[i]){
          n = j;
      return j;
       }
    }
  return -1;
}
void empty(){
  //初始化内存
  for(i=0;i<bsize;i++){
    phb[i]=0;
  }
    count=0;                //计数器置零
}
void FIFO(){
   //先进先出页面置换算法
    for(i = 0; i<psize; i++){ 
     m=searchpb();
     n=searchpro();
        for(j = 0; j < bsize;j++){
          //找flag值最大的
           if(flag[j]>maxflag){
                maxflag = flag[j];
                max = j;
            }
        }   
        if(n == -1){               
      //不存在相同进程
           if(m != -1){            
                //存在空闲物理块
          phb[m] = pro[i];   //进程号填入该空闲物理块
          count++;
                flag[m] = 0;
                for(j = 0;j <= m; j++){
                    flag[j]++;
                }
                m = -1;
           }
           else{               
                //不存在空闲物理块
              phb[max] = pro[i];
                flag[max] = 0;
                for(j = 0;j < bsize; j++){
                  flag[j]++;
                }
                max = -1;
                maxflag = 0;
                count++;
           }
       }
       else{                    
      //存在相同的进程
        phb[n] = pro[i];
            for(j = 0;j < bsize; j++){
         flag[j]++;
            }
            n = -1;
       }
        for(j = 0 ;j < bsize; j++){
        printf("%d  ",phb[j]);
        }
       printf("\n");
    }
    printf("缺页次数为:%d\n",count);
  printf("\n");
}
void Init(Page *b,int c[bsize][psize]){ 
  //初始化内存单元、缓冲区
    int i,j; 
    for(i=0;i<psize;i++){ 
        b[i].num=-1; 
        b[i].time=psize-i-1; 
    } 
    for(i=0;i<bsize;i++) 
        for(j=0;j<psize;j++) 
            c[i][j]=-1; 
} 
int GetMax(Page *b){ 
  //取得在内存中停留最久的页面,默认状态下为最早调入的页面
    int i; 
    int max=-1;
    int tag=0;
    for(i=0;i<bsize;i++){ 
        if(b[i].time>max){ 
            max=b[i].time; 
            tag=i; 
        } 
    } 
    return tag; 
}
int Equation(int fold,Page *b){ 
  //判断页面是否已在内存中
    int i; 
    for(i=0;i<bsize;i++){ 
        if (fold==b[i].num) 
            return i; 
    } 
    return -1; 
} 
void Lruu(int fold,Page *b){ 
  //LRU核心部分
    int i; 
    int val; 
    val=Equation(fold,b); 
    if (val>=0){ 
        b[val].time=0; 
        for(i=0;i<bsize;i++) 
            if (i!=val) 
                b[i].time++; 
    } 
    else{
        queue[++K]=fold; //记录调入页面
        val=GetMax(b); 
      b[val].num=fold; 
        b[val].time=0; 
        for(i=0;i<bsize;i++) 
            if (i!=val) 
                b[i].time++; 
    } 
}
void LRU(){
    int i,j; 
    K=-1; 
    Init(b, c); 
    for(i=0;i<psize;i++){ 
        Lruu(pro[i],b); 
        c[0][i]=pro[i]; 
        //记录当前的内存单元中的页面
            for(j=0;j<bsize;j++) 
                c[j][i]=b[j].num; 
    } 
    //结果输出 
    printf("内存状态为:\n"); 
    Myprintf; 
    for(j=0;j<psize;j++) 
      printf("|%2d ",pro[j]); 
        printf("|\n"); 
        Myprintf; 
        for(i=0;i<bsize;i++){ 
            for(j=0;j<psize;j++){ 
                if(c[i][j]==-1) 
                    printf("|%2c ",32); 
                else 
                    printf("|%2d ",c[i][j]); 
            } 
            printf("|\n"); 
        } 
        Myprintf; 
        printf("\n调入队列为:"); 
        for(i=0;i<K+1;i++) 
    printf("%3d",queue[i]); 
        printf("\n缺页次数为:%6d\n缺页率:%16.6f",K+1,(float)(K+1)/psize); 
}
int main()
{
  int sel;  
    do{ 
      printf("0、退出(Exit)\n");
      printf("1、产生随机序列\n");
      printf("2、最久未使用(LRU)\n");
      printf("3、先进先出(FIFO)\n");
      printf("<请选择所要执行的操作:(0)(1)(2)(3)>\n");
      scanf("%d",&sel);
      if(sel == 0){
        printf("退出 \n");
    }
    if(sel == 1){
      build();
    }
    if(sel == 2){
      printf("LRU\n");
      LRU();
      empty();
      printf("\n");
    }
    if(sel == 3){
      printf("FIFO\n");
      FIFO();
      empty();
      printf("\n");
    }
  }while(sel!=0);
}

效果图

image.png

先输入1,产生随机序列,模拟进程序号列

image.png

再输入2调用LRU

image.png

输入3调用FIFO

image.png

输入0退出


目录
相关文章
|
10天前
|
算法 调度 UED
深入理解操作系统之进程调度算法
【9月更文挑战第9天】在操作系统的心脏跳动中,进程调度扮演着关键角色,就如同指挥家控制交响乐的节奏。本文将通过浅显易懂的语言和生动的比喻,带领读者走进进程调度的世界,探索不同调度算法背后的哲学与实践,以及它们如何影响系统的性能和用户体验。从最简单的先来先服务到复杂的多级队列和反馈循环,我们将一同见证操作系统如何在众多任务中做出选择,确保系统的高效与公平。
|
26天前
|
缓存 算法 前端开发
深入理解缓存淘汰策略:LRU和LFU算法的解析与应用
【8月更文挑战第25天】在计算机科学领域,高效管理资源对于提升系统性能至关重要。内存缓存作为一种加速数据读取的有效方法,其管理策略直接影响整体性能。本文重点介绍两种常用的缓存淘汰算法:LRU(最近最少使用)和LFU(最不经常使用)。LRU算法依据数据最近是否被访问来进行淘汰决策;而LFU算法则根据数据的访问频率做出判断。这两种算法各有特点,适用于不同的应用场景。通过深入分析这两种算法的原理、实现方式及适用场景,本文旨在帮助开发者更好地理解缓存管理机制,从而在实际应用中作出更合理的选择,有效提升系统性能和用户体验。
56 1
|
20天前
|
存储 算法 调度
深入理解操作系统:进程调度的算法与实现
【8月更文挑战第31天】在操作系统的核心,进程调度扮演着关键角色,它决定了哪个进程将获得CPU的使用权。本文不仅剖析了进程调度的重要性和基本概念,还通过实际代码示例,展示了如何实现一个简单的调度算法。我们将从理论到实践,一步步构建起对进程调度的理解,让读者能够把握操作系统中这一复杂而精妙的部分。
|
20天前
|
算法 调度 开发者
深入理解操作系统:进程管理与调度算法
在数字时代的心脏,操作系统扮演着至关重要的角色。它不仅是计算机硬件与软件之间的桥梁,更是确保多任务高效运行的守护者。本文将带你一探操作系统中进程管理的奥秘,并通过实际代码示例深入解析进程调度算法。无论你是编程新手还是资深开发者,了解这些基础概念都将有助于你更好地理解计算机工作原理,并提升你对系统性能调优的认识。准备好,让我们一起揭开操作系统的神秘面纱!【8月更文挑战第31天】
|
20天前
|
算法 调度
探索操作系统的心脏:进程调度算法揭秘
【8月更文挑战第31天】本文将带领读者深入理解操作系统中至关重要的一环——进程调度。通过浅显易懂的语言和逐步深入的内容安排,我们将从基础概念入手,探讨进程调度的目的和挑战,进而分析几种常见的调度算法。文中不仅提供了丰富的代码示例,还设计了互动问题,鼓励读者思考并应用所学知识。让我们一起揭开操作系统进程调度的神秘面纱,看看它是如何在幕后支撑着我们日常使用的电脑和移动设备的顺畅运行。
|
1月前
|
算法 程序员
理解操作系统内存管理:页面置换算法全解析
大家好,我是小米,热爱分享技术的大哥哥!今天聊的是操作系统中的页面置换算法。它解决的是内存满载时,如何选择合适的页面移出以腾出空间的问题。主要有三种算法:FIFO(先进先出),简单但性能不佳;LRU(最近最久未使用),考虑时间局部性,性能较好但实现较复杂;OPT(最佳置换),理论上最优但无法实际应用。这些算法各有千秋,在实际应用中需根据场景选择最合适的方案。希望这能帮大家更好地理解内存管理的核心机制!
72 2
|
2月前
|
算法 大数据 调度
探索操作系统的心脏:进程调度算法
【7月更文挑战第31天】在数字世界的复杂编织中,操作系统扮演着枢纽的角色,而进程调度则是其跳动的心脏。本文将深入探讨几种常见的进程调度算法,通过代码示例揭示它们对系统性能的影响,并讨论如何根据应用场景选择恰当的调度策略。
22 1
|
2月前
|
算法 调度 UED
深入理解操作系统之进程调度算法
【7月更文挑战第31天】在操作系统的设计中,进程调度是核心功能之一,它直接关系到系统性能和用户体验。本文将探讨几种常见的进程调度算法,并通过代码示例加深理解。我们将从理论到实践,一探究竟。
26 0
|
15天前
|
算法 BI Serverless
基于鱼群算法的散热片形状优化matlab仿真
本研究利用浴盆曲线模拟空隙外形,并通过鱼群算法(FSA)优化浴盆曲线参数,以获得最佳孔隙度值及对应的R值。FSA通过模拟鱼群的聚群、避障和觅食行为,实现高效全局搜索。具体步骤包括初始化鱼群、计算适应度值、更新位置及判断终止条件。最终确定散热片的最佳形状参数。仿真结果显示该方法能显著提高优化效率。相关代码使用MATLAB 2022a实现。
|
15天前
|
算法 数据可视化
基于SSA奇异谱分析算法的时间序列趋势线提取matlab仿真
奇异谱分析(SSA)是一种基于奇异值分解(SVD)和轨迹矩阵的非线性、非参数时间序列分析方法,适用于提取趋势、周期性和噪声成分。本项目使用MATLAB 2022a版本实现从强干扰序列中提取趋势线,并通过可视化展示了原时间序列与提取的趋势分量。代码实现了滑动窗口下的奇异值分解和分组重构,适用于非线性和非平稳时间序列分析。此方法在气候变化、金融市场和生物医学信号处理等领域有广泛应用。