FIFO
FIFO算法是最早出现的置换算法。该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。
LRU
最近最久未使用(LRU)的页面置换算法是根据页面调入内存后的使用情况做出决策的,需要记录页面的访问时间。每当进程访问某页面时, 便将该页面的页面号从栈中移出,将它压入栈顶。因此,栈顶始终是最新被访问页面的编号,而栈底则是最近最久未使用页面的页面号。
代码实现
#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); }
效果图
先输入1,产生随机序列,模拟进程序号列
再输入2调用LRU
输入3调用FIFO
输入0退出