由于本人java学艺不精,这两种算法均采用最基础的for循环来实现。等本小媛再修炼修炼,会对此代码进行优化,大家敬请期待。

FIFO先进先出算法

 算法原理:

 

  • 要淘汰内存某页时,选择 最先进入内存的页 淘汰。
  • 例:已知 进程页面走向如下:    7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1    供该进程使用的内存块数为3, 采用 请求 调页    策略。
  •   (1) 画出访问各页时内存块中页号情况   (2) 求缺页率

 

  • 缺页率的计算:当CPU进入内存找某页时发现没有,需要重新调入,属于一次缺页。

代码实现:

代码实现分为两部分:part1:先从外部调入进程页直到内存块满;part2:当内存块满了之后,若要调入新的进程页号,则需根据先进先出原则淘汰内存块中的页号。

part1:当第一个页号调入内存时,由于内存块内为空,可直接调入。从第二个页号调入时,就要与之前已经调入内存块的页号进行对比。如果某页之前已被调入进内存块,则不需要再调入。非缺页记录变量加一;如果某页之前未被调用过,则此时被调入进内存块。

part2:当内存块被填满之后,在调用下一个进程页时,与内存块中已有的页号进行对比,如果之前已被调入,则不需要被再次调入。非缺页变量加一;如果之前未被调用,则需淘汰内存块中现有的页号,根据先进先出原则,在数组中i值最小的,是最早进入内存块的,i值大的是最晚进入内存块的。所以在淘汰进程页时,可以从i=0;开始淘汰,直到淘汰到i=number;

		     int yes=0;
		     int [] block=new int [number];//blcok数组是用来存放内存块内数据的,在这里先往内存块内存放数据,将内存块填满
		     block[0]=page[0];//最开始的时候,block里面是空的,所以可以直接进程页号可直接调入内存块中
		     for(int i=1;i<number;i++){//for循环将进程页号调入数组
		    	 boolean o=false;
		    	for(int m=0;m<i;m++){//本层循环来判断内存中是否已经存在要使用的进程的页号
		    	if (block[m]==page[i]){
		    		yes++;//如果内存块中存在要调用的页号,则非缺页次数加一
		    		o=true;}
		    	}
		    	while(o){
		    		for(int j=0;j<i-1;j++){//输出此时内存块中的页号情况,由于此时内存块中并未赋新值,所以内存块中的情况依旧是上一轮循环后的结果。
			    		System.out.print(block[j]+" ");
		    		}
		    		break;
		    	}
		    	while(!o){
		    		block[i]=page[i];//如果内存中不存在要调用的页号,则将新页号调入内存块
		    		for(int j=0;j<i;j++){
			    		System.out.print(block[j]+" ");
			    	
		    		}
		    		break;
		    	}
		    	System.out.println();
		}
		   
		int s=0;
		int n=0;
		for(int i=number;i<p;i++){//内存块被装满后
			boolean e=false;
			for(int j=0;j<number;j++){
				if (page[i]==block[j]){
					e=true;
					n++;}//非缺页变量
				
				}
		if(e){
			for(int m=0;m<number;m++){//输出此时内存块中的已有页号
				System.out.print(block[m]+" ");
				
				}
		}
		else{
					
					block[s]=page[i];//数组中的页号从block[0]到block[number]
					s++;
					if(s==number){
						s=0;//当到达数组最大值后,s再变为0,新的一轮淘汰开始
					}
					for(int m=0;m<number;m++){
						System.out.print(block[m]+" ");
						
				}
			}
		System.out.println();
		}
		System.out.println("缺页次数:"+(p-n-yes)+"次");//非缺页次数由n和yes两部分组成
	
		double g=(p-n-yes)/(double)p;
		System.out.print("缺页率:");
		System.out.println(String.format("%.2f",g));

LRU算法  最近最久未使用置换法 ( LRU= Least Recently Used )

算法思想:

需要淘汰页面时,选择内存中最近一段时间里最久没有使用过 页面淘汰。

 

通常会使用一个 栈 来保存在内存中的页面的页号。当一个页面被访问时,其对应的页号要放在栈顶,当要淘汰页面时,栈底页号对应的页面即为要淘汰的页面(即最近最久未被访问的页面)。

由于我不会用代码表示栈,所以我还是用了数组。用i=0;表示栈底。i=number;表示栈顶。嘻嘻嘻

