练习0:填写已有实验
请把你做的实验2/3/4/5的代码填入本实验中代码中有“LAB1”/“LAB2”/“LAB3”/“LAB4”“LAB5”的注释相应部分。并确保编译通过。注意:为了能够正确执行lab6的测试应用程序,可能需对已完成的实验1/2/3/4/5的代码进行进一步改进。
1 | 复制以下文件 其中 proc.c 和 trap.c 需要进行修正 |
练习1: 使用 Round Robin 调度算法
完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件)个人完成的lab5和练习0完成后的刚修改的lab6之间的区别,分析了解lab6采用RR调度算法后的执行过程。执行make grade,大部分测试用例应该通过。但执行priority.c应该过不去。
请在实验报告中完成:
- 请理解并分析sched_calss中各个函数指针的用法,并接合Round Robin 调度算法描述ucore的调度执行过程
1 | // 初始化算法所需要的数据结构 |
Round Robin 调度执行过程
1 | 设置当前进程剩余时间片 |
- 请在实验报告中简要说明如何设计实现”多级反馈队列调度算法”,给出概要设计,鼓励给出详细设计
1 | Multilevel Feedback queues(MLFQ) 的思想 |
练习2: 实现 Stride Scheduling 调度算法
首先需要换掉RR调度器的实现,即用default_sched_stride_c覆盖default_sched.c。然后根据此文件和后续文档对Stride度器的相关描述,完成Stride调度算法的实现。
请在实验报告中简要说明你的设计实现过程。
1 | proc.c: |
这里只实现了用 Priority Queue 作为 stride 调度算法所使用的数据结构
用 list 也是可以的 只不过查找 删除的时候 会随着进程数目的增加而呈现出线性关系
1 | // 就是 32位系统下 int 的最大值 2147483647 |
BIG_STRIDE 的值是怎么来的?
Stride 调度算法 的思路是 每次找 stride步进值最小的进程
每个进程 每次执行完以后 都要在 stride步进 += pass步长
其中 步长 是和 优先级成反比的 因此 步长可以反映出进程的优先级
但是随着每次调度 步长不断增加 有可能会有溢出的风险
因此 需要设置一个步长的最大值 使得他们哪怕溢出 还是能够进行比较
在 uCore 中 BIG_STRIDE 的值是采用 无符号32位整数表示 而 stride 也是无符号32位整数
也就是说 最大值只能为 (2^32 - 1)
如果一个 进程的 stride 已经为 (2^32 -1)
时 那么再加上 pass步长 一定会溢出 然后又从0开始算
这样 整个调度算法的比较 就没有意义了
这说明 我们必须得约定一个 最大的步长 使得两个进程的步进值哪怕其中一个溢出 或者都溢出 还能够进行比较
首先 因为 步长 和 优先级成反比 可以得到下面一条pass = BIG_STRIDE / priority <= BIG_STRIDE
进而得到pass_max <= BIG_STRIDE
最大步长 - 最小步长 一定小于等于步长max_stride - min_stride <= pass_max
所以得出max_stride - min_stride <= BIG_STRIDE
前面说了 uCore 中 BIG_STRIDE 用的 无符号32位整数 最大值只能为 (2^32 - 1)
而 又因为是无符号的 因此 最小 只能为 0 而且我们需要把32位无符号整数进行比较 需要保证任意两个进程stride的差值在32位有符号数能够表示的范围之内 故 BIG_STRIDE 为 (2^32 - 1) / 2
最后还是实验结果