3.3 进程调度
L16
学习目标
绝对装入、可重定位、动态;对照本课 ld 脚本与 esp_app_desc 镜像。
- 链接脚本定 VMA/LMA。
- bootloader 装入 app 段。
- SOWL:片上 SRAM + Flash。
- 速度与容量权衡。
- 四条件:互斥、占有且等待、不可抢占、循环等待。破坏任一条件即可预防。
- 银行家算法用安全序列避免进入不安全状态,实现代价高,适合动画理解。
- 固件实例:任务 A 持 UART 锁等 GPIO,任务 B 持 GPIO 锁等 UART。超时放弃是工程折中。
- Tick 推进 Delay 唤醒。
原理 · 深入理解
3.3 进程调度
本节概览:先建立「进程调度」的框架,再依次展开下列小节。
- 进程调度的任务、机制和方式
- 轮转调度算法
- 优先级调度算法
- 多队列调度算法
- 多级反馈队列(multileved feedback queue)调度算法
- 基于公平原则的调度算法
3.3.1 进程调度的任务、机制和方式
进程调度机制由排队器和分派器等组成。每当一个进程转为就绪状态,排队器就把它插入相应就绪队列;分派器则依据调度程序选定的进程,将其从就绪队列取出,并在分派器与新进程之间进行上下文切换。
通过这两个部件的配合,完成从就绪队列到处理机的调度流程。
进程转为就绪时插入相应就绪队列。
取出选定进程并进行上下文切换。
非抢占方式(Nonpreemptive Mode):一旦把处理机分配给某进程,就一直让它运行下去,不会因时钟中断或任何其它原因抢占,直至该进程完成或因某事件被阻塞,才把处理机分配给其它进程。
抢占方式(Preemptive Mode):允许调度程序根据某种原则暂停正在执行的进程,把处理机重新分配给另一进程。抢占方式较复杂,系统开销也较大。
非抢占方式:分配后不抢占,直至完成或阻塞
抢占方式:按原则可暂停当前进程,开销较大
进程调度的任务包括三步:保存当前进程的处理机现场信息(程序计数器、通用寄存器等);按某种算法从就绪队列中选取一个进程并将其状态改为运行;由分派程序把处理器分配给该进程,将其 PCB 中现场信息装入处理器寄存器,把控制权交给它从断点恢复运行。
保存程序计数器、通用寄存器等现场。
从就绪队列选一进程,置为运行状态。
装入 PCB 现场,从断点恢复运行。
3.3.2 轮转调度算法
轮转(RR)法:所有就绪进程按 FCFS 排成队列,系统每隔一定时间产生中断,把 CPU 分给队首进程执行一个时间片。时间片用完换下一个队首进程。
这样保证就绪队列中所有进程在确定时间内都能获得一个时间片的处理机时间。
RR 调度中进程切换的两种情况:① 时间片未用完进程就完成了,立即激活调度程序;② 时间片用完时计时器中断被激活,进程尚未完成则送往就绪队列尾部。
时间片大小对系统性能影响很大。时间片太小导致频繁切换开销大;太大则退化为 FCFS。
结合图 3-3(q=1 和 q=4 时进程的周转时间)理解时间片大小对性能的影响。
3.3.3 优先级调度算法
优先级调度算法把处理机分给就绪队列中优先级最高的进程,分为两种。
- 非抢占式优先级调度:分配后一直执行到完成或放弃处理机
- 抢占式优先级调度:执行中出现更高优先级进程就抢占
静态优先级在创建进程时确定,运行期间不变,用整数(优先数)表示。确定依据有三个。
- 进程类型
- 进程对资源的需求
- 用户要求
3.3.4 多队列调度算法
多队列调度算法将系统中的就绪队列从一个拆分为若干个,把不同类型或性质的进程固定分配到不同就绪队列。不同就绪队列可采用不同调度算法,一个队列中的进程可设置不同优先级,不同队列本身也可设置不同优先级。
由于设置多个就绪队列,每个队列可实施不同调度算法,系统针对不同用户需求很容易提供多种调度策略。
优点:可为不同类型进程提供多种调度策略
3.3.5 多级反馈队列(multileved feedback queue)调度算法
多级反馈队列调度算法的机制。
- 设置多个就绪队列,优先级从高到低
- 每个队列采用 FCFS 算法
- 按队列优先级调度
如果第一个队列的时间片略大于多数人机交互所需处理时间,便能较好满足各类用户。
- 终端型用户
- 短批处理作业用户
- 长批处理作业用户
3.3.6 基于公平原则的调度算法
实施公平调度算法时系统必须具备的功能。
- 跟踪计算每个进程已执行的处理时间
- 计算每个进程应获得的处理机时间(自创建以来时间除以 n)
- 计算进程获得处理机时间的比率
公平调度的执行方法。
- 比较各进程获得处理机时间的比率,选择比率最小的进程运行
- 该进程运行直到超过最接近它的进程比率为止
做 · 实验
- 根据「学习目标」列出 3 个关键词,对照原理段落解释给自己听。
- 编译 Delay 实验,观察串口周期性输出。
- 对照预备篇裸机实验,用自己的话写出两种延时对 CPU 的影响。
进程调度
deadlock-banker
mem-hierarchy
用控件单步操作;日志区记下每一步发生了什么。
代码导读
本课在工作台编译烧录。先读 user 实验入口,再对照 kernel / HDF 中被调用的函数,不要一上来改链接脚本。
总结与提升
- 能说出 Flash 与 DRAM 在链接中的角色。
- 能用自己的话复述学习目标,并指出概念与板上实验的对应。
- 能画出嵌入式常见两级(SRAM/Flash)。
- 能默写死锁四条件,并举一个固件中的例子。
- 能叙述 Delay 从阻塞回到就绪的路径。
- 能对比裸机忙等与本课 Delay。
- 能指出抢占发生的条件。
延伸思考
- 为何 app 起始常是 0x42000020?
- 如果把本节机制拿到 Linux 或完整 OpenHarmony 上,会多出哪些硬件假设?
- 为何固件代码放 Flash 还可在 IRAM 执行热路径?
- 超时放弃算不算「解除死锁」?