(待续)C#语言中的动态数组(ArrayList)模拟常用页面置换算法(FIFO、LRU、Optimal)

时间:2023-12-18 22:48:38

目录

00 简介

01 算法概述

02 公用方法与变量解释

03 先进先出置换算法(FIFO)

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

05 最佳置换算法(OPT)

00 简介

页面置换算法主要是记录内存的忙闲状态,为进程分配和释放内存。当主存的空间太小而无法装入所有的进程时,就需要在内存和硬盘之间进行调度操作。

多数操作系统只采用某种特定的页面置换算法进行置换,无法预先探测当前运行进程的页面访问模式,因此不能根据不同的页面访问模式,选用不同的页面置换算法。当然,如果能对不同的访问模式选取相应的页面置换算法,将提高操作系统的调度能力,进而提高整个系统的性能。

此处采用C#语言中的动态数组(ArrayList)进行对三种算法的模拟。

01 算法概述

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

最简单的页面置换算法是先入先出(FIFO)法。这种算法的实质是,总是选择在主存中停留时间最长(即最老)的一页置换,即先进入内存的页,先退出内存。理由是:最早调入内存的页,其不再被使用的可能性比刚调入内存的可能性大。建立一个FIFO队列,收容所有在内存中的页。被置换页面总是在队列头上进行。当一个页面被放入内存时,就把它插在队尾上。
这种算法只是在按线性顺序访问地址空间时才是理想的,否则效率不高。因为那些常被访问的页,往往在主存中也停留得最久,结果它们因变“老”而不得不被置换出去。
FIFO的另一个缺点是,它有一种异常现象,即在增加存储块的情况下,反而使缺页中断率增加了。当然,导致这种异常现象的页面走向实际上是很少见的。

2 最佳置换算法(OPT)

最优置换(Optimal Replacement)是在理论上提出的一种算法。其实质是:当调入新的一页而必须预先置换某个老页时,所选择的老页应是将来不再被使用,或者是在最远的将来才被访问。采用这种页面置换算法,保证有最少的缺页率。
但是最优页面置换算法的实现是困难的,因为它需要人们预先就知道一个进程整个运行过程中页面走向的全部情况。不过,这个算法可用来衡量(如通过模拟实验分析或理论分析)其他算法的优劣。

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

FIFO算法和OPT算法之间的主要差别是,FIFO算法利用页面进入内存后的时间长短作为置换依据,而OPT算法的依据是将来使用页面的时间。如果以最近的过去作为不久将来的近似,那么就可以把过去最长一段时间里不曾被使用的页面置换掉。它的实质是,当需要置换一页时,选择在最近一段时间里最久没有使用过的页面予以置换。这种算法就称为最久未使用算法(Least Recently Used,LRU)。
LRU算法是与每个页面最后使用的时间有关的。当必须置换一个页面时,LRU算法选择过去一段时间里最久未被使用的页面。
LRU算法是经常采用的页面置换算法,并被认为是相当好的,但是存在如何实现它的问题。LRU算法需要实际硬件的支持。其问题是怎么确定最后使用时间的顺序,对此有两种可行的办法:

(1)计数器。

最简单的情况是使每个页表项对应一个使用时间字段,并给CPU增加一个逻辑时钟或计数器。每次存储访问,该时钟都加1。每当访问一个页面时,时钟寄存器的内容就被复制到相应页表项的使用时间字段中。这样我们就可以始终保留着每个页面最后访问的“时间”。在置换页面时,选择该时间值最小的页面。这样做,不仅要查页表,而且当页表改变时(因CPU调度)要维护这个页表中的时间,还要考虑到时钟值溢出的问题。

(2)栈。

用一个栈保留页号。每当访问一个页面时,就把它从栈中取出放在栈顶上。这样一来,栈顶总是放有目前使用最多的页,而栈底放着目前最少使用的页。由于要从栈的中间移走一项,所以要用具有头尾指针的双向链连起来。在最坏的情况下,移走一页并把它放在栈顶上需要改动6个指针。每次修改都要有开销,但需要置换哪个页面却可直接得到,用不着查找,因为尾指针指向栈底,其中有被置换页。(此次模拟运用该方法)
因实现LRU算法必须有大量硬件支持,还需要一定的软件开销。所以实际实现的都是一种简单有效的LRU近似算法。
一种LRU近似算法是最近未使用算法(Not Recently Used,NUR)。它在存储分块表的每一表项中增加一个引用位,操作系统定期地将它们置为0。当某一页被访问时,由硬件将该位置1。过一段时间后,通过检查这些位可以确定哪些页使用过,哪些页自上次置0后还未使用过。就可把该位是0的页淘汰出去,因为在最近一段时间里它未被访问过。

