近日,在体系结构的课程中,老师留了一个上机作业,为cache—主存—辅存三级调度模拟,要求如下:

实现三级存储体系的模拟调度程序

描述:CPU在cache访问数据块,若命中给出对应的cache实地址,若不命中在主存中查找,如果找到调入到cache中,若是cache已满使用LRU算法进行替换,采用写回法保持cache与主存的一致性。若是没有命中在辅存中查找,找到之后调入到主存,并更新cache。

实验要求:

(1)主存的容量可以更改

(2)分配给程序的页面数可以更改

(3)Cache采用组相连映像,cache大小、组数、组内块数均可以更改

(4)地址流可以采用输入的方式给出

(5)辅存部分可以不用实现

(6)要求有图形化的用户界面,上述参数均可以直接输入。

(7)显示执行程序时数据块以及页面的替换过程

(8)编程语言:选取自己熟悉的高级语言

百度了很久,没有找到Cache组相联映像的LRU替换算法,以下只是自己的一点想法与思路,若有不足,欢迎指正。

程序运行界面如下:

  

 点击确定后:

  

第0组Cache块中各个块的使用情况为:
T1时刻 1
T2时刻 1
T3时刻 1 4
T4时刻 4 1
T5时刻 4 1
T6时刻 4 1
T7时刻 1 0
T8时刻 0 1
T9时刻 0 1
T10时刻 1 5
T11时刻 5 4
T12时刻 5 4
T13时刻 5 4
T14时刻 5 4
T15时刻 5 4

第1组Cache块中各个块的使用情况为:
T2时刻 2
T3时刻 2
T4时刻 2
T5时刻 2 3
T6时刻 3 7
T7时刻 3 7
T8时刻 3 7
T9时刻 7 2
T10时刻 7 2
T11时刻 7 2
T12时刻 2 6
T13时刻 2 6
T14时刻 6 7
T15时刻 7 2

下面是Cache类的代码,主要实现Cache的LRU替换算法,使用LinkedHashMap本身自带的特性实现的LRU算法

import java.util.LinkedHashMap;
import java.util.Map; /**
* 模拟Catch块中的LRU替换算法
* 此处使用java中LinkedHashMap,利用其自身特性,对removeEldestEntry()方法进行重写
* @author SUIXUE
*
*/
public class Cache { public int cacheSize = 2; public Cache(){ } public Cache(int cacheSize){
this.cacheSize = cacheSize;
} //此处的写法避免了新建类,也无需继承
Map<Integer, Integer> map = new LinkedHashMap<Integer, Integer>((int) Math.ceil(cacheSize / 0.75f) + 1, 0.75f, true) {
/**
*
*/
private static final long serialVersionUID = 1L; @Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > cacheSize;
}
}; /**
* 重写toString()方法
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Map.Entry<Integer, Integer> entry : this.map.entrySet()) {
sb.append(String.format("%s ", entry.getKey()));
}
return sb.toString();
} /**
* 此处的主要目的是在Cache中采用组相联映像时,在输出结果时同时显示当前时间
* @param addr
* @return
*/
public String display(int[] addr){
StringBuilder sb = new StringBuilder();
int index =15-addr.length+1;
for(int i = 0; i < addr.length;i++){
this.map.put(addr[i], 0);
sb.append("T").append(index++).append("时刻 ").append(this.toString()+"\n");
}
return sb.toString();
}
}

