操作系统——作业调度算法 python实现

文章目录

    • 一、实现内容
    • 二、流程图
        • (1)程序基本要求
        • (2)流程图
    • 三、实现思路
        • 单道系统模拟
        • 多道系统模拟
    • 四、完整代码及输出
        • (1)单道系统作业调度模拟
        • (2)多道系统作业调度模拟

一、实现内容

(1) 编写并调试一个单道处理系统的作业调度模拟程序。
  作业调度算法:分别采用先来先服务(FCFS),最短作业优先(SJF)、响应比高者优先(HRRN)的调度算法。
  对每种调度算法都要求打印每个作业开始运行时刻、完成时刻、周转时间、带权周转时间,以及这组作业的平均周转时间及带权平均周转时间,以比较各种算法的优缺点。
(2) 编写并调度一个多道程序系统的作业调度模拟程序。
  作业调度算法:采用基于先来先服务的调度算法或基于优先级的作业调度算法。其余可以参考课本中的方法进行设计。
  对于多道程序系统,要假定系统中具有的各种资源及数量、调度作业时必须考虑到每个作业的资源要求。

二、流程图

(1)程序基本要求

在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的 CPU时限等因素。
  作业调度算法:采用先来先服务(FCFS)调度算法,即按作业提交的先后次序进行调度。总是首先调度在系统中等待时间最长的作业。每个作业由一个作业控制块JCB表示,JCB可以包含如下信息:作业名、提交时间、所需的运行时间、所需的资源、作业状态、链指针等等。
  作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种状态之一。每个作业的最初状态总是等待W。各个等待的作业按照提交时刻的先后次序排队,总是首先调度等待队列中队首的作业。每个作业完成后要打印该作业的开始运行时刻、完成时刻、周转时间和带权周转时间,这一组作业完成后要计算并打印这组作业的平均周转时间、带权平均周转时间。

(2)流程图

操作系统——作业调度算法 python实现_第1张图片

三、实现思路

单道系统模拟

(1)在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的 CPU时限等因素

(2)高响应比怎么体现?
在进程调度中,pcb类中添加了2个和优先级有关的类属性,静态优先级prior和动态优先级dy_prior。那在JCB类中,并不需要显示初始的优先级,因为初始的优先级一定为0,所以可以将动态优先级这个属性删除,随着作业调度,执行作业的操作的时间变化,每次执行完上一个作业就计算当前的各个作业的优先级,并赋值prior。

(3)SJF算法也很简单,虽然多了一个优先级的概念,但是一个确定作业序列中,每个作业的所需时长已知,那我干脆将这个作业序列,按照每个序列的时长,从小到大排列,然后再进行FCFS的调度就好了。

(4)HRRN响应比高者优先调度算法也是按照优先级先后调度,这里的优先级和SJF不同,这肯定是动态变化的,有点类似动态优先级调度,但是更简单。这里的优先级=(等待时间+要求服务时间)/要求服务时间。等待的时间和所需要的时间的和刚好是系统对该作业的响应时间。而这个比值看分母,说明该算法还是偏袒时间短的作业,等待时间相同时,作业越短,获得执行的几率越高。
因为每次都要计算优先级,所以就没法直接对序列循环了。更类似实验一的算法了。

我是这么解决的,每次都执行序列首部的作业。在执行了上一个作业后,将执行完的作业移动位置到序列尾部,然后对剩下的len(list)-len(state=finish)个挑选当前优先级最大的到序列首部。都是O(n)个复杂度。

而id=0的就是默认的t0=0时,等待时间最长的,所以虽然一开始首部的优先级是0,但是他应该是第一个执行的

多道系统模拟

四、完整代码及输出

(1)单道系统作业调度模拟

import random
##这是单道处理系统作业的调度模拟,包括FCFS(先来先服务)、SJF(短作业优先)、HRRN(响应比高着优先)算法。
class JCB :
    def __init__(self, id, cputime) :
        # id:序号  cputime:作业预计所需时间
        self.id = id
        self.prior = 0      #可作为HRRN中需要的优先级,一开始为0,随着调度、等待而改变;
        self.cputime = cputime
        self.state = 0  # 0表示Wait 1表示Run 2表示Finish
        self.starttime = 0    #进程开始运行的时间
        self.endtime = 0     #进程结束运行时间

    def out_init(self):
        print(("初始化JCB序列:%-2d" + "预计所需时间:%-2d")%(self.id,self.cputime))

    def outSituation_HRRN(self) :  #输出HRRN法作业调度情况
        Turnaround = self.endtime   #周转时间= 完成时间-提交时间
        Daiquan = Turnaround / self.cputime  #带权周转时间:周转时间/运行所需时间
        print(("HRRN法: "+"作业:%-2d"  +"  优先权:%-2d"+ "  作业所需CPU时间:%-2d" +"  开始运行时间:%-2d"
               + "  结束运行时间:%-2d" +"  周转时间:%.2f" + "  带权周转时间:%.2f")%
              (self.id,self.prior,self.cputime,self.starttime,self.endtime,Turnaround, Daiquan))

    def outSituation_FCFS(self) :  #输出FCFS法作业调度运行情况
        Turnaround = self.endtime
        Daiquan = Turnaround / self.cputime
        print(("FCFS: " + "作业:%-2d" + "  作业所需CPU时间:%-2d" + "  开始运行时间:%-2d"
               + "  结束运行时间:%-2d"+"  周转时间:%.2f" + "  带权周转时间:%.2f") %
              (self.id, self.cputime, self.starttime, self.endtime,Turnaround, Daiquan))

    def outSituation_SJF(self) :  #输出SJF法作业调度运行情况
        Turnaround = self.endtime
        Daiquan = Turnaround / self.cputime
        print(( "SJF法: "+"作业:%-2d" + "  作业所需CPU时间:%-2d" + "  开始运行时间:%-2d"
               + "  结束运行时间:%-2d"+"  周转时间:%.2f" + "  带权周转时间:%.2f") %
              (self.id, self.cputime, self.starttime, self.endtime,Turnaround, Daiquan))