02 公用方法与变量解释

C#中的动态数组不在默认项目中给的命名空间里,若调用,需要引入下面所示的命名空间:

 using System.Collections;

这是对下面的部分变量的解释。

 OriginalArray
//原始数组,静态数组,存放整个页面串
ManagedArray
//被管理数组,动态数组,模拟物理块/栈结构
index
//序列号,标记即将进入到物理块的元素所对应的序号
OriginalIndex
//同上

在三种算法的实现过程中,都涉及到把页面串中的元素放入物理块中,当物理块中存在与将放入物理块中的页面串内元素相同的元素时,FIFO算法和Optimal算法不对元素进行处理,LRU算法中(运用了栈的方法)把相同元素放在栈顶。否则做另外操作。对页面串和物理块中是否遇到相同元素判断用此方法。

01 方法:判断接下来要放入物理块中元素与物理块中现存元素是否相同。
02 方法需求:物理块/栈模拟数组,原页面串模拟数组,判断序号index。
03 执行过程:遍历物理块,如果物理块中元素与将要放入物理块元素相同,则返回true,遍历结束后证明不存在,返回false。
04 返回值:存在为true,不存在为false。

  bool checksame(int[] OriginalArray, ArrayList ManagedArray, int OriginalArrayIndex)
{
for (int i = ; i < ManagedArray.Count; i++)
{
if (Convert.ToInt32(ManagedArray[i]) == OriginalArray[OriginalArrayIndex])
{
return true;
}
}
return false;
}

03 先进先出置换算法(FIFO)

   private void FIFO(int[] OriginalArray)
{
int PageLength = OriginalArray.Length;
int cursor = ;
for (int i = ; i < OriginalArray.Length; i++)
{
if (ManagedArray.Count < blockCount)
{
if (checksame(OriginalArray, ManagedArray, i) == false)
{
ManagedArray.Add(OriginalArray[i]);
} }
else
{
if (checksame(OriginalArray, ManagedArray, i) == false)
{
ManagedArray[cursor] = OriginalArray[i];
cursor++;
if (cursor >= blockCount)
{
cursor = ; }
}
} //[show the result code] }
}

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

   private void LRU(int[] OriginalArray)
{
int PageLength = OriginalArray.Length;
for (int i = ; i < OriginalArray.Length; i++)
{
if (ManagedArray.Count < blockCount)
{
if (checksame(OriginalArray, ManagedArray, i) == true)
{
ManagedArray.Remove(OriginalArray[i]);
}
else { };
ManagedArray.Add(OriginalArray[i]);
}
else
{
if (checksame(OriginalArray, ManagedArray, i) == false)
{
ManagedArray.RemoveAt();
}
else
{
ManagedArray.Remove(OriginalArray[i]);
}
ManagedArray.Add(OriginalArray[i]);
} //[show the result code] }
}

05 最佳置换算法(OPT)

 1  private int getdistance(ArrayList ManagedArray, int[] OriginalArray, int OriginalIndex, int ManagedIndex)
{
int distance = ; if (OriginalIndex < OriginalArray.Length)
{
for (int i = OriginalIndex; i < OriginalArray.Length; i++)
{
if (OriginalArray[i] == Convert.ToInt32(ManagedArray[ManagedIndex]))
{
distance = i - OriginalIndex;
break;
}
else
{
distance = OriginalIndex + OriginalArray.Length + ;
// make Original[i]'s distance max
}
} }
return distance;
}
 1  private void OPT(int[] OriginalArray)
2 {
3 PageLength = OriginalArray.Length;
4
5 int[] distances = new int[blockCount];
6 for (int i = 0; i < distance.Length; i++)
7 {
8 distance[i] = 0;
9 }
10
11
12 for (int i = 0; i < OriginalArray.Length; i++)
13 {
14 if (ManagedArray.Count < blockCount)
15 {
16 if (checksame(OriginalArray, ManagedArray, i) == false)
17 {
18 ManagedArray.Add(OriginalArray[i]);
19 }
20
21 }
22 else
23 {
24 if (checksame(OriginalArray, ManagedArray, i) == false)
25 {
26
27 for (int k = 0; k < ManagedArray.Count; k++)
28 {
29 distances[k] = getdistance(ManagedArray, OriginalArray, i, k);
30 }
31
32
33 for (int m = 0; m < distances.Length; m++)
34 {
35 if (distances[m] == distances.Max())
36 {
37 ManagedArray[m] = OriginalArray[i];
38 break;
39
40 }
41 }
42 }
43
44
45 }
46
47 //[show the result code]
48 }