操作系统-进程与线程(调度器与闲逛进程,调度算法与评价标准)

1. 调度器/调度程序

进程从就绪态转化为运行态,或者从运行态转化为就绪态都需要调度器

CPU运行哪个进程由调度算法决定。
一个进程在CPU上运行的时间由时间片决定。

执行调度器/调度程序的时机:

  1. 创建新进程
  2. 进程退出
  3. 运行进程阻塞
  4. IO中断发生,唤醒了某些阻塞进程

如果是非抢占式调度策略:只有在进程退出,或者进程阻塞的时候才会触发调度器

抢占式调度策略:每个或每K个时钟中断都会触发调度器。

需要注意:

  • 在支持内核级线程操作系统,调度程序的操作对象是内核级线程
  • 不支持内核级线程操作系统,调度程序的操作对象是进程

2. 闲逛进程

如果没有进程就绪时,此时CPU就会运行闲逛进程。

闲逛进程的特点:

  1. 优先级最低
  2. 能耗低
  3. 闲逛进程会反复执行0地址指令,不需要访存,不需要访问CPU寄存器。
  4. 指令周期结束后会检测中断。

3. 调度算法评价标准

CPU利用率: (CPU处于忙碌时间)÷(CPU总时间)(通常会考察多道程序并发执行的情况下CPU利用率)
系统吞吐量: 单位时间内完成的作业数目

系统吞吐量=(一段时间内完成的作业数目÷一段时间)

周转时间: 作业被提交到系统到作业完成的这段时间

  • 平均周转时间:各个作业周转时间和÷作业数目
  • 带权周转时间:作业周转时间÷作业实际运行时间(带权周转时间越小,用户效果越好)
  • 平均带权周转时间:带权周转时间和÷作业数

等待时间: 进程/作业处于等待处理机状态的时间

  • 进程等待时间:进程建立后等待被服务的时间和
  • 作业等待时间:作业在外存后备队列等待时间+进程等待时间

相应时间: 用户提交请求到首次产生响应所用的时间

4.调度算法

先来先服务(FCFS)

思路:按照作业,进程到达的先后顺序进行服务

当用于作业调度时:考虑那个作业先到达后备队列。
当用于进程调度时:考虑那个进行先到达就绪队列。

FCFS调度算法是非抢占式的调度算法

在这里插入图片描述

解:这些进程都是纯计算型进程,首先采用先来先服务调度算法,进程的调度顺序为:

p1->p2->p3->p4

