mirror of
https://github.com/LearningOS/rust-based-os-comp2022.git
synced 2026-02-09 05:14:46 +08:00
Merge branch 'main' of github.com:LearningOS/rust-based-os-comp2022 into main
This commit is contained in:
@@ -32,20 +32,20 @@ ch3 中我们实现的调度算法十分简单。现在我们要为我们的 os
|
||||
|
||||
算法描述如下:
|
||||
|
||||
(1) 为每个进程设置一个当前 stride,表示该进程当前已经运行的“长度”。另外设置其对应的 pass
|
||||
值(只与进程的优先权有关系),表示对应进程在调度后,stride 需要进行的累加值。
|
||||
(1) 为每个进程设置一个当前 pass,表示该进程当前已经运行的“长度”。另外设置其对应的 stride
|
||||
值(只与进程的优先权有关系),表示对应进程在调度后,pass 需要进行的累加值。
|
||||
|
||||
(2) 每次需要调度时,从当前 runnable 态的进程中选择 stride 最小的进程调度。对于获得调度的进程 P,将对应的 stride 加上其对应的步长 pass。
|
||||
(2) 每次需要调度时,从当前 runnable 态的进程中选择 pass 最小的进程调度。对于获得调度的进程 P,将对应的 pass 加上其对应的步长 stride。
|
||||
|
||||
(3) 一个时间片后,回到上一步骤,重新调度当前 stride 最小的进程。
|
||||
(3) 一个时间片后,回到上一步骤,重新调度当前 pass 最小的进程。
|
||||
|
||||
可以证明,如果令 P.pass = BigStride / P.priority 其中 P.priority 表示进程的优先权(大于 1),而
|
||||
可以证明,如果令 P.stride = BigStride / P.priority 其中 P.priority 表示进程的优先权(大于 1),而
|
||||
BigStride 表示一个预先定义的大常数,则该调度方案为每个进程分配的时间将与其优先级成正比。证明过程我们在这里略去,有兴趣的同学可以在网上查找相关资料。
|
||||
|
||||
其他实验细节:
|
||||
|
||||
- stride 调度要求进程优先级 :math:`\geq 2`,所以设定进程优先级 :math:`\leq 1` 会导致错误。
|
||||
- 进程初始 stride 设置为 0 即可。
|
||||
- 进程初始 pass 设置为 0 即可。
|
||||
- 进程初始优先级设置为 16。
|
||||
|
||||
为了实现该调度算法,内核还要增加 set_prio 系统调用
|
||||
@@ -62,7 +62,7 @@ BigStride 表示一个预先定义的大常数,则该调度方案为每个进
|
||||
|
||||
- 你可以在TCB加入新的字段来支持优先级等。
|
||||
- 为了减少整数除的误差,BIG_STRIDE 一般需要很大,但为了不至于发生反转现象(详见问答作业),或许选择一个适中的数即可,当然能进行溢出处理就更好了。
|
||||
- stride 算法要找到 stride 最小的进程,使用优先级队列是效率不错的办法,但是我们的实验测例很简单,所以效率完全不是问题。事实上,很推荐使用暴力扫一遍的办法找最小值。
|
||||
- stride 算法要找到 pass 最小的进程,使用优先级队列是效率不错的办法,但是我们的实验测例很简单,所以效率完全不是问题。事实上,很推荐使用暴力扫一遍的办法找最小值。
|
||||
- 注意设置进程的初始优先级。
|
||||
|
||||
.. attention::
|
||||
@@ -152,38 +152,38 @@ BigStride 表示一个预先定义的大常数,则该调度方案为每个进
|
||||
|
||||
stride 算法深入
|
||||
|
||||
stride 算法原理非常简单,但是有一个比较大的问题。例如两个 pass = 10 的进程,使用 8bit 无符号整形储存
|
||||
stride, p1.stride = 255, p2.stride = 250,在 p2 执行一个时间片后,理论上下一次应该 p1 执行。
|
||||
stride 算法原理非常简单,但是有一个比较大的问题。例如两个 stride = 10 的进程,使用 8bit 无符号整形储存
|
||||
pass, p1.pass = 255, p2.pass = 250,在 p2 执行一个时间片后,理论上下一次应该 p1 执行。
|
||||
|
||||
- 实际情况是轮到 p1 执行吗?为什么?
|
||||
|
||||
我们之前要求进程优先级 >= 2 其实就是为了解决这个问题。可以证明, **在不考虑溢出的情况下** , 在进程优先级全部 >= 2
|
||||
的情况下,如果严格按照算法执行,那么 STRIDE_MAX – STRIDE_MIN <= BigStride / 2。
|
||||
的情况下,如果严格按照算法执行,那么 PASS_MAX – PASS_MIN <= BigStride / 2。
|
||||
|
||||
- 为什么?尝试简单说明(不要求严格证明)。
|
||||
|
||||
- 已知以上结论,**考虑溢出的情况下**,可以为 Stride 设计特别的比较器,让 BinaryHeap<Stride> 的 pop
|
||||
方法能返回真正最小的 Stride。补全下列代码中的 ``partial_cmp`` 函数,假设两个 Stride 永远不会相等。
|
||||
- 已知以上结论,**考虑溢出的情况下**,可以为 pass 设计特别的比较器,让 BinaryHeap<Pass> 的 pop
|
||||
方法能返回真正最小的 Pass。补全下列代码中的 ``partial_cmp`` 函数,假设两个 Pass 永远不会相等。
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
use core::cmp::Ordering;
|
||||
|
||||
struct Stride(u64);
|
||||
struct Pass(u64);
|
||||
|
||||
impl PartialOrd for Stride {
|
||||
impl PartialOrd for Pass {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Stride {
|
||||
impl PartialEq for Pass {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
TIPS: 使用 8 bits 存储 stride, BigStride = 255, 则: ``(125 < 255) == false``, ``(129 < 255) == true``.
|
||||
TIPS: 使用 8 bits 存储 pass, BigStride = 255, 则: ``(125 < 255) == false``, ``(129 < 255) == true``.
|
||||
|
||||
报告要求
|
||||
------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user