小谷围某高校OS实验:

Posted on 2022-05-06 13:51  阿妍  阅读(46)  评论(1编辑  收藏  举报

系统:Windows10

语言:JAVA

环境:Eclipse+JDK1.8

一、进程调度

1轮转法:

  简单轮转法

  可变时间片轮转法

2多级反馈队列调度算法

二、作业调度【给定】

  最短作业优先(SJF)

  响应比高者优先(HRN)

  先来先服务(FCFS)

三、存储管理【给定】

  首次适应算法

  最佳适应算法

 

 四、银行家算法

【自定义】

一、进程调度

0.PCB数据结构:

class PCB{
   private String name; // 进程名 private int arrivalTime; // 到达时间 private int serviceTime; // 服务时间 private int remainServiceTime; // 还需要服务的时间 private int finishTime; // 完成时间 private int wholeTime; // 周转时间 private double weightWholeTime; // 带权周转时间
}

1.轮转法:对于RR,最重要的是时间片的长度。轮转算法以一个时间片产生中断,当中断发生时,当前运行的程序置于就绪队列(队尾)中,然后基于FCFS选择下一个就绪作业运行。

RR算法实现的核心代码如下:

/**
     * RR 算法实现
     */
    public void RRAlgorithm() {
        mReadyQueue.add(mUnreachQueue.poll());
        Process currProcess = mReadyQueue.poll();
        // 第一个进程执行
        int currTime = executeProcess(currProcess, 0);

        while (!mReadyQueue.isEmpty() || !mUnreachQueue.isEmpty()) {
            // 把所有“到达时间”达到的进程加入运行队列头部
            while (!mUnreachQueue.isEmpty()) {
                if (mUnreachQueue.peek().getArrivalTime() <= currTime) {
                    mReadyQueue.add(mUnreachQueue.poll());
                } else {
                    break;
                }
            }

            if (currProcess.getRemainServiceTime() > 0)
                mReadyQueue.add(currProcess);
            // 运行队列不为空时
            if (!mReadyQueue.isEmpty()) {
                currProcess = mReadyQueue.poll();
                currTime = executeProcess(currProcess, currTime);
            } else {
                // 当前没有进程执行,但还有进程为到达,时间直接跳转到到达时间
                currTime = mUnreachQueue.peek().getArrivalTime();
            }
        }
    }

    private int executeProcess(Process currProcess, int currTime) {
        if (currProcess.getRemainServiceTime() - mTimeSlice <= 0) {
            // 当前进程在这个时间片内能执行完毕
            showExecuteMessage(currTime, currTime += currProcess.getRemainServiceTime(), currProcess.getName());
            currProcess.setFinishTime(currTime);
            currProcess.setRemainServiceTime(0);
            // 对周转时间等进行计算
            calculeteWholeTime(currProcess);
            calculateWeightWholeTime(currProcess);
            mTotalWholeTime += currProcess.getWholeTime();
            mTotalWeightWholeTime += currProcess.getWeightWholeTime();
            mExecutedQueue.add(currProcess);
        } else {
            // 不能执行完毕
            showExecuteMessage(currTime, currTime += mTimeSlice, currProcess.getName());
            currProcess.setRemainServiceTime(currProcess.getRemainServiceTime() - mTimeSlice);
        }
        return currTime;
    }

简单轮转法即为时间片slice=1;可变时间片轮转法即为自定义slice。

2.多级反馈队列调度算法:

本算法设置了三个优先级从高到低的队列,时间片长度可自定义。

算法思路:首次加入的进程入最高优先级队列尾等待;某队列内时间片完而进程还没结束就立即调入次级优先级队列尾等待继续运行;只要有进程进入高优先级队列内,便对低优先级队列中的进程进行抢占式运行;

       每一秒对每个队列内的进程具有的进程标识符、到达时间、运行时间、仍需运行时间(方便显示)等属性进行更新和输出,以此模拟实际操作系统的调度状态。

核心代码如下:

        /*当有进程未运行时或进程队列不为空时,以每1时间片为单位*/
        while(num < proNum || !firstQueue.isEmpty() || !secondQueue.isEmpty() || !thirdQueue.isEmpty()){
            /*当前时刻有进程到达,则添加入第一队列*/
            while(num < proNum && pro[num].reachTime == currentTime)
                firstQueue.offer(pro[num++]);
            //打印上一秒各队列进程状态
            viewMenu(currentTime);
            /*当前为队列1在运行进程*/
            if(!firstQueue.isEmpty()){
                if (secondQueue.peek() != null) secondQueue.peek().state = 'R';
                if (thirdQueue.peek() != null) thirdQueue.peek().state = 'R';
                //仍需时间:-1
                firstQueue.peek().needTime -= 1;
                //CPU剩余时间片:-1
                firstTime -= 1;
                //更新当前时间:+1
                currentTime++;
                //进程正在运行,状态:E.
                if(firstQueue.peek().needTime > 0){
                    firstQueue.peek().state = 'E';
                    //当前队列CPU时间片用完而进程仍未运行完时,进程出队,入次优先级队尾
                    if(firstTime == 0) {
                        firstQueue.peek().state = 'R';
                        secondQueue.offer(firstQueue.poll());
                        firstTime = firstCpu;
                    }

                }
                //进程运行完毕,状态:F,记录完成时刻并出队
                else if(firstQueue.peek().needTime == 0){
                    firstQueue.peek().state = 'F';
                    System.out.printf("\n当前时刻:%d,此进程运行结束:\n",currentTime);
                    System.out.println(firstQueue.peek());
                    Objects.requireNonNull(firstQueue.poll());
                    firstTime = firstCpu;
                }
            }
            /*当前为队列2在运行进程*/
            else if(!secondQueue.isEmpty()){
                if (thirdQueue.peek() != null) thirdQueue.peek().state = 'R';
                //仍需时间:-1
                secondQueue.peek().needTime -= 1;
                //CPU剩余时间片:-1
                secondTime -= 1;
                //更新当前时间:+1
                currentTime++;

                //进程运行完毕,状态:F,记录完成时刻并出队
                if(secondQueue.peek().needTime == 0){
                    secondTime = secondCpu;
                    secondQueue.peek().state = 'F';
                    System.out.printf("\n当前时刻:%d,此进程运行结束:\n",currentTime);
                    System.out.println(secondQueue.peek());
                    Objects.requireNonNull(secondQueue.poll());
                }
                //进程正在运行,状态:E.
                else if(secondQueue.peek().needTime > 0){
                    secondQueue.peek().state = 'E';
                    //当前队列CPU时间片用完而进程仍未运行完时,进程出队,入次优先级队尾
                    if(secondTime == 0) {
                        secondQueue.peek().state = 'R';
                        thirdQueue.offer(secondQueue.poll());
                        secondTime = secondCpu;
                    }
                }
            }
            /*当前为队列3在运行进程*/
            else if(!thirdQueue.isEmpty()){
                //仍需时间:-1
                thirdQueue.peek().needTime -= 1;
                //CPU剩余时间片:-1
                thirdTime -= 1;
                //更新当前时间:+1
                currentTime++;

                //进程正在运行,状态:R.
                if(thirdQueue.peek().needTime > 0){
                    thirdQueue.peek().state = 'E';
                    //当前队列CPU时间片用完而进程仍未运行完时,进程出队,入次优先级队尾
                    if(thirdTime == 0) {
                        thirdQueue.peek().state = 'R';
                        thirdQueue.offer(thirdQueue.poll());
                        thirdTime = thirdCpu;
                    }
                }
                //进程运行完毕,状态:F,记录完成时刻并出队
                else{
                    firstTime = firstCpu;
                    thirdQueue.peek().state = 'F';
                    System.out.printf("\n当前时刻:%d,此进程运行结束:\n",currentTime);
                    System.out.println(thirdQueue.peek());
                    Objects.requireNonNull(thirdQueue.poll());
                }
            }
        }

二、作业调度

1.最短作业优先(SJF):举个例子,假设有以下 4 个进程,其 CPU 执行时间以 ms 计:

进程到达时间执行时间
P1 0 8
P2 1 4
P3 2 9
P4 3 5


进程 P1 在时间 0 开始,因为这时只有进程 P1。进程 P2 在时间 1 到达。进程 P1 剩余时间(7ms)大于进程 P2 需要的时间(4ms),因此进程 P1 被抢占,而进程 P2 被调度。

2.响应比高者优先(HRN):HRN调度策略同时考虑每个作业的等待时间长短和估计需要的执行时间长短,从中选出响应比最高的作业投入执行。

3.先来先服务(FCFS)