def init(num) : #创建数目确定的jcb块,按顺序放入列表中
    jcbList = []
    for i in range(num) :
        jcbList.append(JCB(i, random.randint(1, 20)))
        # 将随机产生的n个作业保存,创建id和预计CPU时间
    print("刚生成的各进程")
    for i in jcbList:  #输出最开始时进程情况
        i.out_init()
    return jcbList

def sort_SJF(jcbList):  #将初始化的序列,按照作业的时间,从小到大排列。
    for i in range(0,len(jcbList)-1):
        for j in range(i+1,len(jcbList)):
            if jcbList[i].cputime > jcbList[j].cputime :
                jcbList[i],jcbList[j] = jcbList[j],jcbList[i]
    return jcbList

def sort_HRRN(jcbList,count): #每次执行完上一个作业,对剩余作业排序,响应比作为优先级,优先级高的排前面
    #优先级=(等待时间+cputime)/cputime  这里的等待时间可以理解为就是时间量T,因为参与排序的肯定是还没执行的作业
    #先计算待处理的作业的优先级,将finish的排到最后,并且将优先级最高的排到第一位
    for i in jcbList:
        i.prior = (count + i.cputime)/i.cputime
    for i in range(len(jcbList)-1,0,-1): #finish的转移到尾部,然后只遍历状态为0的
        if jcbList[i].state == 2:
            continue
        if jcbList[i].prior > jcbList[i-1].prior :
            jcbList[i], jcbList[i - 1] = jcbList[i-1], jcbList[i]


def FCFS(jcbList): #先来先服务调度算法
    count = 0 #时间片0  即指导书中的时间量T0=0
    for i in jcbList:
        i.state = 1
        i.starttime = count   #每个作业只执行一次,所以不需要像实验一动态优先级算法一样来判断是否是第一次执行
        count += i.cputime
        i.endtime = count
        i.state = 2
        i.outSituation_FCFS()
    Turnaround_time = 0
    daiquan_time = 0
    for i in jcbList :  # 计算平均周转时间
        Turnaround_time += i.endtime   #完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
        daiquan_time += i.endtime/i.cputime
    print(('平均周转时间:%.2f'+'  平均带权周转时间%.2f')%(Turnaround_time/len(jcbList),daiquan_time/len(jcbList)))


def SJF(jcbList):  #短作业优先调度算法
    count = 0
    sort_SJF(jcbList)
    for i in jcbList:
        i.state = 1
        i.starttime = count   #每个作业只执行一次,所以不需要像实验一动态优先级算法一样来判断是否是第一次执行
        count += i.cputime
        i.endtime = count
        i.state = 2
        i.outSituation_SJF()
    Turnaround_time = 0
    daiquan_time = 0
    for i in jcbList :  # 计算平均周转时间
        Turnaround_time += i.endtime   #完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
        daiquan_time += i.endtime/i.cputime
    print(('平均周转时间:%.2f'+'  平均带权周转时间%.2f')%(Turnaround_time/len(jcbList),daiquan_time/len(jcbList)))

def HRRN(jcbList):  #响应比高者优先调度算法
    count = 0
    while jcbList[0].state == 0: #只要首部还是0就说明还有作业没执行完
        jcbList[0].state = 1
        jcbList[0].starttime = count
        count += jcbList[0].cputime
        jcbList[0].endtime = count
        jcbList[0].state = 2
        jcbList[0].outSituation_HRRN()

        jcbList.append(jcbList[0]) #将完成的作业移到序列尾部
        del jcbList[0]

        sort_HRRN(jcbList, count)

    Turnaround_time = 0
    daiquan_time = 0
    for i in jcbList :  # 计算平均周转时间
        Turnaround_time += i.endtime  # 完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
        daiquan_time += i.endtime / i.cputime
    print(('平均周转时间:%.2f' + '  平均带权周转时间%.2f') % (Turnaround_time / len(jcbList), daiquan_time / len(jcbList)))


