1、背景
1.1 上下文切换
- 切换cpu的当前任务,从一个进程/线程到另一个
- 保存当前的进程/线程在PCB/TCP中的执行状态
- 读取下一个进程/线程的上下文
1.2 CPU调度
- 从就绪队列中挑选一个进程/线程作为CPU将要运行的下一个进程/线程
- 调度程序:挑选线程/线程的内核函数(通过一些调度策略)
- 什么时候进行调度
- 从一个状态切换到另一个状态(尤其是和运行有关的状态变化)会触发调度
1.3 内核运行调度程序的条件(满足一条即可)
- 一个进程从运行状态切换到等待状态
- 一个进程被终结了
- 用户态进程
- 不可抢占
- 调度程序必须等待时间结束:确保进程一旦启动就不可打断–>导致其他进程必须等待该进程执行完之后才能执行–>可能导致效率不高问题
- 例如Windows中某个进程因为某种原因不得不处于组织/等待状态,这时候其他进程也必须等待该进程执行
- 可以抢占
- 操作系统可以决定执行进程的切换
- 调度程序在中断响应后执行
- 当前的进程从运行切换到就绪,或者一个进程从等待切换到就绪
- 当前的进程可以被换出
- 不可抢占
- 以上抢占策略针对的是,而内核中也存在“是否可以抢占”
- 一个进程执行系统调用,如果这个进程自身不会导致这个进程处于等待状态(持续运行),那么就不会出现抢占现象(切换)–>内核的不可抢占
- 某种系统调用是由某个进程发起的,由于某事件的产生,需要把当前内核的进程切换到优先级更高的进程去执行,一旦系统调用返回就可能到另一种进程–>抢占式内核
- 早期的操作系统都不太支持用户级的抢占,现在的基本支持,使系统更加灵活高效
1.4 CPU调度时间
?
2、调度原则
选择进程的依据。
2.1 执行模型:程序在CPU突发和I/O中交替
- 对于一个进程而言,CPU的运行曲线一般是波浪形状。因为在频繁运算的时候,CPU使用率高;而在I/O读取的时候(较慢),CPU处于闲置状态,占有率下降。所以最理想的状态是,在CPU占有率低的时候执行其他进程,使得整个系统的执行效率高
- 每一个调度决定都是关于在下一个CPU突发时将哪一个工作交给CPU
- 在时间分片机制下,线程可能结束当前CPU突发前被迫放弃CPU
2.2 可量化的评价指标
- CPU使用率:CPU处在忙状态所占时间的百分比
- 吞吐量:在单位时间内完成的进程数量
- 周转时间:一个进程从初始化到结束,包括所有等待时间所花费的时间(等待时间+执行时间)
- 等待时间:进程在就绪队列中的总时间(指就绪态进程,不是等待阻塞进程唤醒的时间)
- 响应时间:从一个请求被提交到产生第一次响应所花费的总时间
2.3 含糊的指标–“更快的服务”
- 低延迟
- 高宽带
评价标准之间存在矛盾,需要做折中,即需要选择各个评价指标的中间态,以满足不同的需求。
2.4 调度策略
CPU使用率、吞吐量尽量大,周转时间、等待时间、响应时间尽量小
- 减少响应时间:及时处理用户的输出并尽快将输出提供给用户
- 减少平均响应时间的波动:在交互系统中,可预测性比高差异低平均更重要
- 减少吞吐量–两方面
- 减少开销(操作系统开销,上下文切换)
- 系统资源的高效利用(CPU,I/O设备)
- 减少等待时间:减少每一个进程的等待时间
2.5 吞吐量vs延迟
- 低延迟调度增加了交互式表现:如果移动了鼠标,但是屏幕中的光标却没动,用户可能会重启电脑
- 但是操作系统需要保证吞吐量不受影响:我想要结束长时间编程,所以操作系统必须不时进行调度,及时存在许多交互任务
- 吞吐量是操作系统的计算带宽
- 响应时间是操作系统的计算延迟
- 例如Linux,针对Desktop和service的调度算法是不同的
2.6 公平的目标
- 确保进程都能公平地得到CPU的服务(等待时间、执行时间
- 为了解决多进程系统中每一个进程都能及时得到CPU服务
- 公平通常会增加平均响应时间
3、通用计算机的调度算法
先到先服务 FCFS(first come,first served)
- 如果进程在执行中阻塞,队列中的下一个会得到CPU
- 前面进程执行时间长,会导致后面进程等很长时间才能处理–>导致整个系统的响应时间慢
- 优点:简单
- 缺点:
- 平均等待时间波动较大
- 花费时间少的任务可能排在花费时间长的任务后面
- 可能导致I/O和CPU之间的重叠处理:CPU密集型进程会导致I/O设备闲置时,I/O密集型进程也在等待
短进程优先(短作业优先)短剩余时间优先 SPN(SJF) SRT:对基本调度的优化
将执行时间短的时间放在前面 – >短进程/短任务优先
- 按照预测的完成时间来将任务入队
- 可以是可抢占的或者不可抢占的
- 可抢占又叫SRT(最短剩余时间):当执行着的进程比刚加入进程执行时间长时,发生切换
- 不可抢占:SPN
- 得到最优平均等待时间
问题:
- 可能导致饥饿
- 连续的短任务流会使长任务饥饿
- 短任务可用时,任何长任务的CPU时间都会增加平均等待时间
- 需要预知未来
- 怎么预估下一个CPU突发的持续时间:简单的解决方法–>询问用户–>如果用户欺骗就杀死进程–>如果用户不知道?
- 通过公式用历史预估下一时刻的执行情况
最高响应比优先 HRRN(highest response ratio next)
- 比之前的算法多考虑了等待时间
- 在SPN调度基础上改进
- 不可抢占
- 关注进程等待了多长时间
- 防止无限期推迟
- 公式:
R = (w + s)/s
w:waiting time 等待时间;s:service time 执行时间;R越大表示等待时间越长,选择R值最高的进程
- 依然需要预估程序的执行时间
轮循 Round Robin
- 在叫作量子(或时间切片)的离散单元中分配处理器
- 时间片结束时,切换到下一个准备好的进程
- 例如设置时间片为20,进程p1耗时49,p2耗时20,p3耗时50。第一轮执行的时候p1还剩29,p2结束,p3还剩30,继续按时间片执行
- 主要特点是公平,平均等待时间还是比较大的
评估
- 花销:额外的上下文切换
- 时间片大小不同,平均等待时间也不一定相同
- 如果时间量子太大:等待时间过长;极限情况退化成FCFS
- 如果时间量子太小:反应迅速;吞吐量由于大量的上下文切换开销受到影响
- 目标:选择一个合适的时间量子;经验规则:维持上下文切换开销处于1%以内
优化策略:
- 就绪队列被划分成独立的队列(e.g.前台(交互),后台(批处理))
- 每一个队列拥有自己的调度策略(e.g.前台-RR,后台-FCFS)
- 调度必须在队列间进行
- 固定优先级:先处理前台后处理后台;可能导致饥饿
- 时间切片:每一个队列都能得到一个确定能够调度其他进程的CPU总时间;e.g.80%给使用RR的前台;20%给使用FCFS的后台
多级反馈队列 Multilevel Feedback Queues
- 一个进程可以在不同的队列中移动:根据进程的特征动态调整
- 例如:n级优先级-优先级调度在所有级别中,RR在每一个级别中
- 时间量子大小随优先级级别增加而增加
- 如果任务在当前的时间量子中没有完成,则降到下一个优先级
- 优点:
- CPU密集型任务的优先级降得很快
- I/O密集型任务停留在高优先级(交互式进程得到较快响应)
公共共享调度 Fair Share Scheduling
FFS控制用户对系统资源的访问
- 一些用户组比其他用户组更重要
- 保证不重要的组无法垄断资源
- 未使用的资源按照每个组所分配的资源的比例来分配
- 没有达到资源使用率目标的组获得更高的优先级
- 例子:Linux
对各种调度算法的评价:
- 确定性模型:确定一个工作量,然后计算每一个算法的表现
- 队列模型:用来处理随机工作负载的数学方法
- 实现/模拟:建立一个允许算法运行实际数据的系统;最灵活/具有一般性
总结
- FCFS:不公平,平均等待时间较差
- SPN/SRT:
- 不公平,但是平均等待时间最小
- 需要精确预测计算时间
- 可能导致饥饿
- HRRN:
- 基于SPN调度改进
- 不可抢占
- RR:公平,但是平均等待时间较差
- MLFQ:与SPN相似
- FFS:公平是第一要素
4、实时调度
实时系统
- 实时系统一般用于工业控制,如火车、机床、嵌入式工厂的运行环境中,程序需要按照规定的时间完成。
- 定义:正确性依赖于其时间和功能两方面的一种操作系统
- 性能指标:时间约束的及时性(deadlines);速度和平均性能相对不重要
- 主要特性:时间约束的可预测性
硬实时系统:需要在保证的时间内完成重要的任务,必须完成
软实时系统:需要重要的进程的优先级更高,尽量完成,并非必须
任务(工作单元):一次计算,一次文件读取,一次信息传递等等
属性:取得进展所需要的资源;定时参数
可调度性
设置一个满足deadline要求的实时系统
- 决定实时任务执行的顺序
- 两大类调度算法
- 静态优先级调度
- 动态优先级调度
RM(Rate Monotonic)速率单调调度 – 静态优先级调度算法
- 最佳静态优先级调度
- 通过周期安排优先级
- 周期越短优先级越高
- 执行周期最短的任务
EDF(Earliest Deadline First)最早期限调度 – 动态优先级调度算法
- 最佳的动态优先级调度
- Deadline越早优先级越高
- 执行Deadline最早的任务
5、多处理器调度
多处理器的CPU调度更加复杂
- 多个相同的单处理器组成一个多处理器
- 优点:负载共享
对称多处理器(SMP)
- 每一个处理器运行自己的调度程序
- 需要在调度程序中同步
6、优先级反转
低优先级任务影响高优先级任务的现象
例如:a>b>c,执行到c的时候a需要等c执行完才能执行,而c的优先级低于b,b可以抢占c,那么就会导致c执行切换到b最终才到a。操作系统会认为当前系统不稳定而进行重启
解决方法:
- 优先级继承:低优先级任务继承高优先级任务的优先级依赖于他们的共享资源。(提高c的优先级等同于a,保证b无法抢占c
- 优先级天花板:一开始就进行资源统计,把资源也定为优先级。资源的优先级和所有可以锁定该资源的任务中优先级最高的任务的优先级相同
- 除非优先级高于系统中所有被锁定的资源的优先级上限,否则任务尝试执行临界区的时候会被阻塞
- 持有最高优先级上限信号量锁的任务,会继承该锁所阻塞的任务的优先级