虚拟存储管理仿真

实验内容

模拟请求分页虚拟存储管理技术中的硬件地址变换、缺页中断及页式淘汰算法处理缺页中断

实验目的

为了使大的作业(其地址空间超过内存可用空间)或多个作业的地址空间之和超过实际主存空间时,仍能运行,引入了”虚拟存储器”的概念.使作业的一部分地址空间在主存,另一部分在辅存,由操作系统实现多级存储的自动管理,实现主存间的自动覆盖.要求通过本实验,对请求分页管理有一个清楚的概念.

实验题目

第一部分:模拟请求分页虚拟存储管理技术中的硬件地址变换和缺页中断的过程
提示:
1、 请求分页虚拟存储管理技术是把作业地址空间的全部信息存放在磁盘上,当作业被选中运行时,先把作业的开始几页装入主存并启动运行.为此,在为作业建立页表时,应说明哪些页已在内存,哪些页不在内存.
页表的格式如下:
在这里插入图片描述
2、 作业在执行时,指令中的逻辑地址指出参加运算操作数(或指令)地址中的页号和页内偏移量.硬件地址转换机构按页号查页表.
若该页的标志为”1”,则表示该页已在主存,从而找到该页对应的内存块号,根据关系式:
绝对地址=块号*块的长度+页内偏移量
计算出欲访问的内存地址.由于页长为2的整次幂,所以只要将块号与页内偏移量相拼接,放入地址寄存器即可按照该地址取指令或取操作数,完成指定的操作.
若对应的页不在内存(即标志为0),则硬件产生缺页中断,转操作系统处理系统.根据页表中的”外存地址”,找到该页.再查内存分块表,找一个空闲块装入该页,修改页表和内存分块表,继续执行被中断的指令.
3、 设计一个”地址变换”程序,模拟硬件地址变换过程:
当访问的页在内存时,则形成绝对地址后,不去模拟指令的执行,而是输出被转换的地址;当访问的页不在内存时,则输出”*该页(页号)不在内存”,以表示产生了一次缺页中断;若地址非法,显示”地址非法”,并终止程序的运行
在这里插入图片描述假定内存的每块长度为128字节,现有一个只有七页的作业,其中第0页至第3页已经装入内存.该作业的页表如下:
在这里插入图片描述作业执行的指令序列如下表:
在这里插入图片描述运行你设计的地址变换程序,显示或打印运行结果.因为只是模拟地址变换,并不模拟指令的执行,故不考虑上述指令的操作结果.
第二部分:采用先进先出(或LRU)算法,实现分页管理的缺页调度.
提示:
1、 在分页虚拟存储系统中,当硬件发出缺页中断时,若内存中已无空闲块,当采用FIFO算法时,则淘汰最先进入内存的页,若该页修改过,还要存入磁盘,然后,再把当前要访问的页装入该块,并修改表中的对应标志.
2、 当采用LRU算法时,则淘汰最近很少访问的页.
两算法均可采用一个数组或链表记录内存中页号的排序,每次将链首页淘汰.数组或链表中只包含页的虚页号─项信息,其它信息通过查页表得到.
在这里插入图片描述

在这里插入图片描述

实验报告:

	(1)、程序中使用数据结构和符号说明.
	(2)、给出程序流程.
	(3)、打印初始页表、调入/出的页、每执行完一条指令页表的状态及得到的内存地址
	(4)、编程语言不限。

采用LRU算法解决

  • 首先创建page类模拟页,生成geeter setter 有参 无参方法 我引入的lombox插件自动生成,手动生成也可以
package com.xu.demo.ytu.lru;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Page {
    private  int pageNum;
    private int flag;
    private  int cacheNum;
    private String outAddress;
    private int changeNum;

    @Override
    public String toString() {
        return
                "\t"+pageNum +
                "                 \t" + flag +
                "                   \t" + cacheNum +
                "                   \t" + outAddress +
                "                   \t" + changeNum ;
    }
}
  • 创建work类模拟工作表,生成geeter setter 有参 无参方法 我引入的lombox插件自动生成,手动生成也可以
package com.xu.demo.ytu.lru;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Work {
    private String operation;
    private int pageNum;
    private String unitNum;
}
  • LRU算法核心
