Python实战——实现进程调度算法:先来先服务(FCFS)、短作业优先(SJF)和动态最高优先数优先(HRRN)

Python实战——实现进程调度算法:FCFS、SJF和HRRN

实验要求

进程调度算法:采用先来先服务、短作业、动态最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)。
每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:
进程名—进程标示数 ID
优先数 PRIORITY 优先数越大优先权越高(仅HRRN)
到达时间—进程的到达时间为进程输入的时间。、
进程还需要运行时间ALLTIME,进程运行完毕ALLTIME=0,
已用CPU时间----CPUTIME、
进程开始阻塞时间STARTBLOCK-表示当进程在运行STARTBLOCK个时间片后,进程将进入阻塞状态
进程的阻塞时间BLOCKTIME–表示当进程阻塞BLOCKTIME个时间片后,进程将进入就绪状态
进程状态—STATE

因为FCFS和SJF比较简单,所以写这两个算法时比较粗糙,没有设置阻塞时间,执行时也只是打印执行进程的信息(这俩是白给的)~~

HRRN算法每次都计算作业的优先级,随着作业等待时间的变长,优先级不断的提高,所以能够得到更快的执行。一般优先级的计算方法是:优先级 = (作业已等待时间 + 作业的服务时间) / 作业的服务时间,而这里我只是简单地令进程在等待或阻塞时优先数+1,效果都差不多~~

代码如下

运行环境为python 3.7

import random
class PCB:
    def __init__(self,pid,priority,arr_time,all_time,cpu_time,start_block,block_time,state): ##初始化进程
        self.pid=pid
        self.priority=priority
        self.arr_time=arr_time
        self.all_time=all_time
        self.cpu_time=cpu_time
        self.start_block=start_block
        self.block_time=block_time
        self.state=state

    def output(self):   ##hrrn输出
        print("进程"+str(self.pid),"优先级:"+str(self.priority),"到达时间:"+str(self.arr_time),
              "还需运行时间:"+str(self.all_time),"已运行时间:"+str(self.cpu_time),
              "开始阻塞时间:"+str(self.start_block),"阻塞时间:"+str(self.block_time),"状态:"+self.state)
    def Output(self):   ##sjf fcfs输出
        print("进程"+str(self.pid),"正在执行,到达时间:"+str(self.arr_time),
              "还需运行时间:"+str(self.all_time),"已运行时间:"+str(self.cpu_time))
    def toBlock(self):  ##将状态置为Block
        self.state="Block"
    def toRun(self):    ##将状态置为Run
        self.state="Run"
    def toFinish(self):     ##将状态置为Finish
        self.state="Finish"
    def toReady(self):      ##将状态置为Ready
        self.state="Ready"
    def running(self):      ##进程运行时状态变化
        self.all_time-=1
        self.cpu_time+=1
    def toBlocking(self):   ##进程将要开始阻塞的状态变化
        if self.start_block>0:
            self.start_block-=1
    def blocking(self):     ##进程阻塞时的状态变化
        if self.block_time>0:
            self.block_time-=1
        self.priority+=1

def init(num):##初始化进程,生成四个进程并按到达时间将它们放入列表list1
    list1=[]
    for i in range(num):
        list1.append(PCB(str(i),random.randint(1,10),random.randint(10,15),
                         random.randint(1,10),0,random.randint(5,10),random.randint(1,10),"Ready"))
    for i in range(len(list1)-1):
        for j in range(i+1,len(list1)):
            if list1[i].arr_time>list1[j].arr_time:
                list1[i],list1[j]=list1[j],list1[i]
    return list1
        
def fcfs(list1):##先来先服务
    time=0
    while 1:
        print("time:",time)
        if time>=list1[0].arr_time:
            list1[0].running()
            list1[0].Output()
            if list1[0].all_time==0:
                print("进程"+list1[0].pid+"执行完毕,周转时间:"+str(time-list1[0].arr_time+1)+"\n")
                list1.remove(list1[0])
        time+=1
        if not list1:
            break

