【南邮操作系统实验】页面置换算法(FIFO、LRU、OPT)图形化界面(JavaFx)

页面置换算法图形化界面

前言

其实以前操作系统实验的时候我写过了三份了:(命令行)
页面置换算法 (FIFO、LRU、OPT)Java 版
页面置换算法(FIFO、LRU、OPT) Python 版
页面置换算法(FIFO、LRU、OPT) C++ 版

这次的实验周女朋友恰好是这个题目,我就厚颜无耻的把以前自己的代码拿过来了(我抄我自己),但是什么都不做也不太好,就用 JavaFx 搭了个图形化界面(赤裸裸的摸鱼啊!)。。不过还发现以前的一些小问题,比如以前页框里的初值都是 0,应该用 null。

大致就长下面这样。。。

运行效果

在这里插入图片描述在这里插入图片描述

源码

目录是这样的。
在这里插入图片描述
友情提示:虽然是图形化界面的,但是 FIFO、LRU、OPT 这三个文件单独运行也是可以的。

FIFO

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);
    }

}

LRU

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);
    }

}

OPT

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);
    }

}

FXML界面

console.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.Cursor?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<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);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43734095/article/details/106146844
今日推荐