package com.xu.demo.ytu.lru;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LRU {
    Node head, tail;
    int size;
    //容量
    int capacity;

    Map<Integer, Node> cache;

    public LRU(int capacity) {
        this.capacity = capacity;
        //初始化链表
        initDoubleLinkList();
        size = 0;
        cache = new HashMap<>(capacity + 2);
    }

    public static class Node {
        public Node pre;
        public Node next;
        public int key;
        public Page page;

        public Node(int key, Page page) {
            this.key = key;
            this.page = page;
        }

        //空参
        public Node() {
        }
    }

    private void initDoubleLinkList() {
        //头结点
        head = new Node();
        //尾结点
        tail = new Node();
        //头指向尾
        head.next = tail;
        //尾指向头
        tail.pre = head;
    }

    //删除结点
    private void deleteNode(Node node) {
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    //添加结点
    private void addNode(Node node) {
        head.next.pre = node;
        node.next = head.next;

        node.pre = head;
        head.next = node;
    }

    private void moveToHead(Node node) {
        //删除原来的结点关系
        deleteNode(node);
        //添加结点到头部
        addNode(node);
    }

    public Page get(int key) {
        Node node = cache.get(key);
        if (node == null) {
            return null;
        }
        moveToHead(node);
        return node.page;
    }

    public void put(int key, Page page) {
        //hashmap中直接查出时间复杂度为O(1)
        Node node = cache.get(key);
        //如果链表中存在继续添加就是把它添加到首位
        if (node != null) {
            node.page = page;
            moveToHead(node);
            return;
        }
        //如果不存在,先加进去,再移除尾结点
        if (size == capacity) {
            Node lastNode = tail.pre;
            deleteNode(lastNode);
            cache.remove(lastNode.key);
            size--;
        }
        //加入头结点
        Node newNode = new Node();
        newNode.key = key;
        newNode.page = page;
        addNode(newNode);
        cache.put(key, newNode);
        size++;
    }


    public static void main(String[] args) {
        //缓存容量为4
        LRU cache = new LRU(4);
        //已经存在与缓存的数据
        cache.put(3, new Page(3, 1, 1, "021", 0));
        cache.put(2, new Page(2, 1, 9, "013", 0));
        cache.put(1, new Page(1, 1, 8, "012", 1));
        cache.put(0, new Page(0, 1, 5, "011", 1));
        //初始化页
        List<Page> pages = new ArrayList<>();
        pages.add(new Page(0, 1, 5, "011", 1));
        pages.add(new Page(1, 1, 8, "012", 1));
        pages.add(new Page(2, 1, 9, "013", 0));
        pages.add(new Page(3, 1, 1, "021", 0));
        pages.add(new Page(4, 0, 0, "022", 0));
        pages.add(new Page(5, 0, 0, "023", 0));
        pages.add(new Page(6, 0, 0, "123", 0));
        System.out.println("————————————————————执行 初始化 操作————————————————————");
        System.out.println("  页号              \t标志            \t内存块号      \t外存地址           \t修改值");
        for (Page page : pages) {
            System.out.println(page + "\t");
        }
        System.out.println("LRU队列顺序:");
        System.out.print(cache.head.next.page.getPageNum()+"<--");
        System.out.print(cache.head.next.next.page.getPageNum()+"<--");
        System.out.print(cache.tail.pre.pre.page.getPageNum()+"<--");
        System.out.print(cache.tail.pre.page.getPageNum());
        System.out.println();

        //初始化工作表
        List<Work> works = new ArrayList<>();
        works.add(new Work("+", 0, "070"));
        works.add(new Work("+", 1, "050"));
        works.add(new Work("*", 2, "015"));
        works.add(new Work("存", 3, "021"));
        works.add(new Work("取", 0, "057"));
        works.add(new Work("-", 6, "040"));
        works.add(new Work("移位", 4, "053"));
        works.add(new Work("+", 5, "023"));
        works.add(new Work("存", 1, "037"));
        works.add(new Work("取", 2, "076"));
        works.add(new Work("+", 4, "001"));
        works.add(new Work("取", 6, "074"));
        //执行操作
        for (Work work : works) {
            Page page = cache.get(work.getPageNum());
            if (page == null) {
                System.out.println("————————————————————执行 " + work.getOperation() + " 操作————————————————————");
                System.out.println("操作的页:"+work.getPageNum());
                System.out.println("缓存不存在该页,发出缺页请求");
                System.out.println("该页面在于内存中");
                System.out.println("淘汰的页:"+cache.tail.pre.page.getPageNum());
                int i = Integer.parseInt(work.getUnitNum(), 8);
                pages.get(work.getPageNum()).setCacheNum(cache.tail.pre.page.getCacheNum());
                pages.get(cache.tail.pre.page.getPageNum()).setFlag(0);
                pages.get(cache.tail.pre.page.getPageNum()).setChangeNum(0);
                pages.get(cache.tail.pre.page.getPageNum()).setCacheNum(0);
                cache.put(work.getPageNum(), pages.get(work.getPageNum()));

                int n = (pages.get(work.getPageNum()).getCacheNum()) * 128 + i;
                System.out.println("绝对地址:" + Integer.toHexString(n));
                pages.get(work.getPageNum()).setFlag(1);
                pages.get(work.getPageNum()).setChangeNum(1);

                System.out.println("  页号              \t标志            \t内存块号      \t外存地址           \t修改值");
                for (Page p : pages) {
                    System.out.println(p + "\t");
                }
                System.out.println("LRU队列顺序:");
                System.out.print(cache.head.next.page.getPageNum()+"<--");
                System.out.print(cache.head.next.next.page.getPageNum()+"<--");
                System.out.print(cache.tail.pre.pre.page.getPageNum()+"<--");
                System.out.print(cache.tail.pre.page.getPageNum());
                System.out.println();

            } else {
                System.out.println("————————————————————执行 " + work.getOperation() + " 操作————————————————————");
                System.out.println("操作的页:"+work.getPageNum());
                System.out.println("该页存在于缓存中");
                //将8进制转10进制再转16进制
                String reallyAddress = Integer.toHexString(page.getCacheNum() * 128 + Integer.parseInt(work.getUnitNum(), 8));
                System.out.println("绝对地址:" + reallyAddress);

                pages.get(work.getPageNum()).setFlag(1);
                pages.get(work.getPageNum()).setChangeNum(1);

                System.out.println("  页号              \t标志            \t内存块号      \t外存地址           \t修改值");
                for (Page p : pages) {
                    System.out.println(p + "\t");
                }
                System.out.println("LRU队列顺序:");
                System.out.print(cache.head.next.page.getPageNum()+"<--");
                System.out.print(cache.head.next.next.page.getPageNum()+"<--");
                System.out.print(cache.tail.pre.pre.page.getPageNum()+"<--");
                System.out.print(cache.tail.pre.page.getPageNum());
                System.out.println();
            }


        }


    }


}
  • 算法设计思路请添加图片描述

运行结果

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 6
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
虚拟仿真软件的技术架构通常包括以下几个方面: 1. 模型库:模型库是虚拟仿真软件的核心组成部分,它包含了各种模型,如物理模型、数学模型等。这些模型是基于真实世界的物理规律和数学原理进行建模,以便在虚拟环境中进行仿真。 2. 图形引擎:图形引擎是用于渲染虚拟环境的技术,它能够将模型库中的模型进行可视化,使用户能够在虚拟环境中看到物体的形态和位置。 3. 物理引擎:物理引擎是用于模拟物理规律的技术,它能够对虚拟环境中的物体进行运动学和动力学计算,以模拟真实世界的物理现象。 4. 交互模块:交互模块是用于用户与虚拟环境进行互动的技术,包括用户输入和虚拟环境的响应。用户可以通过鼠标、键盘等设备与虚拟环境进行交互,虚拟环境可以根据用户的操作进行响应。 5. 数据库:数据库是用于存储虚拟环境中的各种数据,如模型、纹理、动画等。虚拟环境的运行过程中需要频繁地读取和写入数据,因此数据库的性能和可靠性对虚拟仿真软件的运行效率和稳定性至关重要。 6. 网络通信:虚拟仿真软件通常需要与其他软件或设备进行通信,如与传感器、控制器等进行数据交换。因此,网络通信技术也是虚拟仿真软件的重要组成部分。 虚拟仿真软件的技术架构需要综合考虑以上几个方面,以确保其稳定、高效、易用和可扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小小徐404

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值