代码实现:依旧是分成两个部分;part1:先填满内存块;part2:对内存块内的页号进行淘汰。

此算法难点是,当要调入的页号已经在内存块内时,需要将此页号的位置放到栈顶,也就是数组=number的位置,并将数组内的其他页号向栈底推,也就是向i=0;的方向推。

		int yes2=0;
		int y=0;
	     int [] block2=new int [number];//block2数组来存放内存块内的页号。方法与FIFO相同
	     block2[0]=page[0];
	     for(int i=1;i<number;i++){
	    	 boolean o=false;
	    	for(int m=0;m<i;m++){
	    	if (block2[m]==page[i]){//如果页号已经在内存块内
	    	        yes2++;//非缺页变量加一
	    		o=true;
	    		y=m;
			int z=block2[y];//当页号已在内存块中时,将此页号提到栈顶,其余页号往栈底推
			for(int f=y+1;f<i;f++){
				block2[f-1]=block2[f];
			}
			block2[i-1]=z;
			break;
	    		}
	    	}
	    	while(o){
	    		
	    		for(int j=0;j<i-1;j++){
		    		System.out.print(block2[j]+" ");
	    		}
	    		break;
	    	}
	    	while(!o){
	    		block2[i]=page[i];
	    		for(int j=0;j<i;j++){
		    		System.out.print(block2[j]+" ");
		    	
	    		}
	    		break;
	    	}
	    	System.out.println();
	}

	int n2=0;
	int b;
	for(int i=number;i<p;i++){//内存块已满,淘汰页号算法
		boolean e2=false;
		for(int j=0;j<number;j++){
			if (page[i]==block2[j]){
				e2=true;
				n2++;
				b=j;
				int z=block2[b];
				for(int f=b+1;f<number;f++){
					block2[f-1]=block2[f];
					}
				block2[number-1]=z;
				break;
				}
			
			}
	if(e2){
		
		for(int m=0;m<number;m++){
		
			System.out.print(block2[m]+" ");
			
			}
	}
	else{
				for(int h=1;h<number;h++){
					block2[h-1]=block2[h];
				}
				block2[number-1]=page[i];
			
				for(int m=0;m<number;m++){
					System.out.print(block2[m]+" ");
					
			}
		}
	System.out.println();
	}
	System.out.println("缺页次数:"+(p-n2-yes2)+"次");
	
	double g2=(p-n2-yes2)/(double)p;
	System.out.print("缺页率:");
	System.out.println(String.format("%.2f",g2));

最后整体代码我也放到这里啦 (此代码只适合进程页号不小于内存块的情况,本人觉得如果进程页号小于内存块也就没有太大的必要性去研究了)

import java.util.Scanner;


public class Fal {

