- 目的要求
理解虚拟存储器概念,并掌握分页式存储管理地址转换和缺页中断的处理过程。用高级语言模拟请求分页式虚拟存储器的工作过程和页面置换算法LRU。
- 准备知识
- 分页式存储管理原理
在存储器管理中,连续分配方式会形成许多“碎片”,虽然可通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大开销。
如果允许将一个进程直接分散地装入到许多不相邻的分区中,则无须再进行“紧凑”。基于这一思想而产生了离散分配方式。如果离散分配的基本单位是页,则称为分页存储管理方式。在分页存储管理方式中,如果不具备页面对换功能,则称为基本分页存储管理方式,或称为纯分页存储管理方式,它不具有支持实现虚拟存储器的功能,它要求把每个作业全部装入内存后方能运行。
请求式分页系统是建立在基本分页基础上的,为了能支持虚拟存储器功能,而增加了请求调页功能和页面置换功能。
- LRU(Least recently used,最近最少使用)算法
根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
- 实现LRU的常用方法
- 用一个数组来存储数据,给每一个数据项标记一个访问时间戳,每次插入新数据项的时候,先把数组中存在的数据项的时间戳自增,并将新数据项的时间戳置为0并插入到数组中。每次访问数组中的数据项的时候,将被访问的数据项的时间戳置为0。当数组空间已满时,将时间戳最大的数据项淘汰。
- 利用一个链表来实现,每次新插入数据的时候将新数据插到链表的头部;每次缓存命中(即数据被访问),则将数据移到链表头部;那么当链表满的时候,就将链表尾部的数据丢弃。
- 实验内容
设计程序模拟请求分页式虚拟存储器的地址变换和缺页中断处理过程。
页面置换算法:最近最少使用(LRU)算法。
- 建立一个存储分块表(MBT),表示内存所有物理页的当前状态,是否空闲。此表用来为进程分配所需的内存空间,每个进程可分配5个物理页。
- 页面大小为1K个存储单元。
- 允许多进程并发执行,为每个进程建立一个页表,表示该进程中各逻辑页是否已经调入内存,如果已经调入,该逻辑页对应的内存物理页号。
- 当进程发生缺页中断,并且对应的5个物理页没有空闲时,实现采用LRU算法页面置换。
- 程序模拟输出进程的访存过程:输入逻辑地址,转换为逻辑页号和页内地址,判断是否产生缺页中断完成调页,然后实现地址变换,查页表得到对应的物理页号,从而得到物理地址。
- 实验结果
程序运行结果(截图)如下。
- 初始化MBT,创建进程,逻辑地址分别为1000,2000,3000,4000,5000
- 地址变换,进程的5个逻辑地址依次加入内存
- 访问地址,如果页面在主存中时间戳自增,不在主存则使用LRU算法置换页面
- 源程序
- MBT.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace 操作系统实验3
{
class MBT
{
//物理空间大小
int num;
public int Num
{
get { return num; }
set { num = value; }
}
//数组,大小为num,每一项都是物理页Page
ArrayList pageList = new ArrayList();
public ArrayList PageList
{
get { return pageList; }
set { pageList = value; }
}
public void createList(int num)
{
pageList.Capacity = num;
for (int i = 0; i < num; i++)
{
Page p = new Page();
p.Timestamp = -1;
p.Index = i;
p.State = "free";
pageList.Add(p);
}
}
public string print()
{
string s = "MBT\r\n"+"第几项 "+"页码 "+"状态 "+"时间戳\r\n";
for (int i = 0; i < pageList.Count; i++)
{
Page p = pageList[i] as Page;
//s += "物理内存为" + Num + "\r\n";
s += i + " " + p.Index + " " + p.State + " " + p.Timestamp + "\r\n";
}
return s;
}
public string LRU(int i)
{
string s="";
s += "当前无空闲页\r\n";
s += "正在执行LRU算法\r\n";
//s += LRU();
Page p = new Page();
p.Timestamp = 0;
p.Index = i; ;
p.State = "busy";
pageList.Add(p);
s += p.Index + "已加入成功\r\n";
s += print();
int index= getMax();
Page p0=pageList[index] as Page;
pageList.RemoveAt(index);
return p0.Index + "已被移除\r\n";
}
//遍历数组中的所有Page页,如果页面状态为free的话则修改此页面的index为table每一项的index
public string addTable(PageTable pt)
{
string s = "正在将页表加入内存\r\n";
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < pageList.Count; j++)
{
Page p = pageList[j] as Page;
//p.Timestamp++;
if (p.Index==pt.PhysicsIndex1[i]&& p.State == "free")
{
p.Timestamp = 0;
p.Index = pt.PhysicsIndex1[i];
p.State = "busy";
s += p.Index + "已加入成功\r\n";
s += print();
break;
}
}
// else continue;
// Form1.Delay(3);
}
return s;
}
public int getMax()
{
Page p0=pageList[0] as Page;
int max=0;
for (int i = 0; i < pageList.Count; i++)
{
Page p = pageList[i] as Page;
if (p.Timestamp > p0.Timestamp)
max = i;
}
return max;
}
class newsCompare : IComparer
{
int System.Collections.IComparer.Compare(object x, object y)
{
Page newsX = (Page)x;
Page newsY = (Page)y;
if (newsX.Timestamp > newsY.Timestamp)
return -1;
if (newsX.Timestamp < newsY.Timestamp)
return 1;
return 0;
}
}
}
}
- Table.cs 逻辑地址 页码+位移量 表
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 操作系统实验3
{
public class Table
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
//页码
int[] index = new int[5];
public int[] Index
{
get { return index; }
set { index = value; }
}
//位移量
int[] x = new int[5];
public int[] X
{
get { return x; }
set { x = value; }
}
public void setIndex(int a,int b,int c,int d,int e)
{
index[0] = a;
index[1] = b;
index[2] = c;
index[3] = d;
index[4] = e;
}
public void setX(int a, int b, int c, int d, int e)
{
x[0] = a;
x[1] = b;
x[2] = c;
x[3] = d;
x[4] = e;
}
public string print()
{
string s = name+"页表已经建好\r\n";
for (int i = 0; i < 5; i++)
{
s += index[i] + " " + x[i] + "\r\n";
}
return s;
}
}
}
- Page.cs 每一页物理页
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 操作系统实验3
{
class Page
{
//物理页
int index;
public int Index
{
get { return index; }
set { index = value; }
}
string state;
public string State
{
get { return state; }
set { state = value; }
}
int timestamp;
public int Timestamp
{
get { return timestamp; }
set { timestamp = value; }
}
}
}
- PageTable.cs 页表类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace 操作系统实验3
{
//页表
class PageTable
{
int Physicsnum;
public int Physicsnum1
{
get { return Physicsnum; }
set { Physicsnum = value; }
}
int[] LogicIndex=new int[5];
public int[] LogicIndex1
{
get { return LogicIndex; }
set { LogicIndex = value; }
}
int[] PhysicsIndex=new int[5];
public int[] PhysicsIndex1
{
get { return PhysicsIndex; }
set { PhysicsIndex = value; }
}
public void setPhysicsIndex()
{
ArrayList list = new ArrayList();
System.Diagnostics.Debug.WriteLine(this.Physicsnum);
while(list.Count<5){
Random r = new Random();
int a = r.Next(0, Physicsnum);
if(list.Contains(a)!=true)
list.Add(a);
//System.Diagnostics.Debug.WriteLine(r.Next(0, 10));
}
for (int i = 0; i < 5; i++)
{
PhysicsIndex[i] = (int )list[i];
System.Diagnostics.Debug.WriteLine(list[i]);
}
}
public void setLogicIndex(Table t)
{
for (int i = 0; i < 5; i++)
{
LogicIndex[i] = t.Index[i];
}
}
public string print()
{
string s="页表已经建好\r\n";
for(int i=0;i<5;i++)
{
s+=LogicIndex[i]+" "+PhysicsIndex[i]+"\r\n";
}
return s;
}
public PageTable(int num)
{
this.Physicsnum = num;
}
}
}
- Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace 操作系统实验3
{
public partial class Form1 : Form
{
MBT mbt = new MBT();
Table t = null;
PageTable pt ;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
mbt.Num = Int16.Parse(textBox1.Text);
mbt.createList(Int16.Parse(textBox1.Text));
System.Diagnostics.Debug.WriteLine(mbt.PageList.Count);
richTextBox1.Text += mbt.print() ;
}
public void showText(Table t)
{
richTextBox1.Text += t.print();
}
private void button1_Click(object sender, EventArgs e)
{
int n = Int16.Parse(textBox2.Text);
for (int i = 0; i < n; i++)
{
Form2 f2 = new Form2(createTable);
f2.ShowDialog();
}
}
public void createTable(int a, int b, int c, int d, int e,string s)
{
Table t1 = new Table();
t1.Name = s;
t1.setIndex(a / 1024, b / 1024, c / 1024, d / 1024, e / 1024);
t1.setX(a % 1024, b % 1024, c % 1024, d % 1024, e % 1024);
showText(t1);
t = t1;
}
public void setPageTable()
{
pt = new PageTable(Int16.Parse(textBox1.Text));
pt.Physicsnum1 = Int16.Parse(textBox1.Text);
pt.setLogicIndex(t);
pt.setPhysicsIndex();
richTextBox1.Text += pt.print();
}
private void button3_Click(object sender, EventArgs e)
{
/*var runThread = new Thread(() =>
{*/
setPageTable();
//System.Diagnostics.Debug.WriteLine(mbt.PageList.Count);
richTextBox1.Text += mbt.addTable(pt);
/*});
runThread.Start();*/
}
private void button4_Click(object sender, EventArgs e)
{
int add = Int16.Parse(textBox3.Text);
int i=add/1024;
int j=add%1024;
int flag = 0;
richTextBox1.Text += "您输入的地址为" + add + "页码:" + i + "位移量:" + j+"\r\n";
for (int n = 0; n < 5; n++)
{
if (t.Index[n] == i)
{
richTextBox1.Text += "该页存在内存中\r\n";
Page p = mbt.PageList[n] as Page;
p.Timestamp++;
flag = 1;
richTextBox1.Text += mbt.print();
break;
}
}
if (flag == 0)
{
richTextBox1.Text += "该页不在内存中\r\n";
richTextBox1.Text += mbt.LRU(i);
richTextBox1.Text+= mbt.print();
}
}
}
}
- form2.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 操作系统实验3
{
public partial class Form2 : Form
{
public delegate void myDelegate(int a,int b,int c,int d,int e,string s);
private myDelegate mydel;
public Form2(myDelegate del)
{
mydel = del;
InitializeComponent();
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
int address1 = Int16.Parse(textBox1.Text);
int address2 = Int16.Parse(textBox2.Text);
int address3 = Int16.Parse(textBox3.Text);
int address4 = Int16.Parse(textBox4.Text);
int address5 = Int16.Parse(textBox5.Text);
this.mydel(address1,address2,address3,address4,address5,textBox6.Text);
this.Dispose();
}
}
}