其实以前操作系统实验的时候我写过了三份了:(命令行)
页面置换算法 (FIFO、LRU、OPT)Java 版
页面置换算法(FIFO、LRU、OPT) Python 版
页面置换算法(FIFO、LRU、OPT) C++ 版
这次的实验周女朋友恰好是这个题目,我就厚颜无耻的把以前自己的代码拿过来了(我抄我自己),但是什么都不做也不太好,就用 JavaFx 搭了个图形化界面(赤裸裸的摸鱼啊!)。。不过还发现以前的一些小问题,比如以前页框里的初值都是 0,应该用 null。
大致就长下面这样。。。
目录是这样的。
友情提示:虽然是图形化界面的,但是 FIFO、LRU、OPT 这三个文件单独运行也是可以的。
package com.yusael.pagereplace;
import java.util.Stack;
public class FIFO {
public int frameNum; // 分配给该作业的物理页框数
public Integer[] pageFrame; // 物理页框
public int pageNum; // 作业的页面走向总次数
public Integer[] page; // 作业的页面走向
public Stack<Integer> stack = new Stack<>(); // 存放淘汰页面的栈
public int pageMissNum = 0; // 缺页次数
public String fifoRun(int frameNum, String inputPages) {
// Scanner scanner = new Scanner(System.in);
// System.out.print("请输入分配给该作业的物理页框块数:");
// this.frameNum = scanner.nextInt(); // 物理页框数
this.frameNum = frameNum; // 物理页框数
// System.out.print("请输入该作业的页面走向:");
// scanner.nextLine(); // 控制输入格式
// String inputPages = scanner.nextLine();
String[] split = inputPages.split("\\s+|,\\s+|,\\s+|,");
this.pageNum = split.length; // 作业的页面走向总次数
page = new Integer[pageNum]; // 作业的页面走向
for (int i = 0; i < pageNum; i++) {
this.page[i] = Integer.parseInt(split[i]);
}
pageFrame = new Integer[frameNum]; // 物理页框
StringBuilder sb = new StringBuilder();
int count = 0;
int helpNum = 0; // 实现 FIFO 算法
while (count < pageNum) {
// System.out.println("第" + (count+1) + "次:");
sb.append("【第" + (count + 1) + "次】\n");
boolean isMiss = true; // 判断本次是否缺页
boolean isEmpty = true; // 判断物理页框中是否有空位
boolean isExist = false; // 判断物理页框中是否存在本次页面走向
// 判断物理页框中是否已经存在本次页面走向
for (int i = 0; i < frameNum; i++) {
if (page[count] == pageFrame[i]) {
isExist = true;
break;
}
}
// 若本次页面走向,物理页框中已存在,则直接进入下次页面走向
if (isExist == true){
// System.out.println("本次页面走向,页框中已经存在!");
// System.out.print("目前物理页框中页面走向为:");
sb.append("本次页面走向,页框中已经存在!\n");
sb.append("目前物理页框中页面走向为:");
for (Integer i : pageFrame) {
// System.out.print(i + " ");
sb.append(i + " ");
}
sb.append("\n---------------------------------------\n");
count++;
continue;
}
// 判断物理页框有无空位
for (int i = 0 ; i < frameNum ; i++){
if (pageFrame[i] == null){
isEmpty = true;
break;
}else{
isEmpty = false;
}
}
// 本次页面走向,物理页框中不存在,且有空位,按顺序放入
if (isExist == false && isEmpty == true){
for (int i = 0; i < frameNum; i++) {
if (pageFrame[i] == null) { // 物理页框中有空位则放入
pageFrame[i] = page[count];
break; // 从头开始找,找到一个空位即可
}
}
}
// 实现 FIFO 算法
// 本次页面走向,物理页框中不存在,且物理页框中没有空位了
if (isExist == false && isEmpty == false){
// 此时的 pageFrame[helpNum%frameNum] 为淘汰页面
stack.push(pageFrame[helpNum%frameNum]); // 淘汰页面入栈
// System.out.println("本次淘汰页面:" + pageFrame[helpNum%frameNum]);
sb.append("本次淘汰页面:" + pageFrame[helpNum%frameNum] + "\n");
pageFrame[helpNum%frameNum] = page[count]; // 先进先出
helpNum++;
}
if (isMiss == true){ // 计算缺页次数
pageMissNum++;
}
// System.out.print("目前物理页框中页面走向为:");
sb.append("目前物理页框中页面走向为:");
for (Integer i : pageFrame) {
// System.out.print(i + " ");
sb.append(i + " ");
}
// System.out.println();
sb.append("\n---------------------------------------\n");
count++;
}
// System.out.println();
sb.append("\n");
System.out.println("缺页次数:" + pageMissNum + "次");
System.out.println("一共调用: " + pageNum + "次");
System.out.println("缺页中断率:" + pageMissNum*1.0/pageNum*100 + "%" );
System.out.print("淘汰页面:");
for (Integer integer : stack) {
System.out.print(integer + " ");
}
return sb.toString();
}
public static void main(String[] args) {
FIFO fifo = new FIFO();
String s = fifo.fifoRun(3, "2 3 2 1 5 2 4 5 3 2 5 2");
System.out.println(s);
}
}
package com.yusael.pagereplace;
import java.util.Stack;
public class LRU {
public int frameNum; // 分配给该作业的物理页框数
public Integer[] pageFrame; // 物理页框
public int pageNum; // 作业的页面走向总次数
public Integer[] pages; // 作业的页面走向
public Stack<Integer> stack = new Stack<>(); // 存放淘汰页面的栈
public int pageMissNum = 0; // 缺页次数
public String lruRun(int frameNum, String inputPages) {
this.frameNum = frameNum; // 物理页框数
String[] split = inputPages.split("\\s+|,\\s+|,\\s+|,");
this.pageNum = split.length; // 作业的页面走向总次数
pages = new Integer[pageNum]; // 作业的页面走向
for (int i = 0; i < pageNum; i++) {
this.pages[i] = Integer.parseInt(split[i]);
}
pageFrame = new Integer[frameNum]; // 物理页框
StringBuilder sb = new StringBuilder();
int count = 0;
while (count < pageNum) {
sb.append("【第" + (count + 1) + "次】\n");
boolean isMiss = true; // 判断本次是否缺页
boolean isEmpty = true; // 判断物理页框中是否有空位
boolean isExist = false; // 判断物理页框中是否存在本次页面走向
// 判断物理页框中是否已经存在本次页面走向
for (int i = 0; i < frameNum; i++) {
if (pages[count] == pageFrame[i]) {
isExist = true;
break;
}
}
// 若本次页面走向,物理页框中已存在,则直接进入下次页面走向
if (isExist == true){
sb.append("本次页面走向,页框中已经存在!\n");
sb.append("目前物理页框中页面走向为:");
for (Integer i : pageFrame) {
sb.append(i + " ");
}
sb.append("\n---------------------------------------\n");
count++;
continue;
}
// 判断物理页框有无空位
for (int i = 0 ; i < frameNum ; i++){
if (pageFrame[i] == null){
isEmpty = true;
break;
}else{
isEmpty = false;
}
}
// 本次页面走向,物理页框中不存在,且有空位,按顺序放入
if (isExist == false && isEmpty == true){
for (int i = 0; i < frameNum; i++) {
if (pageFrame[i] == null) { // 物理页框中有空位则放入
pageFrame[i] = pages[count];
break; // 从头开始找,找到一个空位即可
}
}
}
// 本次页面走向,物理页框中不存在,且物理页框中没有空位了
// 实现 LRU 算法
if (!isExist && !isEmpty){
for (int i = 0 ; i < frameNum ; i++){
if (pages[count-frameNum] == pageFrame[i]){
stack.push(pageFrame[i]); // 淘汰页面入栈
pageFrame[i] = pages[count];
}
}
}
if (isMiss == true){ // 计算缺页次数
pageMissNum++;
}
sb.append("目前物理页框中页面走向为:");
for (Integer i : pageFrame) {
sb.append(i + " ");
}
sb.append("\n---------------------------------------\n");
count++;
}
sb.append("\n");
return sb.toString();
/* System.out.println("缺页次数:" + pageMissNum + "次");
System.out.println("一共调用: " + pageNum + "次");
System.out.println("缺页中断率:" + pageMissNum*1.0/pageNum*100 + "%" );
System.out.print("淘汰页面:");
for (Integer integer : stack) {
System.out.print(integer + " ");
}*/
}
public static void main(String[] args) {
LRU lru = new LRU();
String s = lru.lruRun(3, "2 3 2 1 5 2 4 5 3 2 5 2");
System.out.println(s);
}
}
package com.yusael.pagereplace;
import java.util.Stack;
public class OPT {
public int frameNum; // 分配给该作业的物理页框数
public Integer[] pageFrame; // 物理页框
public int pageNum; // 作业的页面走向总次数
public Integer[] pages; // 作业的页面走向
public Stack<Integer> stack = new Stack<>(); // 存放淘汰页面的栈
public int pageMissNum = 0; // 缺页次数
public String optRun(int frameNum, String inputPages) {
this.frameNum = frameNum; // 物理页框数
String[] split = inputPages.split("\\s+|,\\s+|,\\s+|,");
this.pageNum = split.length; // 作业的页面走向总次数
pages = new Integer[pageNum]; // 作业的页面走向
for (int i = 0; i < pageNum; i++) {
this.pages[i] = Integer.parseInt(split[i]);
}
pageFrame = new Integer[frameNum]; // 物理页框
StringBuilder sb = new StringBuilder();
int count = 0;
while (count < pageNum) {
sb.append("【第" + (count + 1) + "次】\n");
boolean isMiss = true; // 判断本次是否缺页
boolean isEmpty = true; // 判断物理页框中是否有空位
boolean isExist = false; // 判断物理页框中是否存在本次页面走向
// 判断物理页框中是否已经存在本次页面走向
for (int i = 0; i < this.frameNum; i++) {
if (pages[count] == pageFrame[i]) {
isExist = true;
break;
}
}
// 若本次页面走向,物理页框中已存在,则直接进入下次页面走向
if (isExist == true){
sb.append("本次页面走向,页框中已经存在!\n");
sb.append("目前物理页框中页面走向为:");
for (Integer i : pageFrame) {
sb.append(i + " ");
}
sb.append("\n---------------------------------------\n");
count++;
continue;
}
// 判断物理页框有无空位
for (int i = 0; i < this.frameNum; i++){
if (pageFrame[i] == null){
isEmpty = true;
break;
}else{
isEmpty = false;
}
}
// 本次页面走向,物理页框中不存在,且有空位,按顺序放入
if (isExist == false && isEmpty == true){
for (int i = 0; i < this.frameNum; i++) {
if (pageFrame[i] == null) { // 物理页框中有空位则放入
pageFrame[i] = pages[count];
break; // 从头开始找,找到一个空位即可
}
}
}
// 本次页面走向,物理页框中不存在,且物理页框中没有空位了
// 实现 OPT 算法
if (isExist == false && isEmpty == false){
boolean isExistEle = false; // 是否存在未来不再出现的元素
boolean isFound = false; // 是否找到未来下标的元素
int frameIndex = 0; // 记录的物理页框下标
Stack<Integer> helpStack = new Stack<>(); // 辅助栈
// 寻找将来不再出现的,存在于当前物理页框中的元素
for (int i = 0; i < this.frameNum; i++){
for (int j = count; j < pageNum; j++){
if (pageFrame[i] == pages[j]){ // 若当前物理页框中,不存在未来不再出现的元素
helpStack.push(j); // 记录当前未来将遇见的下标
isFound = true; // 找到未来下标的元素
}
}
// 当前物理页框中,存在未来不再出现的元素
if (!isFound){
frameIndex = i; // 记录当前物理页框
isExistEle = true; // 存在未来不再出现的元素
break;
}
isFound = false;
}
/*for (Integer integer : helpStack) {
System.out.println(integer);
}
System.out.println("TEST " + frameIndex);
System.out.println("isExistEle " + isExistEle);
System.out.println("isFound " + isFound);*/
if(isExistEle){ // 存在未来不再出现的元素
stack.push(pageFrame[frameIndex]); // 淘汰页面入栈
pageFrame[frameIndex] = pages[count];
}else{ // 不存在未来不再出的元素
int t = 0;
for (Integer integer : helpStack) {
if(t < integer){
t = integer;
}
}
for (int i = 0; i < this.frameNum; i++){
if (pageFrame[i] == pages[t]){
stack.push(pageFrame[i]); // 淘汰页面入栈
pageFrame[i] = pages[count];
}
}
}
}
if (isMiss == true){ // 计算缺页次数
pageMissNum++;
}
sb.append("目前物理页框中页面走向为:");
for (Integer i : pageFrame) {
sb.append(i + " ");
}
sb.append("\n---------------------------------------\n");
count++;
}
sb.append("\n");
return sb.toString();
}
public static void main(String[] args) {
OPT opt = new OPT();
String s = opt.optRun(3, "2 3 2 1 5 2 4 5 3 2 5 2");
System.out.println(s);
}
}
console.fxml:
<AnchorPane blendMode="MULTIPLY" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" pickOnBounds="false" prefHeight="350.0" prefWidth="700.0" stylesheets="@console.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.yusael.controller.Controller">
<children>
<SplitPane dividerPositions="0.4475806451612903" prefHeight="350.0" prefWidth="700.0" style="-fx-background-color: lightskyblue" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="398.0" prefWidth="283.0">
<children>
<Text layoutX="18.0" layoutY="62.0" strokeType="OUTSIDE" strokeWidth="0.0" text="作业的物理页框块数:">
<font>
<Font name="System Bold" size="18.0" />
font>
Text>
<Text layoutX="21.0" layoutY="118.0" strokeType="OUTSIDE" strokeWidth="0.0" text="作业的页面走向:">
<font>
<Font name="System Bold" size="18.0" />
font>
Text>
<TextField fx:id="frameNum" layoutX="198.0" layoutY="40.0" opacity="0.8" prefHeight="30.0" prefWidth="66.0" style="-fx-background-color: deepskyblue" />
<Button layoutX="40.0" layoutY="282.0" mnemonicParsing="false" onAction="#fifo" text="FIFO" />
<Button layoutX="123.0" layoutY="282.0" mnemonicParsing="false" onAction="#lru" text="LRU" />
<Button layoutX="205.0" layoutY="282.0" mnemonicParsing="false" onAction="#opt" text="OPT" />
<TextArea fx:id="inputPages" layoutX="23.0" layoutY="139.0" opacity="0.8" prefHeight="110.0" prefWidth="247.0" style="-fx-background-color: deepskyblue" wrapText="true" />
children>
AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<TextArea fx:id="outputText" editable="false" layoutX="22.0" layoutY="17.0" opacity="0.8" prefHeight="237.0" prefWidth="344.0" style="-fx-background-color: deepskyblue" wrapText="true" />
<Label fx:id="loseCount" layoutX="21.0" layoutY="269.0" text="缺页次数:">
<cursor>
<Cursor fx:constant="HAND" />
cursor>
Label>
<Label fx:id="callCount" layoutX="126.0" layoutY="269.0" text="一共调用:">
<cursor>
<Cursor fx:constant="HAND" />
cursor>
Label>
<Label fx:id="interupt" layoutX="242.0" layoutY="269.0" text="缺页中断率:">
<cursor>
<Cursor fx:constant="HAND" />
cursor>
Label>
<Label fx:id="ggPages" layoutX="22.0" layoutY="286.0" prefHeight="63.0" prefWidth="356.0" text="淘汰页面:" wrapText="true">
<cursor>
<Cursor fx:constant="HAND" />
cursor>
Label>
children>
AnchorPane>
items>
SplitPane>
children>
AnchorPane>
Controller.java:
package com.yusael.controller;
import com.yusael.pagereplace.FIFO;
import com.yusael.pagereplace.LRU;
import com.yusael.pagereplace.OPT;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
@FXML
private TextField frameNum;
@FXML
private TextArea inputPages;
@FXML
private TextArea outputText;
@FXML
private Label loseCount;
@FXML
private Label callCount;
@FXML
private Label interupt;
@FXML
private Label ggPages;
@FXML
private ImageView imView;
public void fifo() {
if (checkLegal(frameNum.getText(), inputPages.getText())) return;
FIFO fifo = new FIFO();
String res = fifo.fifoRun(Integer.parseInt(frameNum.getText()), inputPages.getText());
outputText.setText(res);
loseCount.setText("缺页次数:" + fifo.pageMissNum);
callCount.setText("一共调用:" + fifo.pageNum);
interupt.setText("缺页中断率:" + fifo.pageMissNum * 1.0 / fifo.pageNum * 100 + "%");
StringBuilder sb = new StringBuilder();
for (Integer integer : fifo.stack) {
sb.append(integer + " ");
}
ggPages.setText("淘汰页面:" + sb.toString());
}
public void lru() {
if (checkLegal(frameNum.getText(), inputPages.getText())) return;
LRU lru = new LRU();
String res = lru.lruRun(Integer.parseInt(frameNum.getText()), inputPages.getText());
outputText.setText(res);
loseCount.setText("缺页次数:" + lru.pageMissNum);
callCount.setText("一共调用:" + lru.pageNum);
interupt.setText("缺页中断率:" + lru.pageMissNum * 1.0 / lru.pageNum * 100 + "%");
StringBuilder sb = new StringBuilder();
for (Integer integer : lru.stack) {
sb.append(integer + " ");
}
ggPages.setText("淘汰页面:" + sb.toString());
}
public void opt() {
if (checkLegal(frameNum.getText(), inputPages.getText())) return;
OPT opt = new OPT();
String res = opt.optRun(Integer.parseInt(frameNum.getText()), inputPages.getText());
outputText.setText(res);
loseCount.setText("缺页次数:" + opt.pageMissNum);
callCount.setText("一共调用:" + opt.pageNum);
interupt.setText("缺页中断率:" + opt.pageMissNum * 1.0 / opt.pageNum * 100 + "%");
StringBuilder sb = new StringBuilder();
for (Integer integer : opt.stack) {
sb.append(integer + " ");
}
ggPages.setText("淘汰页面:" + sb.toString());
}
private boolean checkLegal(String... texts) {
for (String s : texts) {
if (s == null || s.equals("")) {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Warning Dialog");
alert.setHeaderText(null);
alert.setContentText("请输入正确的数据!");
alert.showAndWait();
return true;
}
}
return false;
}
@Override
public void initialize(URL location, ResourceBundle resources) {
}
}
package com.yusael;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("console.fxml"));
primaryStage.setTitle("页面调度算法模拟");
Scene scene = new Scene(root, 700, 350);
scene.getStylesheets().add(getClass().getResource("console.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}