操作系统 页面置换算法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退出


目录
相关文章
|
2月前
|
算法 调度 UED
探索操作系统的心脏:调度算法的奥秘与影响
【10月更文挑战第9天】 本文深入探讨了操作系统中至关重要的组件——调度算法,它如同人体的心脏,维持着系统资源的有序流动和任务的高效执行。我们将揭开调度算法的神秘面纱,从基本概念到实际应用,全面剖析其在操作系统中的核心地位,以及如何通过优化调度算法来提升系统性能。
|
1月前
|
算法 调度 Python
深入理解操作系统中的进程调度算法
在操作系统中,进程调度是核心任务之一,它决定了哪个进程将获得CPU的使用权。本文通过浅显易懂的语言和生动的比喻,带领读者了解进程调度算法的重要性及其工作原理,同时提供代码示例帮助理解。
|
1月前
|
机器学习/深度学习 算法 数据挖掘
提高时钟置换算法的性能
【10月更文挑战第25天】通过上述一种或多种方法的综合应用,可以在不同程度上提高时钟置换算法的性能,使其更好地适应各种复杂的系统环境和应用场景,提高虚拟内存管理的效率和系统的整体性能。
125 62
|
1月前
|
算法
时钟置换算法
【10月更文挑战第25天】时钟置换算法是一种简单而有效的页面置换算法,它通过使用位标志和环形链表的结构,在一定程度上平衡了算法的复杂性和性能表现。虽然它存在一些局限性,但通过改进和与其他算法的结合,可以在不同的系统环境中发挥重要作用,提高虚拟内存管理的效率和系统的整体性能。
157 51
|
1月前
|
算法
虚拟内存的页面置换算法有哪些?
【10月更文挑战第25天】不同的页面置换算法各有优缺点,在实际应用中,操作系统会根据不同的应用场景和系统需求选择合适的页面置换算法,或者对算法进行适当的改进和优化,以平衡系统的性能、开销和资源利用率等因素。
64 5
|
1月前
|
算法 大数据 Linux
深入理解操作系统之进程调度算法
【10月更文挑战第24天】本文旨在通过浅显易懂的语言,带领读者深入了解操作系统中的进程调度算法。我们将从进程的基本概念出发,逐步解析进程调度的目的、重要性以及常见的几种调度算法。文章将通过比喻和实例,使复杂的技术内容变得生动有趣,帮助读者建立对操作系统进程调度机制的清晰认识。最后,我们还将探讨这些调度算法在现代操作系统中的应用和发展趋势。
|
2月前
|
算法 调度 UED
深入理解操作系统的进程调度算法
【10月更文挑战第7天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。它不仅影响系统的性能和用户体验,还直接关系到资源的合理分配。本文将通过浅显易懂的语言和生动的比喻,带你一探进程调度的秘密花园,从最简单的先来先服务到复杂的多级反馈队列,我们将一起见证算法如何在微观世界里编织宏观世界的和谐乐章。
|
2月前
|
边缘计算 算法 调度
探究操作系统的心脏:调度算法的进化与影响
【10月更文挑战第2天】 本文深入探讨了操作系统中核心组件——调度算法的历史演变、关键技术突破及其对现代计算的影响。通过详细回顾从单任务到多任务、实时系统及分布式计算环境下调度算法的发展,文章揭示了这些算法如何塑造我们的数字世界,并对未来的趋势进行了展望。不同于传统的摘要,本文特别聚焦于技术细节与实际应用的结合点,为读者提供一幅清晰的技术演进蓝图。
70 4
|
2月前
|
算法 调度 UED
探索操作系统的心脏:进程调度算法
【9月更文挑战第32天】在数字世界的每一次心跳中,都隐藏着一个不为人知的英雄——进程调度算法。它默默地在后台运作,确保我们的命令得到快速响应,应用程序平稳运行。本文将带你走进操作系统的核心,一探进程调度的奥秘,并通过代码示例揭示其背后的智慧。准备好跟随我一起深入这趟技术之旅了吗?让我们开始吧!
|
3月前
|
算法 调度
操作系统的心脏:深入解析进程调度算法
本文旨在深入探讨现代操作系统中的核心功能之一——进程调度。进程调度算法是操作系统用于分配CPU时间片给各个进程的机制,以确保系统资源的高效利用和公平分配。本文将详细介绍几种主要的进程调度算法,包括先来先服务(FCFS)、短作业优先(SJF)、时间片轮转(RR)以及优先级调度(PS)。我们将分析每种算法的基本原理、优缺点及其适用场景。同时,本文还将讨论多级反馈队列(MFQ)调度算法,并探讨这些算法在实际应用中的表现及未来发展趋势。通过深入解析这些内容,希望能够为读者提供对操作系统进程调度机制的全面理解。

热门文章

最新文章