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

目录

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#中的动态数组不在默认项目中给的命名空间里,若调用,需要引入下面所示的命名空间:

1 using System.Collections;
 1  bool checksame(int[] OriginalArray, ArrayList ManagedArray, int OriginalArrayIndex)
 2         {
 3             for (int i = 0; i < ManagedArray.Count; i++)
 4             {
 5                 if (Convert.ToInt32(ManagedArray[i]) == OriginalArray[OriginalArrayIndex])
 6                 {
 7                     return true;
 8                 }
 9             }
10             return false;
11         }

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

 1   private void FIFO(int[] OriginalArray)
 2         {
 3             int PageLength = OriginalArray.Length;
 4             int cursor = 0;
 5             for (int i = 0; i < OriginalArray.Length; i++)
 6             {
 7                 if (ManagedArray.Count < blockCount)
 8                 {
 9                     if (checksame(OriginalArray, ManagedArray, i) == false)
10                     {
11                         ManagedArray.Add(OriginalArray[i]);
12                     }
13
14                 }
15                 else
16                 {
17                     if (checksame(OriginalArray, ManagedArray, i) == false)
18                     {
19                         ManagedArray[cursor] = OriginalArray[i];
20                         cursor++;
21                         if (cursor >= blockCount)
22                         {
23                             cursor = 0;
24
25                         }
26                     }
27                 }
28
29               //[show the result code]
30
31             }
32         }

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

 1   private void LRU(int[] OriginalArray)
 2         {
 3             int PageLength = OriginalArray.Length;
 4             for (int i = 0; i < OriginalArray.Length; i++)
 5             {
 6                 if (ManagedArray.Count < blockCount)
 7                 {
 8                     if (checksame(OriginalArray, ManagedArray, i) == true)
 9                     {
10                         ManagedArray.Remove(OriginalArray[i]);
11                     }
12                     else { };
13                     ManagedArray.Add(OriginalArray[i]);
14                 }
15                 else
16                 {
17                     if (checksame(OriginalArray, ManagedArray, i) == false)
18                     {
19                         ManagedArray.RemoveAt(0);
20                     }
21                     else
22                     {
23                         ManagedArray.Remove(OriginalArray[i]);
24                     }
25                     ManagedArray.Add(OriginalArray[i]);
26                 }
27
28                //[show the result code]
29
30             }
31         }

05 最佳置换算法(OPT)

 1  private int getdistance(ArrayList ManagedArray, int[] OriginalArray, int OriginalIndex, int ManagedIndex)
 2         {
 3             int distance = 0;
 4
 5             if (OriginalIndex < OriginalArray.Length)
 6             {
 7                 for (int i = OriginalIndex; i < OriginalArray.Length; i++)
 8                 {
 9                     if (OriginalArray[i] == Convert.ToInt32(ManagedArray[ManagedIndex]))
10                     {
11                         distance = i - OriginalIndex;
12                         break;
13                     }
14                     else
15                     {
16                         distance = OriginalIndex + OriginalArray.Length + 999;
17                         // make Original[i]‘s distance max
18                     }
19                 }
20
21             }
22             return distance;
23         }
 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             }
时间: 2024-10-09 15:58:03

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

虚存管理页面置换算法 — FIFO和RUL算法模拟实现

本篇博文为追忆曾经写过的算法系列第一篇(20081021) 温故知新 目的: 为了解决内存容量有限与多作业运行的冲突,运用了虚拟存储技术,能从逻辑上对内存进行扩充,达到扩充内存的效果.分页存储管理是实现虚拟存储的一种方案.通过模拟算法的实验,加深理解,虚拟存储器的基本原理和方法. 要求: 1.请求分页的置换算法(FIFO && RUL算法实现):2.按给定的顺序列,输出页面调度过程包括命中 / 缺页,调入/调出:3.计算缺页率,频率. 说明: vp_list[N] //访问序列 bs[M]

