页面置换算法

页面置换算法

      地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断。当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法。


最佳置换算法(OPT)

       从主存中移出永远不再需要的页面;如无这样的页面存在,则选择最长时间不需要访问的页面。于所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。 
最佳置换算法可以用来评价其他算法。假定系统为某进程分配了三个物理块,并考虑有以下页面号引用串:
    7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1
      进程运行时,先将7, 0, 1三个页面依次装入内存。进程要访问页面2时,产生缺页中断,根据最佳置换算法,选择第18次访问才需调入的页面7予以淘汰。然后,访问页面0时,因为已在内存中所以不必产生缺页中断。访问页面3时又会根据最佳置换算法将页面1淘汰……依此类推,如图3-26所示。从图中可以看出釆用最佳置换算法时的情况。

先进先出置换算法(FIFO)(理想置换算法)

     先进先出置换算法是最简单的页面置换算法。这种算法的基本思想是:当需要淘汰一个页面时,总是选择驻留主存时间最长的页面进行淘汰,即先进入主存的页面先淘汰。其理由是:最早调入主存的页面不再被使用的可能性最大。 

最近最久未使用算法(LRU)

       这种算法的基本思想是:利用局部性原理,根据一个作业在执行过程中过去的页面访问历史来推测未来的行为。它认为过去一段时间里不曾被访问过的页面,在最近的将来可能也不会再被访问。所以,这种算法的实质是:当需要淘汰一个页面时,总是选择在最近一段时间内最久不用的页面予以淘汰。 

时钟置换算法(CLOCK)

       LRU算法的性能接近于OPT,但是实现起来比较困难,且开销大;FIFO算法实现简单,但性能差。所以操作系统的设计者尝试了很多算法,试图用比较小的开销接近LRU的性能,这类算法都是CLOCK算法的变体。

       简单的CLOCK算法是给每一帧关联一个附加位,称为使用位。当某一页首次装入主存时,该帧的使用位设置为1;当该页随后再被访问到时,它的使用位也被置为1。对于页替换算法,用于替换的候选帧集合看做一个循环缓冲区,并且有一个指针与之相关联。当某一页被替换时,该指针被设置成指向缓冲区中的下一帧。当需要替换一页时,操作系统扫描缓冲区,以查找使用位被置为0的一帧。每当遇到一个使用位为1的帧时,操作系统就将该位重新置为0;如果在这个过程开始时,缓冲区中所有帧的使用位均为0,则选择遇到的第一个帧替换;如果所有帧的使用位均为1,则指针在缓冲区中完整地循环一周,把所有使用位都置为0,并且停留在最初的位置上,替换该帧中的页。由于该算法循环地检查各页面的情况,故称为CLOCK算法,又称为最近未用(Not Recently Used, NRU)算法。

      CLOCK算法的性能比较接近LRU,而通过增加使用的位数目,可以使得CLOCK算法更加高效。在使用位的基础上再增加一个修改位,则得到改进型的CLOCK置换算法。这样,每一帧都处于以下四种情况之一:

最近未被访问,也未被修改(u=0, m=0)。

最近被访问,但未被修改(u=1, m=0)。

最近未被访问,但被修改(u=0, m=1)。

最近被访问,被修改(u=1, m=1)。


算法执行如下操作步骤:

从指针的当前位置开始,扫描帧缓冲区。在这次扫描过程中,对使用位不做任何修改。选择遇到的第一个帧(u=0, m=0)用于替换。

如果第1)步失败,则重新扫描,查找(u=0, m=1)的帧。选择遇到的第一个这样的帧用于替换。在这个扫描过程中,对每个跳过的帧,把它的使用位设置成0。

如果第2)步失败,指针将回到它的最初位置,并且集合中所有帧的使用位均为0。重复第1步,并且如果有必要,重复第2步。这样将可以找到供替换的帧。


代码实现

package com.cch.entity;

import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Scanner;