下面是主界面的代码

 import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList; import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField; /**
* MainFrame类: 继承JFrame,同时实现接口ActionListener
*
* @author SUIXUE
*
*/
public class MainFrame extends JFrame implements ActionListener { /**
*
*/
private static final long serialVersionUID = 1L; private int memory = 0;
private int page = 0;
private int memoryQuNum = 0; public int cacheSizeNum = 16;
public int cacheGroupNum = 2;
public int cacheBlockNumber = 2; private int cacheNum = cacheGroupNum * cacheBlockNumber;
private int memoryBlockNum = 0;
public int[] addr = new int[] {1,2,4,1,3,7,0,1,2,5,4,6,4,7,2};//默认的地址流,可以在界面文本框中更改 public Cache[] cache;// 将cache的每组看做一个cache块
public ArrayList<Integer>[] cacheAddrs;// 每组都有对应的地址流 /**
* 初始化Cache分组(本方法是将每个分组看做一个单独独立的Cache块)
*/
public void initCache() {
for (int i = 0; i < cache.length; i++) {
cache[i] = new Cache(cacheBlockNumber);
}
} /**
* 初始化地址流
* 将用户输入的地址流,通过分析,分别对应进入不同的Cache分组中
*/
public void initAddrs() {
for (int i = 0; i < cacheAddrs.length; i++) {
cacheAddrs[i] = new ArrayList<>();
}
for (int i = 0; i < addr.length; i++) {
int temp = addr[i] % this.cacheNum;// 7%4 = 3
int groupNum = temp / this.cacheBlockNumber;// 3/2 = 1 ArrayList<Integer> arrayList = cacheAddrs[groupNum];
arrayList.add(addr[i]);// 向各组添加地址流 //当当前地址不对其他组进行影响时,其他组中的Cache地址流其实等同于该时刻仍是它上一次的地址
if(i != 0){
for(int j = 0; j < cacheGroupNum;j++){
if(j != groupNum && cacheAddrs[j].size()>0){
cacheAddrs[j].add(cacheAddrs[j].get(cacheAddrs[j].size()-1));
}
}
}
}
} private JPanel mainPanel; /**
* 左侧面板
*/
private JPanel originalPanel; // 主存大小
private JPanel memoryPanel;
private JLabel memorySizeLabel;
private JTextField memorySize; // 页面数
private JPanel pagePanel;
private JLabel pageNumLabel;
private JTextField pageNum; // cache
private JPanel cachePanel; // cache大小
private JPanel cacheSizePanel;
private JLabel cacheSizeLabel;
private JTextField cacheSize; // 组数
private JPanel cacheGroupSizePanel;
private JLabel cacheGroupSizeLabel;
private JTextField cacheGroupSize; // 组内块数
private JPanel cacheBlockNumPanel;
private JLabel cacheBlockNumLabel;
private JTextField cacheBlockNum; // 按钮
private JPanel button;
private JPanel addrPanel;
private JTextField addrText;
private JLabel addrLabel;
private JButton affirm; /**
* 右侧面板
*/
private JScrollPane scrollPanel;
private JPanel resultPanel; private JLabel display; // 右侧转换结果显示框
private JTextArea resultArea; /**
* 构造函数
*/
public MainFrame() {
initComponent();
} // 初始各组件
private void initComponent() { // 设置布局
mainPanel = new JPanel();
mainPanel.setLayout(new GridLayout(1, 2)); // --------左侧面板---------------
originalPanel = new JPanel();
originalPanel.setLayout(new BorderLayout()); // -------主存面板----------------
memoryPanel = new JPanel();
memorySizeLabel = new JLabel("主存容量");
memorySize = new JTextField(10);
memorySize.setHorizontalAlignment(JTextField.RIGHT);
memorySize.setText("32");
JLabel unitLabel = new JLabel("KB");
memoryPanel.add(memorySizeLabel, BorderLayout.WEST);
memoryPanel.add(memorySize, BorderLayout.CENTER);
memoryPanel.add(unitLabel, BorderLayout.EAST); // ---------页面大小面板----------------
pagePanel = new JPanel();
pageNumLabel = new JLabel("页面大小");
pageNum = new JTextField(10);
pageNum.setHorizontalAlignment(JTextField.RIGHT);
pageNum.setText("3");
JLabel unitLabel1 = new JLabel("页");
pagePanel.add(pageNumLabel, BorderLayout.WEST);
pagePanel.add(pageNum, BorderLayout.CENTER);
pagePanel.add(unitLabel1, BorderLayout.EAST); JPanel tempPanel = new JPanel();
tempPanel.setLayout(new GridLayout(2, 1));
tempPanel.add(memoryPanel);
tempPanel.add(pagePanel); // -----------cache面板---------------
cachePanel = new JPanel();
cachePanel.setLayout(new GridLayout(3, 1));
cachePanel.setBorder(BorderFactory.createTitledBorder("cache")); cacheSizeLabel = new JLabel("cahce大小");
cacheSize = new JTextField(10);
cacheSize.setHorizontalAlignment(JTextField.RIGHT);
cacheSize.setText("16");
JLabel unitLabel2 = new JLabel("KB");
cacheSizePanel = new JPanel();
cacheSizePanel.add(cacheSizeLabel, BorderLayout.WEST);
cacheSizePanel.add(cacheSize, BorderLayout.CENTER);
cacheSizePanel.add(unitLabel2, BorderLayout.EAST); cacheGroupSizeLabel = new JLabel("cahce组数");
cacheGroupSize = new JTextField(10);
cacheGroupSize.setHorizontalAlignment(JTextField.RIGHT);
cacheGroupSize.setText("2");
JLabel unitLabel3 = new JLabel("组");
cacheGroupSizePanel = new JPanel();
cacheGroupSizePanel.add(cacheGroupSizeLabel, BorderLayout.WEST);
cacheGroupSizePanel.add(cacheGroupSize, BorderLayout.CENTER);
cacheGroupSizePanel.add(unitLabel3, BorderLayout.EAST); cacheBlockNumLabel = new JLabel("组内块数 ");
cacheBlockNum = new JTextField(10);
cacheBlockNum.setHorizontalAlignment(JTextField.RIGHT);
cacheBlockNum.setText("2");
JLabel unitLabel4 = new JLabel("块");
cacheBlockNumPanel = new JPanel();
cacheBlockNumPanel.add(cacheBlockNumLabel, BorderLayout.WEST);
cacheBlockNumPanel.add(cacheBlockNum, BorderLayout.CENTER);
cacheBlockNumPanel.add(unitLabel4, BorderLayout.EAST); cachePanel.add(cacheSizePanel);
cachePanel.add(cacheGroupSizePanel);
cachePanel.add(cacheBlockNumPanel); button = new JPanel();
button.setLayout(new GridLayout(2,1)); addrLabel = new JLabel("块地址流 ");
addrText = new JTextField(20);
addrText.setHorizontalAlignment(JTextField.RIGHT);
addrText.setText("1 2 4 1 3 7 0 1 2 5 4 6 4 7 2");
addrPanel = new JPanel();
addrPanel.add(addrLabel,BorderLayout.WEST);
addrPanel.add(addrText,BorderLayout.CENTER); JPanel affirmPanel = new JPanel();
affirm = new JButton("确定");
affirmPanel.add(affirm,BorderLayout.CENTER); button.add(addrPanel);
button.add(affirmPanel);
affirm.addActionListener(this); originalPanel.add(tempPanel, BorderLayout.NORTH);
originalPanel.add(cachePanel, BorderLayout.CENTER);
originalPanel.add(button, BorderLayout.SOUTH); // --------右侧面板---------------
resultPanel = new JPanel();
resultPanel.setLayout(new BorderLayout()); display = new JLabel("Cache中各个块的使用情况"); resultArea = new JTextArea();
resultArea.setEditable(false);
resultArea.setBorder(BorderFactory.createTitledBorder("RESULT")); scrollPanel = new JScrollPane(resultArea); resultPanel.add(display, BorderLayout.NORTH);
resultPanel.add(scrollPanel, BorderLayout.CENTER); // -------------------------------------------------------
mainPanel.add(originalPanel);
mainPanel.add(resultPanel);
mainPanel.setBorder(BorderFactory.createTitledBorder("三级调度模拟")); this.add(mainPanel);
this.setTitle("小可爱的三级调度模拟");
this.setSize(750, 350);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setVisible(true); } @Override
public void actionPerformed(ActionEvent e) { try {
this.memory = Integer.valueOf(memorySize.getText());
this.page = Integer.valueOf(pageNum.getText());
this.cacheSizeNum = Integer.valueOf(cacheSize.getText());
this.cacheGroupNum = Integer.valueOf(cacheGroupSize.getText());
this.cacheBlockNumber = Integer.valueOf(cacheBlockNum.getText());
this.cacheNum = cacheGroupNum * cacheBlockNumber;
this.memoryQuNum = this.memory / this.cacheSizeNum;
this.memoryBlockNum = this.memoryQuNum * this.cacheNum; cache = new Cache[cacheGroupNum];
cacheAddrs = new ArrayList[cacheGroupNum]; String addrString = this.addrText.getText();
String[] addrItems = addrString.split(" "); for(int i=0;i<addrItems.length;i++){
this.addr[i]=Integer.parseInt(addrItems[i]);
} this.initCache();
this.initAddrs(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < this.cache.length; i++) {
sb.append("第").append(i).append("组Cache块中各个块的使用情况为:\n");
int[] addrTemp = new int[cacheAddrs[i].size()];
for (int j = 0; j < this.cacheAddrs[i].size(); j++) {
addrTemp[j] = ((Integer) this.cacheAddrs[i].get(j))
.intValue();
}
sb.append(this.cache[i].display(addrTemp)).append("\n");
}
resultArea.setText(sb.toString());
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "所有输入均为正整数!\n地址流输入只能用一个空格隔开", "Sorry",
JOptionPane.INFORMATION_MESSAGE);
memorySize.setText("32");
pageNum.setText("3");
cacheSize.setText("16");
cacheGroupSize.setText("2");
cacheBlockNum.setText("2");
addrText.setText("1 2 4 1 3 7 0 1 2 5 4 6 4 7 2");
} } /**
* main 方法
*
* @param args
*/
public static void main(String[] args) {
new MainFrame();
}
}