关于C#中的动态数组ArrayList

在C#中,如果需要数组的长度和元素的个数随着程序的运行不断改变,就可以使用ArrayList类,该类是一个可以动态增减成员的数组. 二.ArrayList类与Array类的区别 ArrayList类实际上是Array类的优化版本. ArrayList只能定义一维数组,Arrays可以定义多维数组. ArrayList的下限始终为0,Array可以定义自己的下限. ArrayList的元素都是object类型的,因此需要进行装箱和拆箱操作,内存分配的代价很高,而Array的元素通常是特定类型的.

C#动态数组ArrayList和List&lt;T&gt;的比较

C#中一维动态数组(即列表)分ArrayList和List<T>两种,其容量可随着我们的需要自动进行扩充 一.ArrayList类(少用) ArrayList位于System.Collections命名空间中,所以我们在使用时,需要导入此命名空间 ArrayList里边的数据类型是object,它类似于向量,可以存储不同的数据类型在一个数组里边(转换为了object) 下面是ArrayList的声明: ArrayList list = new ArrayList(); //声明一个ArrayL

动态数组arraylist的使用

package com.vince.list; import java.util.ArrayList; public class ListDemo { public static void arraylist(){//动态数组 ArrayList list=new ArrayList(); list.add(10); list.add("小白"); list.add(true); //插入第几个元素 //list.add(1,34); //删除元素 //list.remove(0);

Java语言中反射动态代理接口的解释与演示

Java语言中反射动态代理接口的解释与演示 Java在JDK1.3的时候引入了动态代理机制.可以运用在框架编程与平台编程时候捕获事件.审核数据.日志等功能实现,首先看一下设计模式的UML图解: 当你调用一个接口API时候,实际实现类继承该接口,调用时候经过proxy实现. 在Java中动态代理实现的两个关键接口类与class类分别如下: java.lang.reflect.Proxy java.lang.reflect.InvocationHandler 我们下面就通过InvocationHan

C语言中函数返回数组

#include "stdio.h"/*int* set(int a,int *c){ int *b; b=malloc(sizeof(int)*3); c[0]=a; c[1]=1+a; c[2]=2+a; b[0]=13; b[1]=14; b[2]=15; return b;}*/char *set(void){ char *buf; buf=malloc(sizeof(char)*3);//创建内存区 buf[0]=0x30; buf[1]=0x31; buf[2]=0x32;

关于“C语言中的字符数组和字符串”一些需要注意的基础点

在C语言中,没有类似Java的String类对字符串的处理,字符串的包装可以采用字符数组. 先看字符数组: #include<stdio.h> void main() { char array[] = {'a','b','c'}; int str = sizeof(array)/sizeof(char); printf("%d",str); } 此时的输出结果为:3,即字符数组的长度为3. 下面我们用字符串初始化字符数组,代码如下. #include<stdio.h&

C++动态数组简单模拟二叉堆

//C++动态数组简单模拟二叉堆 #include<iostream> using namespace std; class BinaryHeap { private: int cap; //数组最大容量 int size; //当前元素个数 int* datas; //数组首地址 public: explicit BinaryHeap(int cap_) :cap(cap_), size(0) { datas = new int[cap]; } ~BinaryHeap(){ delete d

C语言中指针和数组

C语言数组与指针的那些事儿 在C语言中,要说到哪一部分最难搞,首当其冲就是指针,指针永远是个让人又爱又恨的东西,用好了可以事半功倍,用不好,就会有改不完的bug和通不完的宵.但是程序员一般都有一种迷之自信,总认为自己是天选之人,明知山有虎,偏向虎山行,直到最后用C的人都要被指针虐一遍. 指针 首先,明确一个概念,指针是什么,一旦提到这个老生常谈且富有争议性的话题,那真是1000个人有1000种看法. 在国内的很多教材中,给出的定义一般就是"指针就是地址",从初步理解指针的角度来说,这种