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

一、实现内容

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

二、流程图

(1)程序基本要求

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

(2)流程图

在这里插入图片描述

三、实现思路

单道系统模拟

(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()

输出
在这里插入图片描述

(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()

输出
在这里插入图片描述

  • 23
    点赞
  • 192
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
内含源代码和实验报告 多道批处理系统的两级调度-1 本课程设计要求模拟实现一个的多道批处理系统的两级调度。通过具体的作业调度、进程调度、内存分配等功能的实现,加深对多道批处理系统的两级调度模型和实现过程的理解。 要求作业从进入系统到最后完成,要经历两级调度:作业调度和进程调度。作业调度是高级调度,它的主要功能是根据一定的算法,从输入井中选中若干个作业,分配必要的资源,如主存、外设等,为它们建立初始状态为就绪的作业进程。进程调度是低级调度,它的主要功能是根据一定的算法将CPU分派给就绪队列中的一个进程。 1. 假定某系统可供用户使用的主存空间共100KB,并有4台磁带机。主存分配采用可变分区分配方式且主存中信息不允许移动,对磁带机采用静态分配策略,作业调度分别采用最小作业优先算法,进程调度采用可抢占的最短进程优先算法。 2. 假定“预输入”程序已经把一批作业的信息存放在输入井了,并为它们建立了相应作业表。测试数据如下: 作业 到达时间 估计运行时间 内存需要 磁带机需要 JOB1 10:00 25分钟 15K 2台 JOB2 10:20 30分钟 60K 1台 JOB3 10:30 10分钟 50K 3台 JOB4 10:35 20分钟 10K 2台 JOB5 10:40 15分钟 30K 2台 3. 分别在不同算法控制下运行设计的程序,依次显示被选中作业、内存空闲区和磁带机的情况。比较不同算法作业的选中次序及作业平均周转时间。 4. 选用程序设计语言:C、C++等。
好的,进程调度算法操作系统中非常重要的一部分。常见的进程调度算法有先来先服务(FCFS)、短作业优先(SJF)、高响应比优先(HRRN)、时间片轮转(RR)等。下面是这些算法Python 实现: 1. 先来先服务(FCFS): ```python def FCFS(processes): waiting_time = 0 turn_around_time = 0 completion_time = 0 for process in processes: completion_time += process['burst_time'] turn_around_time += completion_time - process['arrival_time'] waiting_time += turn_around_time - process['burst_time'] return waiting_time / len(processes), turn_around_time / len(processes) ``` 2. 短作业优先(SJF): ```python def SJF(processes): processes = sorted(processes, key=lambda x: x['burst_time']) waiting_time = 0 turn_around_time = 0 completion_time = 0 for process in processes: completion_time += process['burst_time'] turn_around_time += completion_time - process['arrival_time'] waiting_time += turn_around_time - process['burst_time'] return waiting_time / len(processes), turn_around_time / len(processes) ``` 3. 高响应比优先(HRRN): ```python def HRRN(processes): waiting_time = 0 turn_around_time = 0 completion_time = 0 for i, process in enumerate(processes): if i == 0: completion_time = process['burst_time'] else: response_ratio_list = [] for j in range(i): response_ratio = (completion_time - processes[j]['arrival_time'] + processes[j]['burst_time']) / processes[j]['burst_time'] response_ratio_list.append(response_ratio) max_response_ratio_index = response_ratio_list.index(max(response_ratio_list)) selected_process = processes.pop(max_response_ratio_index) completion_time += selected_process['burst_time'] turn_around_time += completion_time - selected_process['arrival_time'] waiting_time += turn_around_time - selected_process['burst_time'] return waiting_time / len(processes), turn_around_time / len(processes) ``` 4. 时间片轮转(RR): ```python def RR(processes, time_slice): waiting_time = 0 turn_around_time = 0 completion_time = 0 while processes: for i in range(len(processes)): if processes[i]['burst_time'] > time_slice: completion_time += time_slice processes[i]['burst_time'] -= time_slice else: completion_time += processes[i]['burst_time'] turn_around_time += completion_time - processes[i]['arrival_time'] waiting_time += turn_around_time - processes[i]['burst_time'] processes.pop(i) break return waiting_time / len(processes), turn_around_time / len(processes) ``` 这里的 `processes` 是一个列表,其中每个元素是一个字典,表示一个进程的信息,如下所示: ```python processes = [ {'name': 'P1', 'arrival_time': 0, 'burst_time': 8}, {'name': 'P2', 'arrival_time': 1, 'burst_time': 4}, {'name': 'P3', 'arrival_time': 2, 'burst_time': 9}, ... ] ``` 在这个列表中,每个进程有一个名称、到达时间和执行时间。你可以根据自己的需要修改这些信息,来测试这些进程调度算法实现
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值