def main():
    print("现在是单道批处理系统作业调度模拟程序")
    while True :
        jcbNum = int(input("输入作业数量(4,8):"))
        print("请从以下方法中选择一种进程调度方法")
        print("(1)FCFS (2)SJF  (3)HRRN  (4)退出")
        method = int(input())
        jcbList = init(jcbNum)
        if method == 1 :
            FCFS(jcbList)
        elif method == 2 :
            SJF(jcbList)
        elif method == 3 :
            HRRN(jcbList)
        else:
            break
        print("")
        try:
            flag = int(input("输入4退出程序,或者enter进行下一次操作"))
            if flag == 4:
                break
        except:
            pass
if __name__ == '__main__':
    main()

输出
操作系统——作业调度算法 python实现_第2张图片

(2)多道系统作业调度模拟

import random
##这是多道处理系统作业的调度模拟,FCFS(先来先服务)算法。
class JCB :
    def __init__(self, id, cputime) :
        # id:序号  cputime:作业预计所需时间
        self.first = 0 #0代表没有进入过内存执行,进入了就加一
        self.id = id
        self.prior = 0      #可作为HRRN中需要的优先级,一开始为0,随着调度、等待而改变;
        self.cputime = cputime
        self.state = 0  # 0表示Wait 1表示Run 2表示Finish
        self.arrivetime = id
        self.starttime = 0    #进程开始运行的时间
        self.endtime = 0     #进程结束运行时间
        self.io = random.randint(1,cputime-1)
        self.restoftime = cputime

    def out_init(self):
        print(("初始化JCB序列:%-2d" + " 到达时间:%-2d"+ " 预计所需时间:%-2d" +"  io所在时间片:%-2d")%
              (self.id,self.arrivetime,self.cputime,self.io))

    def outSituation_FCFS(self) :  #输出FCFS法作业调度运行情况
        Turnaround = self.endtime - self.id
        Daiquan = Turnaround / self.cputime
        print(("FCFS: " + "作业:%-2d" + "  作业所需CPU时间:%-2d" + "  开始运行时间:%-2d"
               + "  结束运行时间:%-2d"+"  周转时间:%.2f" + "  带权周转时间:%.2f") %
              (self.id, self.cputime, self.starttime, self.endtime,Turnaround, Daiquan))


def init(num) : #创建数目确定的jcb块,按顺序放入列表中
    jcbList = []
    for i in range(num) :
        jcbList.append(JCB(i, random.randint(3, 20)))
        # 将随机产生的n个作业保存,创建id和预计CPU时间
    print("刚生成的各进程")
    for i in jcbList:  #输出最开始时进程情况
        i.out_init()
    return jcbList

def FCFS(jcbList):
    #这个系统可以同时处理3个作业,只有一个io,只要当前时间有wait的作业并且执行的作业不满3,就执行新的进程
    #如果io冲突,就让争用的作业就等待,并导入下一个进程,如果io结束,就暂停下一个进程,继续执行上一个作业
    #忽略调度程序的时间
    count = 0

    run_list = [] #len(run_list) <= 3
    while True  :
        io_flag = 0  # 为0说明没有被使用,每次也只用一个时间片,所以每次开始都是0
        if len(run_list)<3 and  jcbList[0].id <= count:
            if jcbList[0].state == 0 :
                run_list.append(jcbList[0])
                del jcbList[0]
                run_list[-1].state = 1
            if run_list[-1].first == 0 :
                run_list[-1].starttime = count
            run_list[-1].first += 1

        if len(run_list) >0 :
            for i in run_list:
                if i.io + i.starttime == count :

                    i.restoftime += 1
                    if io_flag == 0:
                        io_flag = 1
                    else:
                        i.restoftime += 1
                        i.io += 1
                    if jcbList[0].first == 0 :
                        jcbList[0].starttime = count+1
                    jcbList[0].first +=1

                    if jcbList[0].io!=1:
                        jcbList[0].restoftime -= 1
                    elif len(jcbList)>1:
                        if jcbList[1].first == 0:
                            jcbList[1].starttime = count
                        jcbList[1].first += 1
                        jcbList[1].restoftime -= 1

            for i in run_list:
                if i.restoftime == 0:
                    i.state = 2
                    i.endtime = count
                    jcbList.append(i)
                    run_list.remove(i)
                else:
                    i.restoftime -= 1
        if (len(run_list) == 0) :
            break


        count += 1
    for i in jcbList :
        i.outSituation_FCFS()

def main():
    print("现在是多道批处理系统作业调度模拟程序")
    while True :
        jcbNum = int(input("输入作业数量(4,8):"))
        print("请从以下方法中选择一种进程调度方法")
        print("(1)FCFS    (2)退出")
        method = int(input())
        jcbList = init(jcbNum)
        if method == 1 :
            FCFS(jcbList)

        elif method == 2 :
            break

        print("")
        try:
            flag = int(input("输入4退出程序,或者enter进行下一次操作"))
            if flag == 4:
                break
        except:
            pass
if __name__ == '__main__':
    main()

输出
操作系统——作业调度算法 python实现_第3张图片

你可能感兴趣的:(操作系统)