《操作系统》实验一:先来先服务FCFS和短作业优先SJF进程调度算法

【实验题目】:先来先服务FCFS和短作业优先SJF进程调度算法

【实验学时】:4学时

【实验目的】 

通过这次实验,加深对进程概念的理解,进一步掌握进程状态的转变、进程调度的策略及对系统性能的评价方法。

【实验内容】

问题描述:

设计程序模拟进程的先来先服务FCFS和短作业优先SJF调度过程。假设有n个进程分别在T1, … ,Tn时刻到达系统,它们需要的服务时间分别为S1, … ,Sn。分别采用先来先服务FCFS和短作业优先SJF进程调度算法进行调度,计算每个进程的完成时间,周转时间和带权周转时间,并且统计n个进程的平均周转时间和平均带权周转时间。

程序要求如下:

1)进程个数n;每个进程的到达时间T1, … ,Tn和服务时间S1, … ,Sn;选择算法1-FCFS,2-SJF。

2)要求采用先来先服务FCFS和短作业优先SJF分别调度进程运行,计算每个进程的周转时间,带权周转时间,并且计算所有进程的平均周转时间,带权平均周转时间;

3)输出:要求模拟整个调度过程,输出每个时刻的进程运行状态,如“时刻3:进程B开始运行”等等;

4)输出:要求输出计算出来的每个进程的周转时间,带权周转时间,所有进程的平均周转时间,带权平均周转时间。


【源代码】复制到Pycharm或者jupyter notebook可以直接跑!!!

"""
先进先出算法,按照进程到达时间排序,首先把所有进程按到达时间进行排序
第一个到达的进程直接服务,后续进程要进行判断,判断该进程到达时间与前一个进程结束时间
若进程到达时间较迟,该进程开始时间等于该进程到达时间,
若进程到达时间较早,该进程开始时间等于前一个进程结束时间。
"""
def FCFS(pcb, n):
    pcb.sort(key=lambda x:x[1],reverse=False)  #按照到达时间升序排序
    #修改pcb中到达时间和完成时间
    for i in range(n):
        if i == 0:  #如果是第一个到达的进程
            starttime =int(pcb[i][1])  #开始时间等于第一个进程的到达时间
            pcb[i][3] = starttime      #修改第一个进程的开始时间
            pcb[i][4] = starttime + int(pcb[i][2])  #第一个进程的完成时间等于开始时间+服务时间
        elif (i > 0 and  int(pcb[i-1][4]) < int(pcb[i][1])):  #前一个进程的完成时间早于后一个进程的开始时间
            starttime = int(pcb[i][1])   #进程开始时间等于该进程到达时间
            pcb[i][3] = starttime   #修改开始时间为该进程到达时间
            pcb[i][4] = starttime + int(pcb[i][2])  #修改完成时间=开始时间+服务时间
        else:  #前一个进程的完成时间后于后一个进程的开始时间
            starttime = int(pcb[i-1][4])  #该进程开始时间等于前一进程完成时间
            pcb[i][3] = starttime #修改
            开始时间
            pcb[i][4] = starttime + int(pcb[i][2])  #修改完成时间=开始时间+服务时间
    #修改pcb中的带权时间和带权周转时间
    for i in range(n):
        pcb[i][5] = float(pcb[i][4] - int(pcb[i][1])) #带权时间=完成时间-到达时间
        pcb[i][6] = float(pcb[i][5] / int(pcb[i][2])) #带权周转时间=带权时间/服务时间
    #计算平均周转时间和平均带权周转时间
    zztime = 0
    dqzztime = 0
    for i in range(n):
        zztime = float(zztime + float(pcb[i][5]))  #周转时间之和
        dqzztime = float(dqzztime + float(pcb[i][6])) #带权周转时间之和
    average_zztime = float(zztime / n )
    average_dqzztime = float(dqzztime / n)
    #对pcb按照开始时间进行排序
    pcb.sort(key = lambda x:x[3], reverse = False)
    return pcb,average_zztime,average_dqzztime