	public static void main(String[] args) {
		Scanner in=new Scanner (System.in);
		System.out.print("请输入内存块数:");
		int number=in.nextInt();
		System.out.print("请输入进程页数:");
		int p=in.nextInt();
		System.out.print("请输入页面走向:");
		int [] page=new int [p];//用page数组存储页面走向
		for(int i=0;i<p;i++){
			page[i]=in.nextInt();
	}
		System.out.print("页面走向为:");
		for(int i=0;i<p;i++){
			System.out.print(page[i]+" ");	
		}
		System.out.println();
		
		
	
		
			System.out.println(" FIFO页面置换算法");	//从这儿开始是FIFO算法
			System.out.println("各物理块中的页号情况");	
			
		     int yes=0;
		     int [] block=new int [number];//blcok数组是用来存放内存块内数据的,在这里先往内存块内存放数据,将内存块填满
		     block[0]=page[0];//最开始的时候,block里面是空的,所以可以直接进程页号可直接调入内存块中
		     System.out.println(block[0]);
		     int x=1;
	
		     for(int i=1;i<number;i++){//for循环将进程页号调入数组
		    	 boolean o=false;
		    	
		    	 
		    	for(int m=0;m<i;m++){//本层循环来判断内存中是否已经存在要使用的进程的页号
		    	if (block[m]==page[i]){
		    		yes++;//如果内存块中存在要调用的页号,则非缺页次数加一
		    		o=true;}
		    	}
		    	while(o){
		    		for(int j=0;j<x;j++){//输出此时内存块中的页号情况,由于此时内存块中并未赋新值,所以内存块中的情况依旧是上一轮循环后的结果。
			    		System.out.print(block[j]+" ");
		    		}
		    		break;
		    	}
		    	while(!o){
		    		block[i]=page[i];//如果内存中不存在要调用的页号,则将新页号调入内存块
		    		x++;//x用来统计已调入的页号个数,如果调入了新的页号,则x++;方便输出。
		    		for(int j=0;j<x;j++){
			    		System.out.print(block[j]+" ");
			    	
		    		}
		    		break;
		    	}
		    	System.out.println();
		}
		     
		   
		int s=0;
		int n=0;
		for(int i=number;i<p;i++){//内存块被装满后
			boolean e=false;
			for(int j=0;j<number;j++){
				if (page[i]==block[j]){
					e=true;
					n++;}//非缺页变量
				
				}
		if(e){
			for(int m=0;m<number;m++){//输出此时内存块中的已有页号
				System.out.print(block[m]+" ");
				
				}
		}
		else{
					
					block[s]=page[i];//数组中的页号从block[0]到block[number]
					s++;
					if(s==number){
						s=0;//当到达数组最大值后,s再变为0,新的一轮淘汰开始
					}
					for(int m=0;m<number;m++){
						System.out.print(block[m]+" ");
						
				}
			}
		System.out.println();
		}
		     
		     
		System.out.println("缺页次数:"+(p-n-yes)+"次");//非缺页次数由n和yes两部分组成
	
		double g=(p-n-yes)/(double)p;
		System.out.print("缺页率:");
		System.out.println(String.format("%.2f",g));
		     
		    
		System.out.println("_________________________________");
		System.out.println("  LRU 页面置换算法");
		System.out.println("采用栈保存的方法");
		    
		int yes2=0;
		int y=0;
	     int [] block2=new int [number];//block2数组来存放内存块内的页号。方法与FIFO相同
	     block2[0]=page[0];
	     System.out.println(block[0]);
	     x=1;
	     for(int i=1;i<number;i++){
	    	 boolean o=false;
	    	for(int m=0;m<i;m++){
	    	if (block2[m]==page[i]){//如果页号已经在内存块内
	    		yes2++;//非缺页变量加一
	    		o=true;
	    		y=m;
				int z=block2[y];//当页号已在内存块中时,将此页号提到栈顶,其余页号往栈底推
				for(int f=y+1;f<x;f++){
					block2[f-1]=block2[f];
					}
				block2[x-1]=z;
				break;
	    		}
	    	}
	    	while(o){
	    		
	    		for(int j=0;j<x;j++){
		    		System.out.print(block2[j]+" ");
	    		}
	    		break;
	    	}
	    	while(!o){
	    		block2[i]=page[i];
	    		x++;
	    		for(int j=0;j<x;j++){
		    		System.out.print(block2[j]+" ");
		    	
	    		}
	    		break;
	    	}
	    	System.out.println();
	}

	int n2=0;
	int b;
	for(int i=number;i<p;i++){//内存块已满,淘汰页号算法
		boolean e2=false;
		for(int j=0;j<number;j++){
			if (page[i]==block2[j]){
				e2=true;
				n2++;
				b=j;
				int z=block2[b];
				for(int f=b+1;f<number;f++){
					block2[f-1]=block2[f];
					}
				block2[number-1]=z;
				break;
				}
			
			}
	if(e2){
		
		for(int m=0;m<number;m++){
		
			System.out.print(block2[m]+" ");
			
			}
	}
	else{
				for(int h=1;h<number;h++){
					block2[h-1]=block2[h];
				}
				block2[number-1]=page[i];
			
				for(int m=0;m<number;m++){
					System.out.print(block2[m]+" ");
					
			}
		}
	System.out.println();
	}
	System.out.println("缺页次数:"+(p-n2-yes2)+"次");
	
	double g2=(p-n2-yes2)/(double)p;
	System.out.print("缺页率:");
	System.out.println(String.format("%.2f",g2));
		
	}
		

}

 

本代码重复性高,且十分繁琐。但是由于本小媛技术不精,现在的能力也只能写成这样了,此后,等本小媛修炼一番,会对次代码进行优化。欢迎路过的各位大佬们,批评指点。

 

 

Logo

鸿蒙生态一站式服务平台。

更多推荐