周转时间:(完成时间-到达时间

  • p1:7
  • p2:(7+4)- 2=9
  • p3:(7+4+1)- 4=8
  • p4:(7+4+1+4)- 5=11

带权周转时间:周转时间÷运行时间

  • p1:7÷7=1
  • p2:9÷4=2.25
  • p3:8÷1=8
  • p4:11÷4=2.75

等待时间:周转时间-运行时间

需要注意:

如果涉及IO操作的进程,等待时间=周转时间-等待时间-I/O操作时间

  • p1:0
  • p2:9-4=5
  • p3:8-1=7
  • p4:11-4=7

平均等待时间:4.75

平均周转时间:8.75

平均带权周转时间:3.5

优点:

  1. 公平,算法实现简单
  2. 不会导致线程饥饿

缺点:

  1. 对长作业有利,短作业带权等待时间太长,短作业用户体验差

短作业优先服务(SJF)

思想:要求服务时间最短的优先调度

当用于作业调度时:称为SJF
当用于进程调度时:称为短进程优先算法SPF

SJF与SPF是非抢占式调度算法

但是也有其抢占式调度的变种:最短剩余时间优先算法(SRTN)
在这里插入图片描述
解:首先分析调度顺序

短作业/进程优先调度算法:每次调度时选择当前已到达且运行时间最短的作业/进程。

调度顺序为:p1->p3->p2->p4

具体计算过程省略:

平均周转时间= (7+4+10+11)/4 = 8

平均带权周转时间=(1+4+2.5+2.75)/4 = 2.56

平均等待时间= (0+3+6+7)/4 = 4

如果采用抢占式短作业优先算法(SRTN):
在这里插入图片描述
最短剩余时间优先算法:每当有进程加入就绪队列,就绪队列改变时就需要调度,如果新到达的进程剩余时间比当前运行的进程剩余时间更短,则由新进程抢占处理机,当前运行进程重新回到就绪队列。另外,当一个进程完成时也需要调度。

进程调度顺序分析如下:

  1. p1先到达,过了两个时间后p2到达
  2. 2时刻,p1(5) 、p2(4),此时p2剩余时间短。CPU会调度p2
  3. 4时刻,p1(5)、p2(2),p3(1)此时调度p3
  4. 5时刻,p3完成任务,p4进程需要被调度。p1(5)、p2(2)、p4(4)调度p2
  5. p2调度后,调度剩下的p4->p1

在这里插入图片描述
平均周转时间=(16+5+1+6)/4 = 7

平均带权周转时间=(2.28+1.25+1+1.5)/4 = 1.50

平均等待时间=(9+1+0+2)/4 = 3

可以发现,采用抢占式短作业优先比非抢占式的短作业优先更加高效。

如果题目没有明确指明,提到的短作业优先默认是非抢占式的。

注意:
1. 在所有的进程同时可以运行的情况下(所有的进程近似同时到达),采用短作业优先调度算法平均等待时间,平均周转次数最短。
2. 如果没有限定条件,抢占式短作业优先算法(SRTN)平均等待时间,平均周转次数最短

优点:

  1. 可以得到最短的平均等待时间,平均周转次数

缺点:

  1. 对短作业比较好,对长作业用户体验差
  2. 可能会导致饥饿

高响应比优先算法(HRRN)

思路:在每次调度时先计算各个作业/进程的响应比,选择响应比最高的作业/进程为其服务(响应比:(等待时间+要求服务时间)÷要求服务时间。)

属于非抢占式调度算法,在进程主动放弃CPU(正常结束,异常结束,挂起阻塞)时才需要进行调度。
在这里插入图片描述
分析调度顺序:

  1. 0时刻:只有进程p1需要调度,p1上CPU进行调度
  2. 7时刻:p1进程结束,7时刻p2,p3,p4进程都到达
  3. 计算p2、p3、p4的响应比:p2([(7-2)+4]/4=2.25)、p3([(7-4)+1]/1=4)、p4([(7-5)+4]/4=1.5),优先调度相应比高的p3
  4. 8时刻:p3进程结束,计算相应比p2(2.5)、p4(1,75)调度p2
  5. 12时刻:p2进程结束,只剩下p4进程,调度p4

优点:

  1. 综合考虑了等待时间与运行时间
  2. 不会导致饥饿问题,长作业随着等待时间的提高,相应比会提高,避免了饥饿问题

前三种算法主要保证公平性,不区分任务的紧急程度对用户的交互性很差

时间片轮转调度算法(RR)

思想:按照进程进入就绪队列的顺序,轮流让进程在CPU中执行一个时间片长度。如果进程在一个时间段内没有完成任务,则剥夺处理机,让这个进程进入就绪队列尾部等待CPU调度。

需要注意:

  1. 时间片轮转调度算法仅仅适合进程调度,不适合作业调度。只有进程才会被系统分配时间片。
  2. 这种调度算法属于抢占式算法,由时钟装置发出时钟中断通知CPU时间片已经到

在这里插入图片描述
设时间片大小为2时

  1. 时刻0,p1进程到达,p1进程被调度
  2. 时刻2,p2进程到达,p1时间片到达,下CPU并到就绪队列尾部,此时就绪队列为p2(队头4)-p1(3),CPU调度p2进程
  3. 时刻4,p3进程到达,p2时间片到,此时就绪队列为p1(队头3)-p3(1)-p2(2),CPU调度p1
  4. 时刻5,p4进程到达,p1时间片未到,此时就绪队列为p1(队头2)-p3(1)-p2(2)-p4(6)
  5. 时刻6,p1时间片到,轮转调度,此时就绪队列为p3(队头1)-p2(2)-p4(6)-p1(1),CPU调度p3进程
  6. 时刻7,p3进程正常结束,CPU进行调度此时就绪队列为p2(队头2)-p4(6)-p1(1),CPU调度p2
  7. 时刻9,p2进程正常退出,此时就绪队列为p4(队头6)-p1(1),CPU调度p4进程
  8. 之后就是这个两个进程在调度,不在赘述

时间片为5的情况不在赘述

需要注意:

如果设置的时间片比较大时,会导致每个进程都在一个时间片内完成,此时时间片轮转调度算法和先进先服务算法调度顺序相同。

时间片大小不适合太大,也不适合太小。太大了会增加进程响应的时间,太小了回到是进程切换频繁,系统开销增大

优点:

  1. 对于每个进程来讲公平
  2. 进程响应快
  3. 不会导致饥饿问题

缺点

  1. 用于进程切换时有开销
  2. 不区分任务的紧急程度

优先级调度算法

思路:每个作业/进程有各自的优先级,调度时选择优先级最高的作业/进程

这个算法既可以用在进程调度,也可以用于作业调度(同时也适用于IO调度)

优先级调度算法可以由抢占式,也可以有非抢占式

  • 非抢占式只需在进程主动放弃处理机时进行调度即可
  • 抢占式还需在就绪队列变化时,检查是否会发生抢占。

在这里插入图片描述
非抢占式调度图:
在这里插入图片描述
抢占式优先级调度算法:
在这里插入图片描述

需要注意:

  1. 就绪队列不一定只有一个,可以按照优先级来组织就绪队列(把优先级高的进程放在靠近队头的位置)
  2. 根据优先级是否可以动态改变,可将优先级分为静态优先级和动态优先级两种。(动态优先级在运行时优先级可能改变,静态优先级在进程创建后不会改变)
  3. IO繁忙进程优先级比计算繁忙进程优先级高,让IO繁忙进程快速运行,使IO设备能尽快的于CPU并行运行,提高系统吞吐量
  4. 系统进程优先级比用户优先级高

优点:

  1. 区分进程的优先级,可以灵活的处理各个进程或作业

缺点:

  1. 如果有很多优先级比较高的进程到来,可能会导致饥饿问题

多级反馈队列调度算法

这种算法是上述几种调度算法的综合
具体思路:

  1. 设置多级就绪队列,各级队列优先级从高到低,时间片从小到大
  2. 新进程到达时先进入第1级队列,按FCFS原则排队等待被分配时间片,若用完时间片进程还未结束,则进程进入下一级队列队尾。如果此时已经是在最下级的队列,则重新放回该队列队尾
  3. 只有第k级队列为空时,才会为k+1级队头的进程分配时间片

这种算法只适用于进程调度,不适用于作业调度。

此外这种调度算法属于抢占式调度算法
在这里插入图片描述
调度分析:

  1. 0时刻,此时只有p1进程,p1进程在第一级队列被调度
    在这里插入图片描述

  2. 时刻1,此时p2进程到达,p1进程时间片到,p1进程到第二级队列队尾。p2进程进入第一级队列队尾。CPU处理p2进程
    在这里插入图片描述

  3. 时刻2,此时p2进程时间片到达,进入第二级别队列队尾
    在这里插入图片描述

  4. 此时第一级别队列为空,为第二级别队列分配时间片,此时p1在队头,CPU调度p1进程

  5. 时刻4,p1时间片到,执行调度算法,CPU调度p2进程
    在这里插入图片描述

  6. 时刻5,进程p3进程到达,p3进入第一级队列,p2被抢占,p2回到原来队列的队尾,CPU调度p3
    在这里插入图片描述

之后的调度过程与上面类似,就不在赘述了

最终调度顺序为:

P1(1)->P2(1)->P1(2)->P2(1)->P3(1)->P2(2)->P1(4)->P1(1)

优点:

  1. 对各类进程相对公平
  2. 进程响应比较快
  3. 短进程响应快,长进程也能得到积极的响应
  4. 进程具有优先级

缺点:

  1. 短进程如果很多的话,优先级低的进程会导致饥饿问题。

多级队列调度算法

思路:进程被后会对进程进行分类。不同类别的进程优先级不同
在这里插入图片描述

队列之间可以采用时间片轮转调度。
eg:如三个队列分配时间50%、40%、10%

每个队列自身可以采用上述的各种不同的调度算法

eg:

  • 系统进程队列采用优先级调度
  • 交互式队列采用RR
  • 批处理队列采用FCFS
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Python中,可以使用不同的算法来实现车间调度。下面是一些常见的车间调度算法的Python实现示例: 1. 贪心算法: ```python def greedy_scheduling(jobs): jobs = sorted(jobs, key=lambda x: x[1]) # 按工序的优先级进行排序 schedule = [] for job in jobs: start_time = max(job[0], schedule[-1][1]) if schedule else job[0] end_time = start_time + job[2] schedule.append((job[0], end_time)) return schedule ``` 2. 遗传算法: ```python import random def genetic_scheduling(jobs, population_size, generations): population = [random.sample(jobs, len(jobs)) for _ in range(population_size)] # 随机生成初始种群 for _ in range(generations): fitness_scores = [fitness(job_order) for job_order in population] # 计算每个个体的适应度 elite_population = [population[i] for i in sorted(range(population_size), key=lambda x: fitness_scores[x], reverse=True)[:population_size // 2]] # 选择适应度较高的个体作为精英个体 offspring_population = [] while len(offspring_population) < population_size - len(elite_population): parent1, parent2 = random.sample(elite_population, 2) # 随机选择两个父代个体 child = crossover(parent1, parent2) # 交叉产生子代 offspring_population.append(mutate(child)) # 随机变异子代 population = elite_population + offspring_population best_job_order = max(population, key=lambda x: fitness(x)) # 选择适应度最高的个体作为最优解 return best_job_order def fitness(job_order): # 计算个体的适应度 # 根据工序顺序计算总生产时间、成本等指标,并将其作为适应度评价 pass def crossover(parent1, parent2): # 交叉产生子代 pass def mutate(child): # 变异子代 pass ``` 3. 模拟退火算法: ```python import math import random def simulated_annealing_scheduling(jobs, initial_temperature, cooling_rate, num_iterations): current_solution = random.sample(jobs, len(jobs)) # 随机生成初始解 best_solution = current_solution.copy() current_cost = calculate_cost(current_solution) # 计算当前解的成本 best_cost = current_cost for i in range(num_iterations): temperature = initial_temperature / (1 + cooling_rate * i) # 更新温度 new_solution = get_neighbor(current_solution) # 获得当前解的邻居解 new_cost = calculate_cost(new_solution) # 计算邻居解的成本

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NUC_Dodamce

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

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

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

打赏作者

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

抵扣说明:

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

余额充值