1,前言
有关LRU页面置换的学习记录
若有不当之处,请您指出,您的指点是我的荣幸
2,LRU
LRU页面置换,也称为最近最少使用算法
每个进程运行时会被分配一定数量的帧,这是进程所占有的空间。
程序的代码一般是存于外存(一般理解为磁盘)中
执行代码的时候,只有当代码所在的页被操作系统从外存调入内存,并放置在进程所占有的空间中,代码才能执行
而进程逻辑上占有的页数是远远大于分配到的帧数的(页是逻辑概念上的,帧是物理概念上的)
就比如:
- 进程A逻辑上占有的页数为20页,但执行的时候分配到的帧数只有3帧(对应逻辑概念上的3页)
- 就比如此时进程分配到的3帧中存的是:页码为3的页,页码为4的页,页码为5的页
- 而此时进程需要执行的代码位于页码为10的页上,但是操作系统的分配的帧都用完了(不能在操作系统分配的空间之外执行代码!)
- 这时候就需要页面置换的介入
这里记录的是LRU页面置换算法的代码实现!
而LRU算法有两种实现方法–基于CPU计数器和基于堆栈
2.1,代码实现
import java.util.ArrayList;
import java.util.Scanner;
/**
* LRU页面置换算法
* <p>
* 使用计数器
*/
public class LRU {
//表示CPU中计数器
public static int count = 0;
public static void main(String[] args) {
//定义一个进程数组
ArrayList<Node> progress = new ArrayList<>();
//定义进程数量
int pNum = 0;
//定义帧数组
Node[] frame;
//帧数组中是否有相同的页面
int result = 0;
//帧数组中count值最小的元素的下标
int minIndex = 0;
//记录缺页错误发生的次数
int pageFault=0;
Scanner sc = new Scanner(System.in);
System.out.println("请输入进程所需调用的页的数量");
pNum = sc.nextInt();
System.out.println("请输入每个进程分配到的帧的数量");
//定义每个进程分配到的帧数是多少
frame = new Node[sc.nextInt()];
//初始化frame数组,防止在pSame处报空指针异常
for (int n = 0; n < frame.length; n++) {
frame[n] = new Node(-2);
}
System.out.println("请输入页码序列(页码>=0)");
//请输入进程所需的页码序列!
for (int i = 0; i < pNum; i++) {
progress.add(new Node(sc.nextInt()));
}
//LRU页面置换主体
//遍历整个进程数组
for (int c = 0; c < progress.size(); c++) {
//如果帧数组中已经有了相同的页面,那么就不用置换了,拿到其下标,更新计数器即可!
result = pSame(frame, progress.get(c).value);
if (result != -1) {
//如果有相同的页面
//1,先让CPU计数器自增
count++;
//2,把页面加入帧数组之中,并将其计数器更新为最新
frame[result].pCount = count;
} else if (result==-1){
pageFault++;
//如果没有相同的页面
count++;
//找到帧数组中计数器最小的页面,并返回其下标!
minIndex = pMin(frame);
//把新进来的页面赋给frame数组中计数器最小的那一页!
frame[minIndex] = progress.get(c);
//更新其计数器为最新!
frame[minIndex].pCount = count;
}
}
System.out.println("进程虚拟空间所存的页码为:");
for (Node node : frame) {
System.out.println(node.value);
}
System.out.println("缺页错误发生的次数:"+pageFault);
}
//查找frame中是否已经有了同一页
static int pSame(Node[] frame, int value) {
for (int i = 0; i < frame.length; i++) {
//如果有了同一页,那么久返回那一页的下标!
if (frame[i].value == value) {
return i;
}
}
//如果没有同一页,就返回-1
return -1;
}
//找到数组中计数器最小的那个元素,并返回其下标!
static int pMin(Node[] frame) {
int index = 0;
Node temp=frame[0];
for (int i = 0; i < frame.length - 1; i++) {
if (temp.pCount >= frame[i + 1].pCount) {
temp=frame[i+1];
index=i+1;
}
}
//返回计数器最小的下标!
return index;
}
}
//表示每一页,每一页由页码(value)和计数器(count)组成
class Node {
int value;
int pCount;
public Node(int value) {
this.value = value;
pCount = 0;
}
}