"""
短作业优先算法按作业的服务时间排序,首先按到达时间排序,第一个进程被服务,开始时间等于进程到达时间
后续进程按服务时间进程排序

"""
def SJF(pcb,n):
    sjf_pcb = []
    i = 1   #控制从第二个进程开始
    k = 0  #用于控制循环结束
    sjf_pcb = pcb
    sjf_pcb.sort(key=lambda x:x[1],reverse=False)  #按照到达时间升序排序
    
    #第一个到达的进程先服务,修改第一个进程的周转时间,带权周转时间
    starttime = int(sjf_pcb[0][1])   #开始时间等于第一个到达进程的开始时间
    pcb[0][3] = starttime   #修改第一个进程的开始时间
    pcb[0][4] = starttime + int(sjf_pcb[0][2])  #第一个进程的完成时间=开始时间+服务时间
    sjf_pcb[0][5] = int(sjf_pcb[0][4]) - int(sjf_pcb[0][1])  #计算周转时间=完成时间-到达时间
    sjf_pcb[0][6] = float(sjf_pcb[0][5]) / int(sjf_pcb[0][2])  #计算带权周转时间=周转时间/服务时间

    #从第二个进程开始,按服务时间进行排序
    temp_pcb = sjf_pcb[1:len(sjf_pcb)]   #临时存放 
    temp_pcb.sort(key=lambda x: x[2], reverse=False)  #按服务时间进行升序排序
    sjf_pcb[1:len(sjf_pcb)] = temp_pcb   #修改原先进程队列,保存按服务时间排序后的进程顺序
    #从第二个进程开始
    while(i < n):
        h = 1
        # 比较到达时间和前一者的完成时间
        while(int(sjf_pcb[i][1]) >= int(sjf_pcb[i - 1][4])):  #当前进程到达时间迟于上一个进程完成时间,开始时间要相应推迟
            if i == n - 1:    #如果当前进程是已到达最后一个进程,直接修改进程时间
                startTime = sjf_pcb[i][1]  #开始时间=当前进程到达时间
                sjf_pcb[i][3] = starttime  #开始时间
                sjf_pcb[i][4] = starttime + int(sjf_pcb[i][2]) #完成时间=开始时间+服务时间
                sjf_pcb[i][5] = int(sjf_pcb[i][4]) - int(sjf_pcb[i][1]) #周转时间=完成时间-到达时间
                sjf_pcb[i][6] = float(sjf_pcb[i][5]) / int(sjf_pcb[i][2]) #带权周转时间=周转时间/服务时间
                k = 1      #说明已经服务完已到达的最后一个进程,可以跳出当前while循环
                break
            else:      #如果当前进程不是最后一个进程,服务完之后,还要对进程顺序重新进行调换
                temp_sjf_pcb = sjf_pcb[i]  #把未被服务的进程放在sjf_pcb列表末尾,便于后续排序
                sjf_pcb[i] = sjf_pcb[i+h]
                sjf_pcb[i+h] = temp_sjf_pcb
                h += 1
                if h >= n - i - 1:  #说明前面的进程完成之后,还有新的进程没有到达,重新排序(可能新到达的进程服务时间更短)
                    temp_pcb2 = sjf_pcb[i:len(sjf_pcb)]  
                    temp_pcb2.sort(key=lambda x: x[1], reverse=False)   # 后续队列重新按照到达时间顺序进行排序
                    sjf_pcb[i:len(sjf_pcb)] = temp_pcb2
                    sjf_pcb[i][3] = int(sjf_pcb[i][1])  #开始时间=该进程的到达时间
                    sjf_pcb[i][4] = int(sjf_pcb[i][1]) + int(sjf_pcb[i][2]) #完成时间=该进程到达时间+服务时间
                    sjf_pcb[i][5] = int(sjf_pcb[i][4]) - int(sjf_pcb[i][1]) #周转时间=该进程完成时间-到达时间
                    sjf_pcb[i][6] = float(sjf_pcb[i][5]) / int(sjf_pcb[i][2]) #带权周转时间=完成时间/服务时间
                    temp_pcb2 = sjf_pcb[i + 1:len(sjf_pcb)]  #保存后续未服务进程
                    temp_pcb2.sort(key=lambda x: x[2], reverse=False)  # 对未服务的进程重新按照服务时间排序
                    sjf_pcb[i + 1:len(sjf_pcb)] = temp_pcb2  #修改进程队列
                    h = 1
                    i += 1
                else:
                    continue
        if(k == 1): #说明进程服务完成
            break
        else:    #上一进程结束时,该短进程已经到达,对进程进行时间修改
            starttime = sjf_pcb[i - 1][4]  #开始时间=前一个进程的完成时间
            sjf_pcb[i][3] = starttime #开始时间
            sjf_pcb[i][4] = starttime + int(sjf_pcb[i][2])  #完成时间=开始时间+服务时间
            sjf_pcb[i][5] = int(sjf_pcb[i][4]) - int(sjf_pcb[i][1])
            sjf_pcb[i][6] = float(sjf_pcb[i][5]) / int(sjf_pcb[i][2])
            i += 1
    # 计算平均周转时间和平均带权周转时间
    zztime = 0
    dqzztime = 0
    for i in range(n):
        zzTime = float(zztime + float(pcb[i][5]))
        dqzzTime = float(dqzztime + float(pcb[i][6]))
    average_zztime = float(zzTime / n)
    average_dqzztime = float(dqzzTime / n)
    # 输出结果,按照开始时间进行排序
    sjf_pcb.sort(key=lambda x: x[3], reverse=False)
    return pcb,average_zztime,average_dqzztime
    
   def main():
    #实现先来先服务
    pcb = []
    #确认进程数
    n = int(input("请输出进程个数"))
    #输入到达时间和服务时间
    for i in range(n):
        pname = input("请输入第"+str(i+1)+"个进程名:")
        arrivetime = input("请输入到达时间:")
        servicetime = input("请输入服务时间:")
        pcb.append([pname,arrivetime,servicetime,0,0,0,0]) #开始,完成,周转,带权周转
    suanfa = input("请输入你想要执行的算法(FCFS或者SJF)")
    if suanfa=='FCFS':
        pcb,average_zztime,average_dqzztime = FCFS(pcb,n)
    else:
        pcb,average_zztime,average_dqzztime = SJF(pcb,n)
    #输出结果
    for i in range(n):
        print("进程名: %s    开始时间: %d    完成时间: %d    周转时间: %d    带权周转时间: %.2f    " \
                  % (pcb[i][0], int(pcb[i][3]), int(pcb[i][4]), int(pcb[i][5]), float(pcb[i][6])))

    print("本次调度的平均周转时间为: %.2f" % float(average_zztime))
    print("本次调度的平均带权周转时间为: %.2f" % float(average_dqzztime))
    
main()    

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

守岁白驹hh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值