操作系统:进程调度算法详解之FCFS和SPF篇

原创 2015年11月20日 08:55:56

前言:

  在学习操作系统的时候,总是可以听到一些与“调度”相关的东西。记得刚学计算机操作系统的时候,总是觉得调试是一个很高大上的东西,不敢太深入地去接触。这可能是因为学生时代的我在算法方面并不强,而这些调度过程又常以算法的形式出现在课本上。本身上这确实是一些算法。我对这些算法有一些抗拒,可能当时是被DotA给迷惑了吧。现在倒真是感觉算法是一个迷人的东西,有时在没有学到某一种算法,自己也可以在已有的一些算法思维的基础上想出个一二来,这让人很爽。

  本文也是我在温习《计算机操作系统》这本书时候,想着来用代码的形式来描述这些迷人的东西。

概述:

  我们在编码开发的时候,就是在跟进程打交道。不过,可能由于一些高级语言的封装,我们在开发的过程可能感觉不到我们的代码对进程的创建或调用过程。当然,这也不是本文的重点。但是,操作系统却不能不理会进程。下面我就使用Java开发语言来模拟一下进程在操作系统中的调度过程。


本文链接:http://blog.csdn.net/lemon_tree12138/article/details/49927033 -- Coding-Naga
                                                                 --转载请注明出处


进程调度算法:

1.FCFS:

  FCFS的意思是先来先服务(First Come First Service)。顾名思义就是按照进程被添加到等待队列的先后顺序来进行调用的。这里可以先来看一张FCFS的算法过程图:


图-1 进程FCFS调度过程

  从上面的过程图中就可以清楚地知道,进程在整个过程被调度的顺序及过程。

  不过,不知道读者有没有注意到一个问题,那就是上面的图中,我们是让进程(矩形)紧紧挨着的。那么有没有什么情况是让这些矩形不在一起紧挨着呢?如果你是一个注意细节的人,我想你已经注意到了这一点吧。说到这里,我想问另一个问题,如果当我们的队列中的进程都运行完成,而等待队列中已经没有进程了,那么这个时候要怎么处理?在这种情况下CPU一直是处于空闲的状态,直到等待队列中出现了一个进程请求处理机来运行。所以,在模拟程序里我们就可以直接让时间跳过这一段。

  关于上面的一点,在我们的代码里也要考虑到。关键的步骤如下:

<pre name="code" class="java">@Override
    public int execute(ProcessModel... processList) {
        if (processList == null || processList.length == 0) {
            System.out.println(TAG + ">数据为空");
            return -1;
        }

        if (!(processList instanceof ProcessFCFSModel[])) {
            System.out.println(TAG + ">数据类型出错");
            return -2;
        }

        ProcessFCFSModel[] fcfsModels = (ProcessFCFSModel[])processList;
        int runTimeSum = 0;
        for (ProcessFCFSModel model : fcfsModels) {
            if (runTimeSum < model.getComingTime()) {
                runTimeSum = (int)model.getComingTime();
            }

            model.setStartRunTime(runTimeSum);
            runTimeSum += model.getRunTime();
            model.setFinishTime(runTimeSum);
            model.setTurnaroundTime(runTimeSum - model.getComingTime());
            model.setTurnaroundWeightTime(1.0 * model.getTurnaroundTime() / model.getRunTime());
        }

        return runTimeSum;
    }

2.SPF:

  SPF的意思是短进程优先(Short Process First)。意思也很清楚,就是让短的进程先运行,是什么短呢?这里说的是进程的运行时间。不要误以为系统好牛逼,带进程要运行多长时间都可以提前知道。其实,这个值是程序提前写在进程里面的了,系统只要去读取这个值就可以了。

  这里同样也为SPF算法画了一个过程图。其实这两个算法在过程图没有太大的出入,不过在代码差别还不小。见图-2。

图-2 进程SPF调度过程

  可以很明显地看到这里的进程B与左边的进程队列有一些分离的感觉,并且在进程B的上方还有“最短运行时间”的描述。的确,这里的B是在运行过程中选出运行时间最短的进程。

  你不会要问我为什么不事先给这个等待的进程队列进行排序吧。如果是事先对队列进行排序,在“排序”这个操作上时间复杂度的确可以降低。不过,很遗憾。我们不能这样做。因为系统中的进程是一个动态的过程,在什么时候有什么进程过来,都还是未知数。我们不能让操作系统这么神通广大,不让我们人类怎么办?-_-!

SPF模拟调度过程的关键代码如下:

<pre name="code" class="java"><pre name="code" class="java">@Override
    public int execute(ProcessModel... processList) {
        if (processList == null || processList.length == 0) {
            System.out.println(TAG + ">数据为空");
            return -1;
        }

        if (!(processList instanceof ProcessSPFModel[])) {
            System.out.println(TAG + ">数据类型出错");
            return -2;
        }

        ProcessSPFModel[] processArray = (ProcessSPFModel[])processList;
        boolean[]runFlag = new boolean[processArray.length];
        int runTimeSum = 0;
        int index = 0;
        ProcessSPFModel currentProcess = processArray[index];
        while(!noProcessWaitting(runFlag)) {
            currentProcess.setStartRunTime(runTimeSum);
            if (runTimeSum < currentProcess.getComingTime()) {
                runTimeSum = (int)currentProcess.getComingTime();
            }

            runTimeSum += currentProcess.getRunTime();
            currentProcess.setFinishTime(runTimeSum);
            currentProcess.setTurnaroundTime(runTimeSum - currentProcess.getComingTime());
            currentProcess.setTurnaroundWeightTime(1.0 * currentProcess.getTurnaroundTime() / currentProcess.getRunTime());

            runFlag[index] = true;

            index = getIndexMinRuntime(processArray, runFlag, runTimeSum);
            if (0 <= index && index < processArray.length) {
                currentProcess = processArray[index];
            } else {
                System.out.println("未知异常");
                break;
            }
        }

        return runTimeSum;
    }



