内存置换策略--LRU、FIFO、Clock算法(C语言实现)

1 篇文章 0 订阅
1 篇文章 0 订阅
本文详细解析了内存置换策略中的LRU(最近最少使用)、FIFO(先进先出)和Clock(时钟)算法,通过C语言代码实例展示了它们的工作原理和运行结果。特别强调了LRU在性能上的优势以及FIFO和Clock的改进方法。
摘要由CSDN通过智能技术生成

内存置换策略

1.最近最少使用(LRU)算法

  • 概念:LRU策略置换内存中最长时间未被引用的页。根据局部性原理,这也是最近最不可能访问到的页。

  • 实现方法:一种实现方法是给每页添加一个最后一次访问的时间戳,在每次访问内存时更新这个时间戳。
    另一种实现方法是创建一个关于访问页的栈,当有新页进入时,将之前的页按顺序压向栈底,内存不足时将栈底的页面移除,然后将新页放置在栈顶位置。

    本次采用第一种方法:添加时间戳。

  • 基于C语言数组使用LRU算法代码参考:

    #include <stdio.h>
    #define N 3				//内存容量
    
    struct lru{
    	int value;
    	int t;
    } page[N];
    
    void print(){
    	int i;
    	printf("页面存储状态:\n");
    	for (i=0; i<N; i++){
    		printf("value=%d   time=%d\n",page[i].value,page[i].t);
    	}
    }
    
    int lru(int x){
    	int i,j,k;
    	k=0;
    	for (i=0; i<N; i++){
    		if (x==page[i].value){
    			printf("找到请求页面\n");
    			page[i].t = 0;
    			for (j=0; j<N; j++){
    				if (j != i) {
    					page[j].t += 1;
    				}
    			}
    			return 1;
    		}
    	}
    	for (i=0; i<N; i++){
    		if (page[i].value == 0){
    			j = i;
    			break;
    		}
    		else if (k < page[i].t){
    			k = page[i].t;
    			j = i;
    		}
    	}
    	printf("淘汰页面:%d\n",page[j].value);
    	page[j].value = x;
    	page[j].t = 0;
    	for (i=0; i<N; i++){
    				if (i != j) {
    					page[i].t += 1;
    				}
    			}
    	return 0;
    }
    
    int main(void){
    	int x;
    	print();
    	while (1){
    		printf("输入请求页:");
    		scanf("%d",&x);
    		lru(x);
    		print();
    	} 
    	return 0;
    }
    
  • 运行结果:

    在这里插入图片描述

  • 分析:在实际使用中,如果数据量较大的话最好选择采用双链表,链表的置换速度会比较快。Java的LinkedHashMap可以很好实现哈希链表,以后有空再来补充~~

2.FIFO(先进先出)算法

  • 概念:FIFO策略把分配给进程的页框视为一个循环缓冲区,并按循环方式移动页,通俗点说就是将驻留在内存中时间最长的页面置换出去

  • 实现方法:记录每个页面载入内存的顺序,若未在内存中找到所请求的页面,则将新页放置在页面载入顺序最大的位置,并将该位置的顺序记为0。每次进行请求页面操作后,将所存页面的载入顺序全部加1.

  • 基于C语言数组实现FIFO算法代码参考:

    #include <stdio.h>
    #define N 3
    
    struct fifo{
    	int value;
    	int t;						//记录页面载入时间顺序
    } page[N];
    
    void print(){
    	int i;
    	printf("页面存储状态:\n");
    	for (i=0; i<N; i++){
    		printf("%2d",page[i].value);
    	}
    	printf("\n");
    }
    
    void fifo(int x){
    	int i,j;
    	for (i=0; i<N; i++){
    		if (x==page[i].value){
    			printf("找到请求页面\n");
    			break;
    		}
    		if (page[i].value == 0){
    			j = i;
    			break;
    		}
    		else if (page[i].t > page[j].t){
    			j = i;
    		}
    	}
    	printf("淘汰页面:%d\n",page[j].value);
    	page[j].value = x;
    	page[j].t = 0;
    	for(i=1; i<N; i++){
            page[j].t++;
    		if (j==2){
    			j = 0;
    		}else j++;	
    	}
    }
    
    int main(void){
    	int x;
    	print();
    	while (1){
    		printf("输入请求页:");
    		scanf("%d",&x);
    		fifo(x);
    		print();
    	} 
    	return 0;
    }
    
  • 运行结果:

在这里插入图片描述

  • 分析:

    FIFO策略与LRU策略相比,FIFO实现简单,但性能相对较差。例如上面两个算法的输入是相同的,但FIFO多了一次缺页中断,尤其是出现一部分程序或数据在整个程序的生命周期中使用评率较高的情况,若使用FIFO算法,则这些页会被反复地换入和换出。

    有没有方法能以较小的开销来获得近似于LRU的性能呢?有,这类方法几乎都是时钟策略(Clock)的各种变体。

3.Clock(时钟)算法

  • 概念与实现方法:Clock策略给每一个页框附加一个使用位和一个指针,每次内存装入一个页面时,将该页框的使用位置为1。当输入请求页时,先循环整个内存空间判断是否有对应的值,若有,将该页框的使用位数值进行反转(即1转0,0转1),如果指针刚好指向该位置则将指针移动到下一位置;若内存中没有该请求页,则从指针位置开始判断该页框的使用位是否为0,若为0则将该页置换,若不为0,使用位数值反转,指针移向下一页框。

    这里转载一篇用图来解释的博文,能帮助理解,针不戳:时钟(CLOCK)置换算法流程

  • 基于C语言数组实现Clock算法代码参考:

    #include <stdio.h>
    #define N 3
    
    struct CLOCK{
    	int value;
    	bool t;						//使用位,值为0或1
    }page[N];
    
    int clock(int x,int p){
    	int i;
    	for (i=0; i<N; i++){
    		if (page[i].value == x){
    			printf("找到页面%d\n",page[i].value);
    			page[i].t = not page[i].t;
    			if (page[p].value == page[i].value){
    				if (p<2){
    					p++;
    				}else p=0;
    			}
    			return p;
    		}
    	}
    	while(1){
    		if (page[p].value !=x && page[p].t == 0){
    			printf("置换页面%d\n",page[p].value);
    			page[p].value = x;
    			page[p].t = not page[p].t;
    			if (p<2){
    				p++;
    			}else p=0;
    			return p;
    		}else {
    			page[p].t = not page[p].t;
    			if (p<2){
    				p++;
    			}else p=0;
    		}
    	}
    	
    }
    
    void print(int p){
    	int i;
    	printf("页面存储状态:\n");
    	for (i=0; i<N; i++){
    		printf("%2d",page[i].value);		
    	}
    	printf(" 指针指向第%d页\n",p+1);
    	printf("\n");
    }
    
    int main(void){
    	int x,p;
    	p = 0;
    	print(p);
    	while(1){
    		printf("请输入请求页面:");
    		scanf("%d",&x);
    		p = clock(x,p);
    		print(p);
    	}
    	return 0;
    }
    
  • 运行结果:

在这里插入图片描述

  • 补充:

    改进型的CLOCK算法

    在之前的CLOCK算法上面除了使用位,再增加一个修改位。现在每一页有两个状态,分别是(使用位,修改位),可分为以下四种情况考虑:

    (0,0):最近没有使用也没有修改

    (0,1):最近没有使用但修改过,将会被写

    (1,0):最近使用过但没有被修改,下一轮将再次被用

    (1,1):最近使用过也修改过,下一轮页面置换最后的选择

    每次从指针当前位置先寻找内存中是否有(使用位,修改位)为(0,0)的页面,如果没有则找(0,1)的页面;如果指针循环一周后依然未找到,将集合中所有页面的使用位置为0,重复前面的操作,最后一定能找到能够替换的页框。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值