精华内容
下载资源
问答
  • 该压缩包是页面置换算法的综合设计,包括五种页面置换算法,optimal算法,Fifo算法,lru算法,Lfu算法,改进型Clock算法,而且拥有完整的页面操作,可以直接在IDEA中导入工程,编译即可通过。
  • 页面置换算法Java.zip

    2019-12-03 16:36:26
    模拟实现 OPT(最佳置换)、 FIFO 和 LRU 算法,并计算命中率,缺页率。。。。。。。。。。
  • 操作系统 页面置换算法 Java

    热门讨论 2009-07-08 10:57:03
    Java实现 操作系统 简单页面置换算法 FIFO OPT LRU算法,含有文档描述!该程序有简单的界面使这三个算法的运行结果清楚明了,而且是用户自己输入页面序列!
  • LRU页面置换算法Java实现

    千次阅读 2010-12-06 13:30:00
    这是用Java写的操作系统中页面置换算法中的LRU算法,希望大家提意见哈!!

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 页面置换算法java

    2021-02-26 14:18:35
    在一个请求分页系统中,分别采用最佳置换算法、先进先出置换算法、最近最久未使用置换算法(LRU)时,假如一个作业的页面走向为4、3、2、1、4、3、5、4、3、2、1、5,当分配给该作业的物理块数M分别为3和4时,试计算在...
  • java页面置换算法

    2012-05-10 11:09:30
    java页面置换算法opt lru fifo 页面置换算法
  • 页面置换算法.java

    2019-05-21 19:04:07
    一次操作系统算法的描述,有最佳置换算法,先进先出置换算法,和最近最久未使用和最少使用算法(这是一个),需要的人自行下载 代码类型:JAVA 附注释,每行方便理解,最难写的是opt算法。 算法要求:(1)给出页面...
  • java实现页面置换算法

    2020-08-18 15:57:05
    主要为大家详细介绍了java实现页面置换算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • LRU页面置换算法,使用Java语言编写,使用策略模式,可以方便的换成其他页面置换算法!相当好!
  • 页面置换算法

    2013-12-21 15:28:16
    页面置换算法 Java 实现操作系统
  • 操作系统os 页面置换算法java实现) Clock.java Lru.java Opt.java Fifo.java
  • java实现的页面置换算法

    千次阅读 2018-06-10 11:01:26
    java实现的页面置换算法,包括FIFO、LRU、Clock三种算法
    • 原理就不说了,直接上代码
    • FIFO
    import java.util.ArrayList;
    import java.util.List;
    
    import utils.ListUtils;
    
    
    /**
     * 
     * 
     * @author cnkeysky
     *
     */
    
    public class FIFO {
    
        public void run() {
            String[] inputStr = {"1", "2", "3", "4", "2", "1", "2", "3", "5", "2", "3", "7", "6"};
            // 内存块
            int memory = 3;
            List<String> list = new ArrayList<>();
            for(int i = 0; i < inputStr.length; i++){
                if(i == 0){
                    list.add(inputStr[i]);
                    System.out.println("第"+ i +"次访问:\t\t" + ListUtils.listToString(list));
                }else {
                    if(ListUtils.find(list, inputStr[i])){
                        System.out.println("第" + i + "次" + "访问:\t\t" + ListUtils.listToString(list));
                    }else{
                        if(list.size() < memory){
                            list.add(inputStr[i]);
                        }else{
                        list.remove(0);
                        list.add(inputStr[i]);
    
                        }
                        System.out.println("第" + i + "次" + "访问:\t\t" + ListUtils.listToString(list));
                    }
                }
            }
        }
    
    }
    
    • LRU
    import utils.ListUtils;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 最近最久未用置换算法
     * @author cnkeysky
     *
     */
    
    public class LRU {
    
        public static void main(String[] args) {
            String[] inputStr = {"6", "7", "6", "5", "9", "6", "8", "9", "7", "6", "9", "6"};
            // 内存块
            int memory = 3;
            List<String> list = new ArrayList<>();
            for(int i = 0; i < inputStr.length; i++){
                if(i == 0){
                    list.add(inputStr[i]);
                    System.out.println("第"+ i +"次访问:\t\t" + ListUtils.listToString(list));
                }else {
                    if(ListUtils.find(list, inputStr[i])){
                        // 存在字符串,则获取该下标
                        int index = ListUtils.findIndex(list, inputStr[i]);
                        // 下标不位于栈顶时,且list大小不为1时
                        if(!(list.get(list.size() - 1)).equals(inputStr[i]) && list.size() != 1) {
                            String str = list.get(index);
                            list.remove(index);
                            list.add(str);
                        }
                        System.out.println("第" + i + "次" + "访问:\t\t" + ListUtils.listToString(list));
                    }else{
                        if(list.size()>= memory) {
                            list.remove(0);
                            list.add(inputStr[i]);
                            System.out.println("第" + i + "次" + "访问:\t\t" + ListUtils.listToString(list));
                        }else {
                            list.add(inputStr[i]);
                            System.out.println("第" + i + "次" + "访问:\t\t" + ListUtils.listToString(list));
                        }
                    }
                }
            }
        }
    }
    
    • Clock
    import java.util.ArrayList;
    import java.util.List;
    
    import utils.ListUtils;
    
    /**
     * 
     * 
     * @author cnkeysky
     *
     */
    public class Clock {
    
        public static void main(String[] args) {
            String[] inputStr = {"6", "7", "6", "5", "9", "6", "8", "9", "7", "6", "9", "6"};
            List<String> list = new ArrayList<>();
            // 内存块
            int memory = 3;
            // 缺页次数
            int count = 0;
            String[] clock = new String[memory];
            int indexNext = 0;
            int index = 0;
            // 初始化时钟
            for(int i = 0; i < memory; i++) {
                clock[i] = "0";
            }
            for(int i = 0; i < inputStr.length; i++) {
                int indexPre = 0;
                if (i == 0) {
                    list.add(inputStr[i]);
                    clock[indexNext] = "1";
                    indexNext++;
                    System.out.println("第"+ i +"次访问:\t\t" + ListUtils.listToString(list));
                }else {
    
                    if(ListUtils.find(list, inputStr[i])) {
                        indexPre = ListUtils.findIndex(list, inputStr[i]);
                        if(clock[indexPre].equals("0")) {
                            clock[indexPre] = "1";
                        }
                        count++;
                        System.out.println("第"+ i +"次访问:\t\t" + ListUtils.listToString(list));
                    }else {
                        if(list.size() < memory) {
                            list.add(inputStr[i]);
                            clock[indexNext] = "1";
                            indexNext++;
                            System.out.println("第"+ i +"次访问:\t\t" + ListUtils.listToString(list));
                        }else {
                            index = ListUtils.findZero(indexNext, clock, memory);
                            list.remove(index);
                            list.add(index, inputStr[i]);
                            clock[index] = "1";
                            indexNext = index + 1;
                            System.out.println("第"+ i +"次访问:\t\t" + ListUtils.listToString(list));
                        }
                    }
                }
                if(indexNext > memory - 1) {
                    indexNext = Math.abs(memory - indexNext);
                }
            }
            System.out.println("缺页次数:" + (inputStr.length-count));
        }
    
    }
    
    • 工具类ListUtils
    import java.util.List;
    
    public class ListUtils {
    
        public ListUtils() {
    
        }
    
        /**
         * 输出
         * @param list 将List转为数组并输出, out: 2, 3, 4 
         * @return
         */
        public static String listToString(List list){
    
            StringBuffer content = new StringBuffer();
            for(int i = 0; i < list.size(); i++){
                content.append(list.get(i));
                if(i < list.size() - 1){
                    content.append(",");
                }
            }
            return content.toString();
        }
    
        /**
         * 在list中查找是否有str
         * @param list
         * @param str
         * @return
         */
        public static boolean find(List<String> list, String str){
            boolean flag = false;
            for(String lis : list){
                if(lis.equals(str)){
                    flag = true;
                }
            }
            return flag;
        }
    
        /**
         * 在List中查找是否有String,如果有返回下标, 否则返回 -1
         * @param list
         * @param str
         * @return
         */
        public static int findIndex(List<String> list, String str) {
    
            int index = 0;
            for(String lis : list) {
                if(lis.equals(str)) {
                    return index;
                }
                index++;
            }
            return -1;
        }
    
        public static boolean clockJudge(String[] clock, int index) {
            if(clock[index].equals("0")) {
                return true;
            }
            return false;
        }
        /**
         * 
         * @param index 下标
         * @param clock 时钟
         * @param range 当前使用内存块
         * @return
         */
        public static int findZero(int index, String[] clock, int range) {
    
            while(true) {
    
                if(clock[index].equals("0")) {
                    break;
                }else {
                    clock[index] = "0";
                    index++;
                    if(index > range-1) {
                        index = Math.abs(range - index);
                    }
                }
            }
            return index;
        }
    
        /**
         * 在数组中查找是否存在该字符串
         * @param obj
         * @param str
         * @return
         */
        public static boolean strJudge(Object[] obj, String str) {
            boolean flag = false;
            if(obj == null) {
                return flag;
            }
            for(int i = 0; i < obj.length; i++) {
                if(str.equals(obj[i])) {
                    flag = true;
                    break;
                }
            }
            return flag;
        }
    
        /**
         * 获取二维数组中同一列的行的长度
         * @param str 数据
         * @param length 二维数组的列
         * @param memory 内存块
         * @return
         * 
         */
    
        public static int findNull(Object[][] str, int length, int memory) {
    
            int index = 0;
            if(str == null) {
                return -1;
            }
            for(int i = 0; i < memory; i++) {
                if(str[i][length] != null) {
                    index = i;
                }
            }
            return index;
        }
    }
    
    展开全文
  • 操作系统页面置换算法-java界面化实现,并将整个过程动态地演示出来
  • 页面置换算法 操作系统作业 java模拟页面置换,图形界面 调试完全正确! 请放心下载!
  • 页面置换FIFO算法java

    2013-06-17 21:25:29
    页面置换FIFO算法java,仅供学习和参考!
  • 页面置换算法.doc

    2020-03-23 22:48:13
    深入掌握内存调度算法的概念原理和实现方法,编写程序实现: (1) 先进先出页面置换算法(FIFO) ...操作系统页面置换算法课程设计,完整的课设结构,有详细的流程图、Java源码,还有调试截图!!!
  • 页面置换算法, 三种算法编写的程序,支持随机数输入,也支持示例输入,自带PPT例子验证结果
  • 页面置换算法的模拟程序。用随机数方法产生页面走向,根据页面走向,分别采用FIFO和LRU算法进行页面置换,统计缺页率。
  • 操作系统课程设计之用java实现页面置换算法的模拟实现
  • 一:页面置换算法简介 在进程运行过程中,若其所要访问的页面不在内存而需把它们调入内存,但内存已无 空闲空间时,为了保证该进程能正常运行,系统必须从内存中调出一页程序或数据送磁盘 的对换区中。但应将哪个...

    一:页面置换算法简介

    在进程运行过程中,若其所要访问的页面不在内存而需把它们调入内存,但内存已无

    空闲空间时,为了保证该进程能正常运行,系统必须从内存中调出一页程序或数据送磁盘

    的对换区中。但应将哪个页面调出,须根据一定的算法来确定。通常,把选择换出页面的

    算法称为页面置换算法(Page-Replacement Algorithms)。置换算法的好坏,将直接影响到系统

    的性能。

    一个好的页面置换算法,应具有较低的页面更换频率。从理论上讲,应将那些以后不

    再会访问的页面换出,或把那些在较长时间内不会再访问的页面调出。目前存在着许多种

    置换算法,它们都试图更接近于理论上的目标。

    二:常用到的页面置换算法

    1、最佳置换算法(Optimal)) (该算法主要是用来度量其他算法)

    最佳置换算法是由Belady于1966年提出的一种理论上的算法。其所选择的被淘汰页面,

    将是以后永不使用的,或许是在最长(未来)时间内不再被访问的页面。采用最佳置换算法,

    通常可保证获得最低的缺页率。但由于人们目前还无法预知一个进程在内存的若干个页面

    中,哪一个页面是未来最长时间内不再被访问的,因而该算法是无法实现的,但可以利用

    该算法去评价其它算法。

    2、先进先出置换算法(FIFO)

    这是最早出现的置换算法。该算法总是淘汰最先进入内存的页面,即选择在内存中驻

    留时间最久的页面予以淘汰。先进先出这个特性会想到的是队列,算法思想就是先写入到同一个队列

    里面,然后设置一个指针(替换指针),让它指向最老的页面。

    下面就是Java代码模拟FIFO置换算法:

    使用队列记录对应内存空间位置以及页面数据:

    PrintUtils这个工具类主要输出的是过程数据
    
    /** * 没有用计数方法,使用的队列记录对应位置 * @param numbers * @param memorySize */public static void FIFOPages(int[] numbers, int memorySize) {    // 模拟内存空间    int[] pages = new int[memorySize];    Arrays.fill(pages, -1);    String[] ways = new String[memorySize];    Queue<Page> queue = new LinkedList<>();    // 缺页次数    int sum = 0;    // 缺页记录    boolean[] sums = new boolean[numbers.length];    for (int i = 0; i < numbers.length; i++) {        int number = numbers[i];        long count = queue.stream().filter(page -> page.getData().equals(number)).count();        if (count <= 0) {            int size = queue.size();            if (size >= memorySize) {                size = queue.poll().getMemoryPosition();            }            queue.add(new Page(number, size));            pages[size] = numbers[i];            sum++;            sums[i] = true;        }        PrintUtils.setWays(ways, pages);    }    PrintUtils.printResult(numbers, sums, memorySize, sum, ways);}@Setter@Getter@AllArgsConstructor@ToStringpublic class Page {    private Integer data;    private Integer memoryPosition;}

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

    LRU 置换算法虽然是一种比较好的算法,但要求系统有较多的支持硬件。为了了解一

    个进程在内存中的各个页面各有多少时间未被进程访问,以及如何快速地知道哪一页是最

    近最久未使用的页面

    模拟代码:

    public static void URLPage(int[] numbers, int memorySize) {    // 模拟内存空间    int[] pages = new int[memorySize];    Arrays.fill(pages, -1);    // 页面计数    int[] counts = new int[memorySize];    String[] ways = new String[memorySize];    // 缺页次数    int sum = 0;    // 缺页记录    boolean[] sums = new boolean[numbers.length];    for (int i = 0; i < numbers.length; i++) {        if (!havePage(pages, numbers[i], counts)) {            int maxCount = getMaxCount(counts);            pages[maxCount] = numbers[i];            counts[maxCount] = 1;            sum++;            sums[i] = true;        }        PrintUtils.setWays(ways, pages);    }    PrintUtils.printResult(numbers, sums, memorySize, sum, ways);}
    
    /** * 获取最先进入的数据,如果计数最大说明是最先进来的,并且每一个对应计数+1 * * @param counts * @return */private static int getMaxCount(int[] counts) {    int index = 0;    int max = 0;    for (int i = 0; i < counts.length; i++) {        if (counts[i] == -1) {            index = i;            break;        }        if (counts[i] > max) {            max = counts[i];            index = i;        }        counts[i]++;    }    return index;}
    /** * 查看当前内存块中是否有当前页,如果没有就是要置换掉最先进入的页,并且计数+1,有就计数变为1,因为已经被访问了 * * @param pages * @param page * @param counts * @return */private static boolean havePage(int[] pages, int page, int[] counts) {    boolean isHave = false;    for (int i = 0; i < pages.length; i++) {        counts[i]++;        if (pages[i] == page) {            isHave = true;            counts[i] = 1;        }    }    return isHave;}

    4、Clock置换算法

      (1)简单的Clock置换算法

    当采用简单 Clock 算法时,只需为每页设置一位访问位,再将内存中的所有页面都通过

    链接指针链接成一个循环队列。当某页被访问时,其访问位被置 1。置换算法在选择一页淘

    汰时,只需检查页的访问位。如果是 0,就选择该页换出;若为 1,则重新将它置 0,暂不

    换出,而给该页第二次驻留内存的机会,再按照 FIFO 算法检查下一个页面。当检查到队列

    中的最后一个页面时,若其访问位仍为 1,则再返回到队首去检查第一个页面。图 4-31 示

    出了该算法的流程和示例。由于该算法是循环地检查各页面的使用情况,故称为 Clock 算法。

    但因该算法只有一位访问位,只能用它表示该页是否已经使用过,而置换时是将未使用过

    的页面换出去,故又把该算法称为最近未用算法 NRU(Not Recently Used)

    模拟代码如下:

    public static void ClocksPage(int[] numbers, int memorySize) {    // 模拟内存空间    int[] pages = new int[memorySize];    Arrays.fill(pages, -1);    // 页面计数    int[] counts = new int[memorySize];    int index = 0;    String[] ways = new String[memorySize];    // 缺页次数    int sum = 0;    // 缺页记录    boolean[] sums = new boolean[numbers.length];    for (int i = 0; i < numbers.length; i++) {        int number = numbers[i];        if (havePage(pages, number, counts)) {            index = (index + 1) % memorySize;        } else {            while (true) {                int indexs = (index + 1) % memorySize;                if (pages[index] == -1 || (counts[index] == 0 && pages[index] != number)) {                    pages[index] = number;                    counts[index] = 1;                    sum++;                    sums[i] = true;                    index = indexs;                    break;                }                if (pages[index] != number) {                    counts[index] = 0;                    index = indexs;                }            }        }        PrintUtils.setWays(ways, pages);    }    PrintUtils.printResult(numbers, sums, memorySize, sum, ways);}
    /** * 查看当前内存块中是否有当前页 * * @param pages * @param page * @param counts * @return */private static boolean havePage(int[] pages, int page, int[] counts) {    boolean isHave = false;    for (int i = 0; i < pages.length; i++) {        if (pages[i] == page) {            isHave = true;            counts[i] = 1;        }    }    return isHave;}

       (2)改进型Clock置换算法

    简单时钟只有一个标记位,但是改进型是多加了一个标记位,简单时钟最多遍历2遍,改进型的最多比遍历4遍。

    算法书里面是这样描述的:

    假设 search标识访问标记位,update表示修改标记位,下面就有这样的一个规则

    •  

    • 1 类( search  =0, update  =0):表示该页最近既未被访问,又未被修改,是最佳淘汰页。

    • 2 类( search  =0, update  =1):表示该页最近未被访问,但已被修改,并不是很好的淘汰页。

    • 3 类( search  =1, update  =0):表示该页最近已被访问,但未被修改,该页有可能再被访问。

    • 4 类( search  =1, update  =1):表示该页最近已被访问且被修改,该页可能再被访问。 

    (1) 从指针所指示的当前位置开始,扫描循环队列,寻找 search  =0 且  update  =0 的第一类页面,

    将所遇到的第一个页面作为所选中的淘汰页。在第一次扫描期间不改变访问位  search  。

    (2) 如果第一步失败,即查找一周后未遇到第一类页面,则开始第二轮扫描,寻找  search  =0

    且  update  =1 的第二类页面,将所遇到的第一个这类页面作为淘汰页。在第二轮扫描期间,将所

    有扫描过的页面的访问位都置 0。

    (3) 如果第二步也失败,亦即未找到第二类页面,则将指针返回到开始的位置,并将所

    有的访问位复 0。然后重复第一步,如果仍失败,必要时再重复第二步,此时就一定能找到

    被淘汰的页。

    该算法与简单 Clock 算法比较,可减少磁盘的 I/O 操作次数。但为了找到一个可置换的

    页,可能须经过几轮扫描。换言之,实现该算法本身的开销将有所增加。

    模拟代码如下:

    public static void ClocksPage(int[] numbers, int memorySize) {    // 模拟内存空间    int[] pages = new int[memorySize];    Arrays.fill(pages, -1);    // 记录访问状态    int[] search = new int[memorySize];    // 记录修改状态    int[] update = new int[memorySize];    int index = 0;    String[] ways = new String[memorySize];    // 缺页次数    int sum = 0;    // 缺页记录    boolean[] sums = new boolean[numbers.length];    for (int i = 0; i < numbers.length; i++) {        int number = numbers[i];        boolean isHave = false;        for (int page : pages) {            if (page == number) {                isHave = true;                break;            }        }        if (!isHave) {            sums[i] = true;            sum++;            int count = 0;            int start = index;            while (true) {                int j = (index + 1) % memorySize;                if (j == start) {                    ++count;                }
                    if (count == 0 || count == 2) {                    if (search[index] == 0 && update[index] == 0) {                        pages[index] = number;                        search[index] = 1;                        update[index] = 1;                        index = j;                        break;                    }                } else {                    if (search[index] == 0 && update[index] == 1) {                        pages[index] = number;                        search[index] = 1;                        update[index] = 1;                        index = j;                        break;                    }                }                if (count != 0) {                    search[index] = 0;                }                index = j;            }        }        PrintUtils.setWays(ways, pages);    }    PrintUtils.printResult(numbers, sums, memorySize, sum, ways);}

     

    5、最少使用置换算法(LFU:Least Frequently Used)

    在采用最少使用置换算法时,应为在内存中的每个页面设置一个移位寄存器,用来记

    录该页面被访问的频率。该置换算法选择在最近时期使用最少的页面作为淘汰页。由于存

    储器具有较高的访问速度,例如 100 ns,在 1 ms 时间内可能对某页面连续访问成千上万次,

    因此,通常不能直接利用计数器来记录某页被访问的次数,而是采用移位寄存器方式。每

    次访问某页时,便将该移位寄存器的最高位置 1,再每隔一定时间(例如 100 ms)右移一次。

    这样,在最近一段时间使用最少的页面将是∑Ri 最小的页。

    LFU 置换算法的页面访问图与 LRU 置换算法的访问图完全相同;或者说,利用这样一

    套硬件既可实现 LRU 算法,又可实现 LFU 算法。应该指出,LFU 算法并不能真正反映出

    页面的使用情况,因为在每一时间间隔内,只是用寄存器的一位来记录页的使用情况,因

    此,访问一次和访问 10 000 次是等效的。

    6、页面缓冲算法(PBA:Page Buffering Algorithm)

    虽然 LRU 和 Clock 置换算法都比 FIFO 算法好,但它们都需要一定的硬件支持,并需

    付出较多的开销,而且,置换一个已修改的页比置换未修改页的开销要大。而页面缓冲算

    法(PBA)则既可改善分页系统的性能,又可采用一种较简单的置换策略。VAX/VMS 操作系

    统便是使用页面缓冲算法。它采用了前述的可变分配和局部置换方式,置换算法采用的是

    FIFO。该算法规定将一个被淘汰的页放入两个链表中的一个,即如果页面未被修改,就将

    它直接放入空闲链表中;否则,便放入已修改页面的链表中。须注意的是,这时页面在内

    存中并不做物理上的移动,而只是将页表中的表项移到上述两个链表之一中。

    空闲页面链表,实际上是一个空闲物理块链表,其中的每个物理块都是空闲的,因此,

    可在其中装入程序或数据。当需要读入一个页面时,便可利用空闲物理块链表中的第一个

    物理块来装入该页。当有一个未被修改的页要换出时,实际上并不将它换出内存,而是把

    该未被修改的页所在的物理块挂在自由页链表的末尾。类似地,在置换一个已修改的页面

    时,也将其所在的物理块挂在修改页面链表的末尾。利用这种方式可使已被修改的页面和

    未被修改的页面都仍然保留在内存中。当该进程以后再次访问这些页面时,只需花费较小

    的开销,使这些页面又返回到该进程的驻留集中。当被修改的页面数目达到一定值时,例

    如 64 个页面,再将它们一起写回到磁盘上,从而显著地减少了磁盘 I/O 的操作次数。一个

    较简单的页面缓冲算法已在 MACH 操作系统中实现了,只是它没有区分已修改页面和未修

    改页面。

    参考书籍:《计算机操作系统第三版》汤小丹等著

    完整代码地址:

    https://gitee.com/yh128/SpringDemoProject/tree/master/blog-code

     

     

                                                文章同时会更新到公众号,觉得对你有帮助或者有用的可以关注一下哦 

     

    展开全文
  • 模拟操作系统页面置换的过程,具体实现了四种经典算法,即OPT、LRU、FIFO、CLOCK,并且利用Java中的图形库制作了一个好看的图形化界面
  • 大学课程操作系统会有很多实验,LRU页面置换也是其中的一部分,希望能够参考,此LRU内存最大块为五块,可以修改成最大块为输入限制。
  • 《操作系统之Java实现模拟页面置换算法

    千次阅读 多人点赞 2018-05-13 18:08:58
    一. 页面置换三大算法简介 1. FIFO(先进先出置换算法) 2. LRU(最近最久未使用置换算法) 3. OPT(最佳置换算法) 二....1. 基于随机数产生该程序...5. 执行页面置换算法的模拟过程 三. 实现关键思路 1. FIFO 2....

    一. 页面置换三大算法简介

    1. FIFO(先进先出置换算法)

    选择最先进入内存的页面进行置换,即在内存中驻留时间最长的页面要被淘汰。

    该算法的核心思想是:最早调入内存的页,其不再被使用的可能性比刚调入内存的可能性大。

    1

    2. LRU(最近最久未使用置换算法)

    选择最近一段时间内最长时间没有被访问过的页面进行置换。

    该算法根据数据的历史访问记录来进行淘汰数据,其核心思想是:如果数据最近被访问过,那么将来被访问的几率也更高。

    2

    3. OPT(最佳置换算法)

    选择永不使用或者长时间内不再被访问的页面进行置换。这是一种理想化的算法,具有最好的性能,但是实际上却难以实现。原因是程序在实际执行过程中无法预测到随后要被访问到的页面,它们都是随机到达的。

    我们的模拟过程是基于一开始的页面访问顺序就已经确定好了,模拟过程才得以实现。

    3


    二. 实现具体流程

    设该程序对应的指令的总条数为320

    1. 基于随机数产生该程序依次执行的指令的地址序列

    指令地址范围为[0, 319],指令的地址按下述原则生成:

    A:50%的指令是顺序执行的

    B:25%的指令是均匀分布在前地址部分

    C:25%的指令是均匀分布在后地址部分

    具体的实施方法是:

    A:在[0,319]的指令地址之间随机选取一起点m

    B:顺序执行一条指令,即执行地址为m+1 的指令

    C:在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m’

    D:顺序执行一条指令,其地址为m’+1

    E:在后地址[m’+2,319]中随机选取一条指令并执行

    F:重复步骤A-E,直到320 次指令


    2. 将指令地址序列根据页面大小转换为页号序列

    页面大小的取值范围为 1K,2K,4K,8K,16K。

    设页面大小为1K,用户内存容量4页到32页,用户虚存容量为32K。
    在用户虚存中,按每K(即每页)存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为:

    第 0 条-第 9 条指令为第 0 页(对应虚存地址为[0,9]);

    第 10 条-第 19 条指令为第 1 页(对应虚存地址为[10,19]);

    ………………………………

    第 310 条-第 319 条指令为第 31 页(对应虚存地址为[310,319]);

    按以上方式,用户指令可组成 32 页。


    3. 合并相邻页号

    在生成的页号序列中,对于相邻相同的页号,合并为一个页号。


    4. 指定分配给该程序的内存块数

    分配给该程序的内存块数取值范围为1块,2块,直到程序使用的页面数。


    5. 执行页面置换算法的模拟过程

    分别采用 FIFO、LRU和OPT 算法对页号序列进行调度,计算出对应的缺页中断率。
    并打印出页面大小、分配给程序的内存块数、算法名、对应的缺页中断率。



    三. 实现关键思路

    1. FIFO

    设置一个指针始终指向最早进入内存块序列的内存块,并保持动态更新。


    2. LRU

    可以使用双向链表加上哈希表来实现:

    1. 当访问到新的(不位于当前内存块序列中)内存块时(即缺页),将其插入到链表首部;
    2. 如果当前内存块序列中某个内存块被命中(被使用到),则将其移到链表首部;
    3. 为链表设置一个容量(设为分配给该程序的内存块数),当超出这个容量时,丢弃链表尾部的内存块。
    4. 剩下的哈希表用来查找内存块。

    实际上,Java已经为我们提供这种结构了!——-LinkedHashMap

    我们主要将其中的accessOrder设置为true,保证了LinkedHashMap底层实现的双向链表是按照访问的先后顺序排序。


    3. OPT

    主要工作是:在当前访问位置,记录当前的内存块序列中的所有内存块在后续未访问的页号序列中的位置(即下标)。

    可以设置一个指针记录上述结果中的最大下标,该下标对应的内存块即为缺页时要被置换的内存块。



    四. 实现代码

    1. 考虑到程序的指令序列会比较庞大,采用GUI界面显示不太友好,故不采用GUI界面实现模拟过程,而采用控制台方式实现。
    2. 考虑到分配的内存块数可能会比较大,将内存块序列采用横向显示,且一开始按从左到右的顺序分配内存块。


    Code:

    pageReplacementSimulation.java

    package com.wuchangi;
    
    import java.util.*;
    
    public class PageReplacement
    {
        //页面大小,每个页面可包含instructionsNumPerPage条指令
        public static int instructionsNumPerPage;
    
        //存放该程序依次执行的指令的有序地址序列
        public static int[] instructionsSequence = null;
    
        //存放将有序指令地址序列转换成(经过合并相邻页号)的有序页号序列
        public static int[] pagesSequence = null;
    
        //指定分配给该程序的内存块数
        public static int memoryBlocksNum;
    
    
        public static void main(String[] args)
        {
    
            int count = 1;
            Scanner scan = new Scanner(System.in);
    
            System.out.println("\t\t**********欢迎使用页面置换模拟系统!**********\n");
    
            while (true)
            {
                System.out.println("*****第 " + count + " 个程序的页面置换模拟过程*****\n");
                System.out.println("请输入程序包含的指令条数:(只支持5的倍数, 退出系统请输入-1)");
    
                int inputValue = scan.nextInt();
    
                if(inputValue == -1) break;
    
                int instructionsNum = inputValue;
    
                instructionsSequence = generateInstructionsSequence(instructionsNum);
                System.out.println("系统随机生成的指令地址序列如下:");
                showInstructionsSequence(instructionsSequence);
                System.out.println();
    
                System.out.println("请输入页面大小(1,2,4,8,16 分别表示 1k,2k,4k,8k,16k):");
    
                //每1k存放10条指令
                instructionsNumPerPage = scan.nextInt() * 10;
                pagesSequence = convertToPagesSequence(instructionsSequence, instructionsNumPerPage);
                System.out.println("该指令地址序列对应的页号序列(已经过相邻页号合并)如下:");
                showPagesSequence(pagesSequence);
                System.out.println();
                System.out.println("实际总共使用到的页号个数为:" + pagesSequence.length);
                System.out.println();
    
                System.out.println("请输入分配给该程序的内存块数:(1~" + pagesSequence.length + ")");
                memoryBlocksNum = scan.nextInt();
    
                while(true)
                {
                    System.out.println("请输入需要模拟的页面置换算法标号:(1:FIFO, 2:LRU, 3:OPT, 退出该程序的页面置换模拟过程请输入-1)");
                    int flag = scan.nextInt();
    
                    if(flag == -1) break;
    
                    switch (flag)
                    {
                        case 1:
                            FIFO(pagesSequence, memoryBlocksNum);
                            break;
                        case 2:
                            LRU(pagesSequence, memoryBlocksNum);
                            break;
                        case 3:
                            OPT(pagesSequence, memoryBlocksNum);
                            break;
                        default:
                            System.out.println("您的输入有误!");
                    }
    
                    System.out.println();
                }
    
                System.out.println("\n\n");
    
                count++;
            }
    
            System.out.println("\n~~~~~~~~~~您已成功退出系统!~~~~~~~~~~");
    
        }
    
        //instructionsNum为5的倍数
        public static int[] generateInstructionsSequence(int instructionsNum)
        {
            int[] instructionsSequence = new int[instructionsNum];
    
            int count = 0;
    
            while (count < instructionsNum)
            {
                int randomAddress1 = 0 + (int) (Math.random() * (((instructionsNum - 1) - 0) + 1));
                instructionsSequence[count] = randomAddress1;
                randomAddress1++;
                instructionsSequence[++count] = randomAddress1;
    
                int randomAddress2 = 0 + (int) (Math.random() * ((randomAddress1 - 0) + 1));
                instructionsSequence[++count] = randomAddress2;
                randomAddress2++;
                instructionsSequence[++count] = randomAddress2;
    
                int randomAddress3 = (randomAddress2 + 1) + (int) (Math.random() * (((instructionsNum - 1) - (randomAddress2 + 1)) + 1));
                instructionsSequence[++count] = randomAddress3;
    
                count++;
            }
    
            return instructionsSequence;
        }
    
        public static void showInstructionsSequence(int[] instructionsSequence)
        {
            for (int i = 0; i < instructionsSequence.length; i++)
            {
                System.out.printf("%5s", instructionsSequence[i]);
    
                if ((i + 1) % 20 == 0)
                {
                    System.out.println();
                }
            }
    
            System.out.println();
        }
    
    
        public static int[] convertToPagesSequence(int[] instructionsSequence, int instructionsNumPerPage)
        {
            ArrayList<Integer> pagesList = new ArrayList<Integer>();
    
            int temp = -1;
            //页号
            int pageIndex;
    
            for (int i = 0; i < instructionsSequence.length; i++)
            {
                pageIndex = instructionsSequence[i] / instructionsNumPerPage;
    
                //将相邻的页号合并
                if (pageIndex != temp)
                {
                    pagesList.add(pageIndex);
                    temp = pageIndex;
                }
            }
    
            //有序页号序列经合并之后长度最长不超过指令的有序地址序列长度
            int[] pagesSequence = new int[pagesList.size()];
    
            for (int i = 0; i < pagesList.size(); i++)
            {
                pagesSequence[i] = pagesList.get(i);
            }
    
            return pagesSequence;
        }
    
    
        public static void showPagesSequence(int[] pagesSequence)
        {
            for (int i = 0; i < pagesSequence.length; i++)
            {
                System.out.printf("%5s", pagesSequence[i]);
    
                if ((i + 1) % 20 == 0)
                {
                    System.out.println();
                }
            }
    
            System.out.println();
        }
    
    
        public static void FIFO(int[] pagesSequence, int memoryBlocksNum)
        {
            //执行页号序列期间内存块的状态
            int[][] memoryBlocksState = new int[pagesSequence.length][memoryBlocksNum];
    
            //该指针指向将要被置换的内存块的位置(下标位置)
            int curPosition = 0;
    
            //执行每个页号时内存块序列的状态
            int[] tempState = new int[memoryBlocksNum];
    
            //记录缺页情况, 1表示缺页,0表示不缺页
            int[] isLackOfPage = new int[pagesSequence.length];
            Arrays.fill(isLackOfPage, 0, pagesSequence.length, 0);
    
            //缺页次数
            int lackTimes = 0;
    
            //开始时,内存块状态都为空闲(-1表示)
            Arrays.fill(tempState, 0, memoryBlocksNum, -1);
    
            for (int i = 0; i < pagesSequence.length; i++)
            {
                //如果缺页
                if (findKey(tempState, 0, memoryBlocksNum - 1, pagesSequence[i]) == -1)
                {
                    isLackOfPage[i] = 1;
                    lackTimes++;
                    tempState[curPosition] = pagesSequence[i];
    
                    //指针向右移动超过memoryBlocksNum时,重置其指向开始的内存块位置0
                    if (curPosition + 1 > memoryBlocksNum - 1)
                    {
                        curPosition = 0;
                    }
                    else
                    {
                        curPosition++;
                    }
                }
    
                //保存当前内存块序列的状态
                System.arraycopy(tempState, 0, memoryBlocksState[i], 0, memoryBlocksNum);
    
            }
    
            showMemoryBlocksState(memoryBlocksState, pagesSequence, memoryBlocksNum, isLackOfPage, lackTimes);
        }
    
        public static void LRU(int[] pagesSequence, int memoryBlocksNum)
        {
            //维护一个最近使用的内存块集合
            LRULinkedHashMap<String, Integer> recentVisitedBlocks = new LRULinkedHashMap<String, Integer>(memoryBlocksNum);
    
            //执行页号序列期间内存块的状态
            int[][] memoryBlocksState = new int[pagesSequence.length][memoryBlocksNum];
    
            //该指针指向将要被置换的内存块的位置(下标位置)
            int curPosition = 0;
    
            //执行每个页号时内存块序列的状态
            int[] tempState = new int[memoryBlocksNum];
    
            //记录缺页情况, 1表示缺页,0表示不缺页
            int[] isLackOfPage = new int[pagesSequence.length];
            Arrays.fill(isLackOfPage, 0, pagesSequence.length, 0);
    
            //缺页次数
            int lackTimes = 0;
    
            //开始时,内存块状态都为空闲(-1表示)
            Arrays.fill(tempState, 0, memoryBlocksNum, -1);
    
            for (int i = 0; i < pagesSequence.length; i++)
            {
                //如果缺页
                if(findKey(tempState, 0, memoryBlocksNum - 1, pagesSequence[i]) == -1)
                {
                    isLackOfPage[i] = 1;
                    lackTimes++;
    
                    //如果内存块还有剩余
                    if(tempState[memoryBlocksNum - 1] == -1)
                    {
                        tempState[curPosition] = pagesSequence[i];
                        recentVisitedBlocks.put(String.valueOf(pagesSequence[i]), pagesSequence[i]);
                        curPosition++;
                    }
                    //如果内存块都已被使用
                    else
                    {
                        //找到当前内存块序列中最近最少使用的内存块,并将其置换
                        curPosition = findKey(tempState, 0, memoryBlocksNum - 1, recentVisitedBlocks.getHead());
                        tempState[curPosition] = pagesSequence[i];
                        recentVisitedBlocks.put(String.valueOf(pagesSequence[i]), pagesSequence[i]);
                    }
                }
                //如果不缺页
                else
                {
                    //将这里被使用的pageSequence[i]在最近使用的内存块集合中的原先位置调整到最近被访问的位置
                    recentVisitedBlocks.get(String.valueOf(pagesSequence[i]));
                }
    
                //保存当前内存块序列的状态
                System.arraycopy(tempState, 0, memoryBlocksState[i], 0, memoryBlocksNum);
            }
    
            showMemoryBlocksState(memoryBlocksState, pagesSequence, memoryBlocksNum, isLackOfPage, lackTimes);
        }
    
        public static void OPT(int[] pagesSequence, int memoryBlocksNum)
        {
            //执行页号序列期间内存块的状态
            int[][] memoryBlocksState = new int[pagesSequence.length][memoryBlocksNum];
    
            //该指针指向将要被置换的内存块的位置(下标位置)
            int curPosition = 0;
    
            //执行每个页号时内存块序列的状态
            int[] tempState = new int[memoryBlocksNum];
    
            //记录缺页情况, 1表示缺页,0表示不缺页
            int[] isLackOfPage = new int[pagesSequence.length];
            Arrays.fill(isLackOfPage, 0, pagesSequence.length, 0);
    
            //缺页次数
            int lackTimes = 0;
    
            //开始时,内存块状态都为空闲(-1表示)
            Arrays.fill(tempState, 0, memoryBlocksNum, -1);
    
            for (int i = 0; i < pagesSequence.length; i++)
            {
                //如果缺页
                if(findKey(tempState, 0, memoryBlocksNum - 1, pagesSequence[i]) == -1)
                {
                    isLackOfPage[i] = 1;
                    lackTimes++;
    
                    //如果内存块还有剩余
                    if(tempState[memoryBlocksNum - 1] == -1)
                    {
                        tempState[curPosition] = pagesSequence[i];
                        curPosition++;
                    }
                    //如果内存块都已被使用
                    else
                    {
                        int maxLoc = 0;
    
                        for(int j = 0; j < memoryBlocksNum; j++)
                        {
                            //找出当前内存块序列中的内存块tempState[j]在将来会被访问到的(第一个)位置
                            int loc = findKey(pagesSequence, i + 1, pagesSequence.length - 1, tempState[j]);
    
                            //如果将来该内存块都不再被使用了
                            if (loc == -1)
                            {
                                curPosition = j;
                                break;
                            }
                            //找出当前内存块序列中的所有内存块在将来会被访问到的最远位置,设为maxLoc
                            else
                            {
                                if(maxLoc < loc)
                                {
                                    maxLoc = loc;
                                    curPosition = j;
                                }
                            }
                        }
    
                        tempState[curPosition] = pagesSequence[i];
                    }
                }
    
                //保存当前内存块序列的状态
                System.arraycopy(tempState, 0, memoryBlocksState[i], 0, memoryBlocksNum);
            }
    
            showMemoryBlocksState(memoryBlocksState, pagesSequence, memoryBlocksNum, isLackOfPage, lackTimes);
    
        }
    
    
        //返回key在arr中第一次出现的位置,start和end为数组下标, 找不到则返回-1
        public static int findKey(int[] arr, int start, int end, int key)
        {
            for (int i = start; i <= end; i++)
            {
                if (arr[i] == key)
                {
                    return i;
                }
            }
    
            return -1;
        }
    
    
        public static void showMemoryBlocksState(int[][] memoryBlocksState, int[] pagesSequence, int memoryBlocksNum, int[] isLackofPage, int lackTimes)
        {
            String[] pagesDescription = {"不缺页", "缺页"};
    
            int pagesSequenceLength = pagesSequence.length;
    
            for (int i = 0; i < pagesSequenceLength; i++)
            {
                System.out.println("当前访问页号:" + pagesSequence[i]);
                System.out.print("\t");
    
                for (int j = 0; j < memoryBlocksNum * 6 + 1; j++)
                {
                    System.out.print("-");
                }
    
                System.out.print("\n\t");
    
                for (int k = 0; k < memoryBlocksNum; k++)
                {
                    if (k == 0)
                    {
                        System.out.print("|");
                    }
                    //如果当前内存块还没被使用,置为空
                    if (memoryBlocksState[i][k] == -1)
                    {
                        System.out.printf("%5s|", " ");
                    }
                    else
                    {
                        System.out.printf("%5s|", memoryBlocksState[i][k]);
                    }
                }
    
                System.out.print("  缺页情况:" + pagesDescription[isLackofPage[i]]);
    
                System.out.print("\n\t");
    
                for (int j = 0; j < memoryBlocksNum * 6 + 1; j++)
                {
                    System.out.print("-");
                }
    
                System.out.println();
            }
    
            //缺页率
            double lackOfPagesRate = lackTimes * 1.0 / pagesSequence.length;
    
            System.out.println("\n该程序的页号序列长度为:" + pagesSequence.length + ", 执行该算法后,缺页次数为:" + lackTimes + ", 缺页率为:" + lackOfPagesRate * 100 + "%");
        }
    
    }
    
    
    //LRU算法的辅助存储类
    class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V>
    {
        //最大内存块数(容量)
        private int maxMemoryBlocksNum;
    
        //设置默认负载因子
        private static final float DEFAULT_LOAD_FACTOR = 0.75f;
    
        public LRULinkedHashMap(int maxCapacity)
        {
            //设置accessOrder为true,保证了LinkedHashMap底层实现的双向链表是按照访问的先后顺序排序
            super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
            this.maxMemoryBlocksNum = maxCapacity;
        }
    
        //得到最近最少被访问的元素
        public V getHead()
        {
            return (V) this.values().toArray()[0];
        }
    
        //移除多余的最近最少被访问的元素
        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest)
        {
            return size() > maxMemoryBlocksNum;
        }
    }



    五. 测试情况

    4


    顺便附上项目源码,支持开源精神,欢迎star、fork:
    https://github.com/Yuziquan/PageReplacementSimulation


    (希望可以帮到有需要的人~~)

    展开全文
  • swing实现页面置换算法模拟系统代码 源代码下载地址:http://www.zuidaima.com/share/1822243586837504.htm 页面置换算法是操作系统方面的知识, 在地址映射过程中,若在页面中发现所要访问的页面不在内存...
  • 页面置换算法综合实现(JavaJava Swing)算法导入算法分析一、界面分析二、界面设计三、界面相关算法设计算法展示一、操作展示二、算法比较结尾 算法导入        失踪人口回归...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,499
精华内容 1,799
关键字:

页面置换算法java

java 订阅