def sjf(list1):##抢占式短作业优先
    list2=[]   ##就绪队列
    time=0
    while 1:
        len_list2=len(list2)
        print("time:",time)
        if list1:
            i=0
            while 1:   ##将进程放入就绪队列,就绪队列的第一个是正在执行的进程
                if time==list1[i].arr_time:
                    list2.append(list1[i])
                    list1.remove(list1[i])
                    pid=list2[0].pid  ##获取就绪队列第一个进程的进程ID
                    i-=1
                i+=1
                if i>=len(list1):
                    break                 
        if len(list2)>=2 and len(list2)!=len_list2: ##判断就绪队列中最短的作业
            len_list2=len(list2)
            for i in range(len(list2)-1):
                for j in range(i+1,len(list2)):
                    if list2[i].all_time>list2[j].all_time:
                        list2[i],list2[j]=list2[j],list2[i]
        if list2: ##执行过程
            if pid!=list2[0].pid: ##如果正在执行的进程改变,则发生抢占
                print("发生抢占,进程"+list2[0].pid+"开始执行")
                pid=list2[0].pid
            list2[0].running()
            list2[0].Output()
            if list2[0].all_time==0:
                print("进程"+list2[0].pid+"执行完毕,周转时间:"+str(time-list2[0].arr_time+1)+"\n")
                list2.remove(list2[0])
                if list2:
                    pid=list2[0].pid
        time+=1
        if not list2 and not list1:
            break
def hrrn(list1): ##动态最高优先数优先
    list2=[]  ##就绪队列
    list3=[]  ##阻塞队列
    time=0
    while 1:
        print("time:",time)
        if list1:
            i=0
            while 1: ##将进程放入就绪队列
                if time==list1[i].arr_time:
                    list2.append(list1[i])
                    list1.remove(list1[i])
                    pid=list2[0].pid
                    i-=1
                i+=1
                if i>=len(list1):
                    break
        for i in range(len(list2)-1): ##将就绪队列的进程按优先级大小排列
            for j in range(i+1,len(list2)):
                if list2[i].priority<list2[j].priority:
                    list2[i].toReady()
                    list2[i],list2[j]=list2[j],list2[i]
        if list2: ##执行过程
            if pid!=list2[0].pid:
                print("发生抢占,进程"+list2[0].pid+"开始执行")
                pid=list2[0].pid
            if list2[0].start_block>0 or list2[0].block_time<=0:
                list2[0].toRun()
                list2[0].running()
                list2[0].toBlocking() 
            for i in range(1,len(list2)):
                list2[i].priority+=1
                list2[i].toBlocking()
        if list3: ##阻塞队列
            for i in list3:
                i.blocking()
                
        for i in list2:
            i.output()
        for i in list3:
            i.output()
            
        if list2:  ##当进程开始阻塞时间为0,将进程放入阻塞队列
            i=0
            while 1:
                if list2:
                    if list2[i].start_block==0 and list2[i].block_time!=0:
                        print("进程"+list2[i].pid+"开始阻塞,进入阻塞队列")
                        list2[i].toBlock()
                        list3.append(list2[i])
                        list2.remove(list2[i])
                        i-=1
                i+=1
                if i>=len(list2):
                    break
            
        if list3:  ##当进程阻塞时间为0,将进程放入就绪队列
            i=0
            while 1:
                if list3[i].block_time==0:
                    print("进程"+list3[i].pid+"阻塞结束,进入就绪队列")
                    list3[i].toReady()
                    list2.append(list3[i])
                    list3.remove(list3[i])
                    pid=list2[0].pid
                    i-=1
                i+=1
                if i>=len(list3):
                    break
                
        if list2: ##进程执行完毕则移出就绪队列
            if list2[0].all_time<=0:
                list2[0].toFinish()
                print("进程"+list2[0].pid+"执行完毕,周转时间:"+str(time-list2[0].arr_time+1),"状态:"+list2[0].state+"\n")
                list2.remove(list2[0])
                if list2:
                    pid=list2[0].pid
        
        time+=1
        if not (list1 or list2 or list3):
            break
if __name__=="__main__":
    while 1:
        n=input("请选择算法(1、先来先服务  2、抢占式短作业优先  3、动态最高优先数优先):")
        if n=="1":
            list1=init(4)
            for i in list1:
                i.Output()
            fcfs(list1)
        elif n=="2":
            list1=init(4)
            for i in list1:
                i.Output()
            sjf(list1)
        elif n=="3":
            list1=init(4)
            for i in list1:
                i.output()
            hrrn(list1)
        else:
            print("输入错误,请重新输入!")