MainFrame

在解决Cache的组相联映像中,我主要采用的方法是将地址流随Cache分组而进行分组,只有特定的主存块才能进入到特定的Cache组中。针对每一组的Cache进行基本的Cache的LRU替换算法(Cache类中)

cache—主存—辅存三级调度模拟的更多相关文章

  1. 在Unix系统中,主存索引节点和辅存索引节点从内容上比较有什么不同,为什么要设置主存索引节点?

    主存索引节点和辅存索引节点的不同主要体现在:主存索引节点状态:设备号.索引节点号:引用计数. 主存索引节点状态——反映主存索引节点的使用情况.它指示出: 1.  索引节点是否被锁上了: 2.  是否有 ...

  2. [Spark Core] Spark Client Job 提交三级调度框架

    0. 说明  官方文档  Job Scheduling Spark 调度核心组件: DagScheduler TaskScheduler BackendScheduler 1. DagSchedule ...

  3. Java基础面试操作题:线程同步代码块 两个客户往一个银行存钱,每人存三十次一次存一百。 模拟银行存钱功能,时时银行现金数。

    package com.swift; public class Bank_Customer_Test { public static void main(String[] args) { /* * 两 ...

  4. cache与MMU与总线仲裁

    为了以合理的价格,设计容量和速度满足计算机系统的需求,计算机体系结构设计者设计出了存储器的层次结构. "Cache-主存"和"主存-辅存"是最常见的两种层次结构 ...

  5. 【重学计算机】机组D4章:存储系统

    1. 存储系统层次结构 主存速度缓慢的原因:主存增速与CPU不同步,执行指令期间多次访问主存 主存容量不足的原因: 存在制约主存容量的技术因素:如由CPU.主板等相关技术指标规定了主存容量 应用对主存 ...

  6. OpenStack 高性能虚拟机之大页内存

    目录 文章目录 目录 前文列表 虚拟存储器系统 页式虚拟存储器 大页内存 Linux 的大页内存 大页的实现原理 大页内存配置 透明巨型页 THP 大页面对内存的影响 Nova 虚拟机的大页内存设置 ...

  7. Java并发编程的本质是解决这三大问题

    [本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] 前言 并发编程的 ...

  8. 【av68676164(p51-p53)】虚拟内存管理(2)

    虚拟内存管理(2) 7.3.4 缺页终端 分级存储体系 cache+内存+辅存 页表扩充-带中断位的页表 页号 页框号 中断位I 辅存地址 访问位 修改位 1 1 0 0 0 1 中断位I-标志该页是 ...

  9. Cache and Virtual Memory

    Cache存储器:电脑中为高速缓冲存储器,是位于CPU和主存储器DRAM(DynamicRandonAccessMemory)之间,规模较小,但速度很高的存储器,通常由SRAM(StaticRando ...

随机推荐

  1. Json传递后台数据的问题

    在后台我有两个类: public Class Person { private String name; private Address address;//一个自定义的类 //getter和sett ...

  2. QTP自传之对象库编程

    对象库编程是我们平时工作中使用最多的编程方式,在自动化脚本开发中起到举足轻重的作用,与描述性性编程相比,更直接和易于维护,今天就和大家简单的聊聊如何进行对象库编程. 既然是对象库编程,肯定要对已存在于 ...

  3. arcgis数据文件使用

    dem数据打开,保存,使用 打开

  4. wait和waitpid的使用和区别

    昨天看到一则新闻,讲的是一个游戏开发大拿猝死去世的新闻,公司发了讣告,打算接下去给他爸爸妈妈每个月10000的赡养费,很是感慨,本来中国的游戏业和国外就差距大,天妒英才啊.真心想对那些游戏公司的领导说 ...

  5. firefox HackBar组件模拟请求POST请求

    组件下载地址:https://addons.mozilla.org/zh-CN/firefox/addon/hackbar/

  6. 一步一步学android之事件篇——单击事件

    在使用软件的时候单击事件必不可少,比如我想确定.取消等都需要用户的单击,所有的单击事件都是由View.OnClickListener接口来进行处理的,接口定义如下: public static int ...

  7. errno与perror

    很多系统函数在错误返回时将错误原因记录在libc定义的全局变量errno中,每种错误原因对应一个错误码,请查阅errno(3)的Man Page了解各种错误码,errno在头文件errno.h中声明, ...

  8. 在eclipse下编译hadoop2.0源码

    Hadoop是一个分布式系统基础架构,由apache基金会维护并更新.官网地址: http://hadoop.apache.org/ Hadoop项目主要包括以下4个模块: Hadoop Common ...

  9. 360. Sort Transformed Array

    一元二次方程...仿佛回到了初中. 主要看a的情况来分情况讨论: =0,一次函数,根据b的正负单调递增递减就行了. <0,凸状..从nums[]左右两边开始往中间一边比较一边 从右往左 放: 0 ...

  10. AngularJS测试二 jasmine测试路由 控制器 过滤器 事件 服务

    测试应用 1.测试路由 我们需要检测路由是否在运作,是否找到了,或者是404了.我们要确认路由事件触发了,预期的模板是否真的加载了.既然路由会改变页面的地址(URL)和页面内容,我们需要检测路由是否被 ...