上传者: 66454750
|
上传时间: 2025-06-19 17:09:52
|
文件大小: 1.15MB
|
文件类型: DOC
### 操作系统实验——线程的调度
#### 实验背景及目标
本次实验旨在通过实践操作,使学生深入了解操作系统中的线程调度机制,特别是优先级调度策略。通过一系列的步骤,包括修改现有代码来实现线程的静态优先级与动态优先级,并基于此设计并实现一种优先级调度算法。实验完成后,学生应能够掌握以下知识点:
1. **线程优先级的基本概念**:了解线程优先级的概念及其分类。
2. **静态优先级与动态优先级的区别**:理解两种优先级的不同之处以及它们是如何影响线程调度的。
3. **优先级调度算法的设计与实现**:学会如何设计并实现一个简单的优先级调度算法。
#### 实验内容详解
1. **静态优先级 (nice)**:静态优先级是指为线程设置的一个初始优先级值,它通常不会随着时间或线程的行为而改变。除非通过特定的系统调用如 `setpriority` 进行手动调整。在这个实验中,我们将通过以下几个步骤实现静态优先级:
- 在 `struct tcb` 结构体中添加一个新的成员变量 `nice`,代表线程的静态优先级。
- 初始化新创建的线程时,默认将 `nice` 设置为0。
- 提供系统调用 `sys_getpriority` 和 `sys_setpriority` 来获取和设置线程的静态优先级。
2. **动态优先级 (priority)**:动态优先级是系统根据线程的使用情况(例如CPU使用时间)和当前系统负荷自动计算出的优先级。为了实现动态优先级的计算,我们需要执行以下操作:
- 在 `struct tcb` 结构体中增加两个新成员变量:`estcpu` 和 `priority`。
- `estcpu` 记录线程最近使用的CPU时间量。
- `priority` 代表线程的动态优先级,其计算公式为:`priority = PRI_USER_MAX - (estcpu / 4) - (nice * 2)`,其中 `PRI_USER_MAX` 定义了最高可能的用户线程优先级,`estcpu` 是线程最近使用的CPU时间量,`nice` 是线程的静态优先级。
- 动态优先级的计算需要考虑系统当前的平均负荷,因此引入全局变量 `g_load_avg` 来跟踪系统的平均负荷。
3. **全局变量 `g_load_avg`**:这个变量用于存储系统的平均负荷。系统负荷会影响线程的动态优先级计算,因此我们定期更新这个值。具体的实现方法如下:
- 在定时器中断处理程序中更新 `g_load_avg`。
- 每秒更新一次 `g_load_avg` 的值,公式为:`g_load_avg = (59/60) * g_load_avg + (1/60) * nready`,其中 `nready` 表示处于就绪状态的线程数量。
4. **优先级调度算法的实现**:在完成以上准备工作后,我们可以修改 `schedule` 函数以实现优先级调度算法。具体步骤如下:
- 在 `schedule` 函数中计算每个线程的动态优先级 `priority`。
- 根据优先级选择下一个要执行的线程。
- 特别需要注意的是,`task0`(即线程0)是一个特殊线程,只有在没有其他可运行线程的情况下才会被调度执行。
5. **测试与验证**:最后一步是测试实现的调度算法是否正确工作。可以通过编写测试脚本或使用现有的测试框架来验证线程调度的行为是否符合预期。
#### 实验环境
- **编译器**:GCC
- **链接器**:LD
- **调试器**:GDB
- **模拟器**:QEMU
#### 实验步骤总结
1. **添加静态优先级字段**:在 `struct tcb` 中添加 `nice` 字段,并初始化。
2. **增加系统调用**:实现 `sys_getpriority` 和 `sys_setpriority` 以获取和设置线程的静态优先级。
3. **增加动态优先级相关字段**:在 `struct tcb` 中添加 `estcpu` 和 `priority` 字段。
4. **实现全局变量 `g_load_avg`**:用于跟踪系统的平均负荷。
5. **计算属性**:在定时器中断处理函数中计算 `g_load_avg` 和线程的 `estcpu`。
6. **修改调度函数**:在 `schedule` 函数中实现优先级调度算法。
7. **测试调度器**:编写测试脚本来验证调度算法的正确性。
通过以上步骤的学习与实践,学生不仅能够深入了解线程调度机制,还能掌握如何在实际操作系统中实现这些机制。这对于未来从事操作系统开发或研究的学生来说是非常宝贵的实践经验。