这里有一个getIndexMinRuntime(...)方法,它的功能就是获得进程列表中服务时间最短的进程,当然前提是这个进程已经Coming。
private int getIndexMinRuntime(ProcessSPFModel[] processArray, boolean[] runFlag, int runTimeSum) {
        if (processArray.length == 0 || runFlag.length != processArray.length) {
            return -1;
        }

        int earliestIndex = 0;
        long earliestTime = Long.MAX_VALUE;
        int index = -1;
        long minTime = Long.MAX_VALUE;
        for (int i = 0; i < processArray.length; i++) {
            if (runFlag[i]) {
                continue;
            }

            if (processArray[i].getComingTime() < earliestTime) {
                earliestIndex = i;
                earliestTime = processArray[i].getComingTime();
            }

            if (processArray[i].getComingTime() > runTimeSum) {
                continue;
            }

            if (processArray[i].getRunTime() < minTime) {
                minTime = processArray[i].getRunTime();
                index = i;
            }
        }

        index = index < 0 ? earliestIndex : index;

        return index;
    }
在上面的代码里,有两个变量earliestIndex和earliestTime。前者是指尚未执行的最早到达的进程的下标,后者尚未执行的最早到达进程的到达时间。这定义这两个变量的目的是针对于,如果等待的队列中没有可执行的进程,那么我们就去在还没有执行且是最早到达的进程去选择。这一步事实上是模拟时间再向后推移。

实例和结果:

  这里我们通过一个例子来说明采用FCFS和SPF调度算法时的调度性能。现有五个进程A、B、C、D、E,它们到达的时间分别是0、1、2、3、4,所要求的服务时间分别是4、3、5、2 、4。

  通过FCFS和SPF调度算法计算出来的结果如下的图-3所示.


图-3 通过FCFS和SPF算法的调度过程


性能分析:

  从上面的结果中,我们不难计算出FCFS算法的平均周转时间为2.8,而SPF算法的平均周转时间只有2.1。

  进程D的周转时间从11降到了3,带权周转时间也是从5.5降到了1.5.而对于进程C就要稍微差一点了。C的周转时间从10升到了16,带权周转时间也从2升到了3.2。所以在短进程优先的调度算法中,短进程得到了很好地照顾。

  因为SPF相对于FCFS平均的周转时间降了很多。所以,一般情况下我们可以考虑使用SPF调度算法来替代FCFS。不过,有时候还是要具体问题具体问题具体对待了。毕竟是FCFS也有相对SPF的优势。

  关于FCFS和SPF的内容目前就到这里了。下一篇会再来详解一下“非抢占式优先权算法”和“抢占式优先权调度算法”。尽请期待。


GitHub源码下载:

https://github.com/William-Hai/ProcessSchedulingRules

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

先来先服务(FCFS)算法

快期末了在复习操作系统,顺便把实验课上写的算法重新写一遍 先来先服务算法非常简单,当作业来了,先来先运行,后来的按到达时间的先后排在就绪队列上,每次取队首元素运行。 实验环境是WIN7 64位+V...

进程调度模拟程序设计-----FCFS算法简单实现

题目描述: 一.实验目的和要求 加深对进程概念和进程调度过程/算法的理解。本实验要求用高级语言编写和调试一个模拟动态优先权的进程调度算法程序。 二、实验内容 1.给出进程调度的算法描述(如基于...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

FCFS、SJF、HRN调度算法

此程序是模拟作业调度中的先来先服务算法(fcfs),最短作业优先算法(sjf),最高响应比优先算法(hrn)。         print()函数的功能是输出模拟后的各作业运行情况。       ...

先来先服务算法(FCFS java实现)

package Arithmetic; import java.io.BufferedReader; import java.io.InputStream; import java.io.Input...

【操作系统 - 1】先来先服务FCFS和短作业优先SJF进程调度算法

【操作系统系列】学习至此,发现很多学了但很久没用的知识,久而久之,慢慢遗忘。等哪天还需要的话,却发现已经忘得差不多了,即使整理了文档(word等),还是得从头再学一遍。读研第一学期,发现很多东西都可以...

调度算法

在多道程序环境中,主存中有着多个进程,其数目往往多于处理机数量。这就要求系统能按照某种算法,动态地把处理机分配给就绪队列中的一个进程,使之执行,分配处理机的任务是由处理机调度程序完成的。 处理机...
  • mevicky
  • mevicky
  • 2015年07月03日 16:51
  • 2640

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

磁盘调度算法(FCFS&&SSTF)

操作系统磁盘调度算法之FCFS和SSTF篇,我感觉自己写的好垃圾啊!!!#include #include using namespace std; void FCFS(int a[],int n...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:操作系统:进程调度算法详解之FCFS和SPF篇
举报原因:
原因补充:

(最多只允许输入30个字)