pintos Lab1 实验报告
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第 4 页 共 14 页
华东师范大学软件学院实验报告
和 release 之时)。 3. 在对一个线程进行优先级设置的时候,如果这个线程处于被捐赠状态,则对 ori_priority 进行设置, 然后如果设置的优先级大于当前优先级,则改变当前优先级,否则在 捐赠状态取消的时候恢复 ori_priority。 4. 在释放锁对一个锁优先级有改变的时候应考虑其余被捐赠优先级和当前优先级。 5. 将信号量的等待队列实现为优先级队列。 6. 将 condition 的 waiters 队列实现为优先级队列。 7. 释放锁的时候若优先级改变则可以发生抢占。 代码实现: 由于对 thread 类改动较大,直接贴出整个类(也包含了 Part3 中的部份):
完成 Part1 所得结果如下:
Part2: Priority Scheduling 实现思路: 1. 在一个线程获取一个锁的时候,如果拥有这个锁的线程优先级比自己低就提高它的 优先级,并且如果这个锁还被别的锁锁着,将会递归地捐赠优先级,然后在这个线程释放掉 这个锁之后恢复未捐赠逻辑下的优先级。 2. 如果一个线程被多个线程捐赠,维持当前优先级为捐赠优先级中的最大值(acquire
三、实验环境 操作系统:Ubuntu 18.04 软件要求:VScode、GCC、GNU、Perl、QEMU、X、Bochs
四、实验过程与分析 Part1: Alarm Clock 实现思路: 调用 timer_sleep 的时候直接把线程阻塞掉,然后给线程结构体加一个成员 blocked_ticks 来记录这个线程被 sleep 了多少时间, 然后利用操作系统自身的时钟中断(每 个 tick 会执行一次)加入对线程状态的检测, 每次检测将 blocked_ticks 减 1, 如果减到 0 就 唤醒这个线程。 首先在 thread.h 中线程类中加入:
在 tick 中 thread_foreach 要对每个线程都执行 check_blocked_ticks()以确定是否将他们激活。
1. void check_blocked_ticks(struct thread *t,void *aux){ 2. if (t->status==THREAD_BLOCKED && t->blocked_ticks>0) { 3. t->blocked_ticks--; 4. if (t->blocked_ticks==0) { 5. thread_unblock(t); 6. } 7. } 8. }
改动后的 timer_sleep():
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. void timer_sleep (int64_t ticks) { if (ticks<=0) return; enum intr_level old_level; old_level=intr_disable(); thread_current ()->blocked_ticks=ticks; thread_block(); intr_set_level(old_level); }
第 2 页 共 14 页
华东师范大学软件学院实验报告
会将在 "thread.h" 中声明的 thread_ mlfqs 设置为 true,这在 main () 中发生。启用 bsd 计划 程序后, 线程将不再直接控制自己的优先级。应忽略对 thread_ create () 的优先级参数, 以及 对 thread_ set _priority () 的任何调用, 而 thread_ get _ priority() 应返回由计划程序设置的线 程的当前优先级。在以后的任何项目中都不使用高级计划程序。
int64_t blocked_ticks;
并添加 block 状态:
1. enum thread_status 2. { 3. THREAD_RUNNING, 4. THREAD_READY, 5. THREAD_BLOCKED, 6. THREAD_DYING 7. };
/* /* /* /*
Running thread. */ Not running but ready to run. */ Waiting for an event to trigger. */ About to be destroyed. */
1. struct thread 2. { 3. /* Owned by thread.c. */ 4. tid_t tid; /* Thread identifier. */ 5. enum thread_status status; /* Thread state. */ 6. char name[16]; /* Name (for debugging purposes). */ 7. uint8_t *stack; /* Saved stack pointer. */ 8. int priority; /* Priority. */ 9. int org_priority; 10. struct list locks; 11. struct lock *waiting_for_lock; 12. struct semaphore *waiting_for_sema; 13. int64_t blocked_ticks; 14. struct list_elem allelem; /* List element for all threads list. */ 15. 16. /* Shared between thread.c and synch.c. */ 17. struct list_elem elem; /* List element. */ 18. 19. #ifdef USERPROG 20. /* Owned by userprog/process.c. */ 21. uint32_t *pagedir; /* Page directory. */ 22. #endif 23. 24. int nice; 25. int recent_cpu; 26. /* Owned by thread.c. */ 27. unsigned magic; /* Detects stack overflow. */ 28. };
华东师范大学软件学院实验报告
华东师范大学软件学院实验报告
实验课程:操作系统实践 实验名称: Pintos-threads 实验编号: 指导教师: 一、实验目的 Pintos 是一个用于 80x86 体系结构的简单操作系统框架。它支持内核线程、加载和运行 用户程序以及文件系统, 但它以非常简单的方式实现了所有这些。在本次 pintos 项目中, 我 们将加强其在线程这一方面的支持。 在本任务中, 老师为我们提供了一个功能最小的线程系统。我们的工作是扩展此系统的 功能, 以便更好地了解同步问题。我们将主要在此分配的 "线程" 目录中工作, 其中一些工作 是在旁边的 "设备" 目录中进行的。编译应在 "线程" 目录中完成。 年级:大二 姓名: 学号: 组号: 实验日期:2018/11/22 实验时间:4 学时 实验成绩:
与之相对应的 thread_unblock():
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. void thread_unblock (struct thread *t) { enum intr_level old_level; ASSERT (is_thread (t)); old_level = intr_disable (); ASSERT (t->status == THREAD_BLOCKED); list_insert_ordered (&ready_list, &t->elem, (list_less_func *) &thread_priority_cmp, NULL); //check_queue_priority(); t->status = THREAD_READY; ready_thread++; intr_set_level (old_level); }
第 1 页 共 14 页
华东师范大学软件学院实验报告
每秒闪烁一次光标。timer _sleep () 的参数以计时器刻度表示, 而不是以毫秒或任何其他单位 表示。每秒有 timer _ freq 个计时器刻度, 其中 timer _ freq 是在设备中定义的宏。默认值为 100。我们不建议更改此值, 因为任何更改都可能导致许多测试失败。 第三步: 在 pintos 中实现优先调度。当线程添加到优先级高于当前正在运行的线程的就绪列表 中时, 当前线程应立即将处理器授予新线程。同样, 当线程等待锁、信号量或条件变量时, 应 首先唤醒优先级最高的等待线程。线程可以随时提高或降低其自身的优先级, 但降低其优先 级, 使其不再具有最高优先级, 必须导致它立即让出 cpu。线程优先级范围从 pri _ min (0) 到 pri _ max (63)。较低的数字对应于较低的优先级, 因此优先级 0 是最低优先级, 优先级 63 是最高优先级。初始线程优先级作为参数传递给 thread_ create ()。如果没有理由选择其他优 先级, 请使用 pri _ default (31)。pri _ 宏是在 "线程/线程" 中定义的, 我们不应该更改它们的 值。优先级调度的一个问题是 "优先级倒置"。分别考虑高、中、低优先级线程 h、m 和 l。 如果 h 需要等待 l (例如, 对于由 l 持有的锁), 而 m 在准备列表中, 则 h 将永远不会获得 cpu, 因为低优先级线程将不会获得任何 cpu 时间。这个问题的部份解决是 h "捐赠" 它的优 先权 l, 而 l 举行锁, 然后召回捐赠, 一旦 l 发布 (和 h 因而获取) 锁。实施优先捐赠。我 们需要考虑到需要优先捐赠的所有不同情况。请务必处理多个捐赠, 其中多个优先级捐赠给 一个线程。我们还必须处理嵌套捐赠: 如果 h 在等待 m 持有的锁, 而 m 在等待 l 持有的 锁, 则应将 m 和 l 都提升到 h 的优先级。如有必要, 我们可以对嵌套优先捐赠的深度施加 合理的限制, 例如 8 级。 [function] void thread_set _priority (int new_priority) 将当前线程的优先级设置为新的优先 级。如果当前线程不再具有最高优先级, 则会让出 cpu。 [function] int thread_ get _priority (void) 返回当前线程的优先级。在优先捐赠的情况下, 回报更高 (捐赠) 的优先事项。 我们不需要提供任何接口来允许线程直接修改其他线程的优先级。在以后的任何项目中 都不使用优先级计划程序。 第四步: 实现类似于 bsd 计划程序的多级反馈队列调度程序, 以减少在系统上运行作业的平均响 应时间。有关详细要求, 可以参阅附录。与优先级计划程序一样, 高级计划程序根据优先级 选择要运行的线程。但是, 高级计划程序不执行优先级捐赠。因此, 我们应该在开始处理高 级计划程序之前, 让优先级计划程序正常工作, 但可能还有优先级捐赠除外。我们必须编写 代码, 以便我们能够在 pintos 启动时间选择调度算法策略。默认情况下, 优先级计划程序必 须处于活动状态, 但我们必须能够使用 "-mlfqs 内核选项" 选择 bsd 计划程序。传递此选项
二、实验内容与实验步骤 第一步: 阅读和理解初始线程系统的代码。pintos 已经实现了线程创建和线程完成, 这是一个在 线程之间切换的简单调度程序, 以及同步基元 (信号量、锁、条件变量和优化障碍)。我们可 以通读源代码的某些部分, 看看发生了什么。例如:创建线程时, 我们将创建要计划的新上 下文。需要提供了一个要在此上下文中运行的函数, 作为 thread_ create () 的参数。第一次计 划并运行线程时, 它从该函数的开头开始, 并在该上下文中执行。当函数返回时, 线程将终 止。因此, 每个线程的行为就像在 pintos 内部运行的一个小型程序, 函数传递给 thread_ create (), 其作用类似于 main ()。在任何给定的时间, 只有一个线程运行, 其余的线程 (如果 有的话) 变为非活动状态。计划程序决定下一步运行哪个线程。 第二步: 重新实现在 "devicese/timerem. c" 中定义的 timer_sleep ()。目前系统虽然提供了一个工 作实现, 但它 基于"忙等待", 也就是说, 它在循环中旋转, 检查当前时间并调用线程, 直到有 足够的时间过去。我们要重新实现它, 以避免繁忙的等待。 [function] void timer_sleep (int64_t ticks) 暂停执行调用线程, 直到时间提前至少计时器 刻度。除非系统处于空闲状态, 否则线程不需要在 x 刻度后唤醒。只要把它放在准备好的队 列后, 他们已经等待了适当的时间。timer _sleep() 对于实时操作的线程非常有用, 例如, 对于
其中调用到的 thread_block():
1. void 2. thread_block (void) 3. {
第 3 页 共 14 页
华东师范大学软件学院实验报告
来自百度文库
4. 5. 6. 7. 8. 9. 10. }
ASSERT (!intr_context ()); ASSERT (intr_get_level () == INTR_OFF); thread_current ()->status = THREAD_BLOCKED; ready_thread--; schedule ();