运行结果如下

FCFS(仅截取部分)

FCFS

SJF(仅截取部分)

SJF

HRRN(仅截取部分)

HRRN_1HRRN_2

进程的所有信息都是用Random库随机生成,因为一个个输入太麻烦~~
程序执行时只需选择调度算法,执行过程不需要任何操作
特别需要注意的是:在循环的每一秒中,输出信息和具体的操作一定要分开!一定要分开!一定要分开! 要么先打印后操作,要么先操作后打印,不要边操作边打印,会混乱的~
亲身经历总结出的教训~

  • 32
    点赞
  • 165
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 先来先服务FCFS进程调度算法是一种简单的调度算法,按照进程到达的先后顺序进行调度。即先到达的进程先执行,后到达的进程后执行。这种算法的优点是简单易懂,缺点是可能会出现长作业等待时间过长的情况。 作业优先SJF进程调度算法是一种根据进程执行时间长来进行调度的算法。即执行时间的进程先执行,执行时间长的进程后执行。这种算法的优点是可以减少长作业等待时间,缺点是可能会出现作业饥饿的情况。 ### 回答2: 进程调度算法是计算机操作系统中非常重要的一部分,FCFS先来先服务)和SJF作业优先)是其中比较常见的两种算法。下面将分别对两种算法进行介绍及比较。 FCFS算法先来先服务,即按照进入就绪队列的顺序,先进入队列的进程先被执行。该算法的优点是简单易懂,不需要对进程的属性进行过多的分析。但是,该算法存在一个致命的弊端:无法处理作业和长作业混杂的情况,因为如果遇到一个长作业作业就会被迫等待很长时间,导致系统的响应速度变慢。 SJF算法作业优先,即在就绪队列中,选择最作业先执行。该算法的优点是可以尽可能地提高系统的响应速度,保证作业更快地完成。但是该算法也存在一些缺点:由于进程的执行时间不确定,因此难以做出一个准确的预测,如果预测错误,可能会出现长时间的等待,导致系统效率降低。 两种算法的比较:FCFS算法最大的优点是简单易懂,没有太多的计算复杂度,但是对于作业和长作业混杂的情况,无法满足系统性能的要求。而SJF算法虽然能够提高系统的响应速度,并且对于作业友好,但也存在预测困难的问题,也会产生等待的情况。因此,需要根据具体的情况选择适合的算法,如果作业的执行时间能够事先预测,SJF算法是一个很好的选择,否则则可以选择FCFS算法。但是在实际应用中,为了更好地提高系统的性能,一般会采用优先调度算法,根据进程的属性进行优先级的排序,以此来保证更加合理的进程调度顺序。同时,还可以采用时间片轮转的方法,将长作业进行切割,让多个进程共享CPU,提高系统的处理能力。 ### 回答3: 先来先服务FCFS)是一种最简单的调度算法,也被称为先到先服务或先进先出。该算法的基本原理是按照进程到达的顺序进行调度,即先到来的进程先执行,后到达的进程后执行。FCFS算法适用于进程执行时间相同时,优先级相同的情况。由于该算法的简单性,一般只有在任务队列中的进程个固定且任务时间相等时才使用。但是,FCFS算法的显著缺陷是无法解决作业等待长作业的问题,因此在实际应用中,FCFS算法很少使用。 作业优先SJF)是一种比FCFS算法更为高效的调度算法,也被称为最作业优先。该算法的基本原理是按照进程需要执行的时间的长来进行调度,即先优先选择需要执行时间较的进程,而不是按照它们到达的顺序来进行调度。SJF算法适用于任务队列中的进程的时间不一致的情况。该算法具有高响应度、高效率和低等待时间的优点,能够降低平均等待时间。但是,该算法也存在着一定的问题,如容易出现饥饿现象(即在系统运行的过程中,某些进程始终无法被调度执行)。因此,通常可以将作业优先算法与其他调度算法一起使用,以避免饥饿现象的出现。 总之,先来先服务作业优先都是进程调度算法中常见的两种,它们各有优缺点,需要根据具体的情况选择合适的算法来保证系统的效率和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值