public class Page_replacement {
	private int n;// 内储页框
	private int m;// 访问次数
	private int F;// 没能直接找到的次数,(F/m)为缺页率
	private List<Integer> list = null;// 访问地址走向
	private Map<Integer, Integer> map = null;

	public Page_replacement() {
		F = 0;
		map = new HashMap<Integer, Integer>(); // 存储每一个内储页框所存的内容
		Scanner cin = new Scanner(new BufferedInputStream(System.in));
		System.out.println("请输入用户访问页地址走向");
		list = new ArrayList<Integer>();
		String s = cin.nextLine();
		String[] s1 = s.split(" ");
		m = s1.length;
		for (int i = 0; i < m; i++) {
			list.add(Integer.valueOf(s1[i]));
		}
		System.out.println("请输入内储叶框数量");
		n = cin.nextInt();
		menu();
		switch (cin.nextInt()) {
		case 1:
			OPT();
			break;
		case 2:
			FIFO();
			break;
		case 3:
			LRU();
			break;
		}
		cin.close();
	}

	public void menu() {
		System.out.println("**** 选择最佳置换算法请按1 **********");
		System.out.println("**** 选择先进先出置换算法请按2 *******");
		System.out.println("**** 选择最近最远未使用置换算法请按3 ***");
	}

	public void OPT() {// 最佳置换算法
		int j;
		for (int i = 0; i < m; i++) {
			int k = list.get(i);// 待处理元素
			if (!map.containsValue(k)) {
				F++;// 不能直接找到次数加1
				if (map.size() < n) {// 如果没有装满
					int temp = map.size();
					map.put(temp, k);
				} else {// 如果装满了
					int index = 0;// 把哪个位置的淘汰出去
					int max = 0;// 初始最长长度
					for (int t = 0; t < n; t++) {
						for (j = i + 1; j < m; j++) {// 看后面哪一个出现的最晚
							if (list.get(j) == map.get(t)) {// 第一次找到
								if (j - i > max) {
									index = t;// 更新值
									max = j - i;
								}
								break;
							}
						}
						if (j == m) { // 如果到最后都没有找到
							index = t;
							max = j - i;
						}
					}
					map.remove(index);
					map.put(index, k);// 修改表内元素
				}
			}
		}
		System.out.println("误码率为:" + F * 1.0 / m);
	}

	public void FIFO() {// 先进先出置换算法
		Queue<Integer> q = new LinkedList<Integer>();
		for (int i = 0; i < m; i++) {
			int k = list.get(i);// 待处理元素
			if (!map.containsValue(k)) {
				F++;// 不能直接找到次数加1
				if (map.size() < n) {// 如果没有装满
					int temp = map.size();
					map.put(temp, k);
					q.offer(temp);
				} else {
					int temp = q.poll();// 排除的元素位置
					map.remove(temp);
					map.put(temp, k);
					q.offer(temp);

				}
			}
		}
		System.out.println("误码率为:" + F * 1.0 / m);
	}

	public void LRU() {// 最近最远未使用置换算法
		List<Integer> linkedlist = new LinkedList<Integer>();
		int start = 0;
		for (int i = 0; i < m; i++) {
			int k = list.get(i);// 待处理元素
			if (!map.containsKey(k)) {
				F++;// 不能直接找到次数加1
				if (map.size() < n) {// 如果没有装满
					int temp = map.size();
					map.put(k, temp);
					linkedlist.add(k);// 添加位置
				} else {
					int temp = linkedlist.get(0);
					int c = map.get(temp);// 位置
					map.remove(temp);
					map.put(k, c);
					linkedlist.remove(0);
					linkedlist.add(k);
				}
			} else {// 如果包含这个值,把这个值拿走并在后面压入
				int d = linkedlist.indexOf(k);// 查找存在位置
				linkedlist.remove(d);
				linkedlist.add(k);
			}
		}
		System.out.println("误码率为:" + F * 1.0 / m);
	}

	public static void main(String args[]) {
		//7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
		Page_replacement p = new Page_replacement();
	}

}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cchoop

有用的话请杯肥宅水

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值