ImageVerifierCode 换一换
格式:DOCX , 页数:16 ,大小:455.08KB ,
资源ID:10428128      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10428128.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(06时间片轮转调度.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

06时间片轮转调度.docx

1、06时间片轮转调度操作系统实验报告 实验6 时间片轮转调度1. 实验目的与要求 调试EOS的线程调度程序,熟悉基于优先级的抢先式调度。 为EOS添加时间片轮转调度,了解其它常用的调度算法。2. 实验原理 阅读本书第5章中的第节。重点理解EOS当前使用的基于优先级的抢先式调度,调度程序执行的时机和流程,以及实现时间片轮转调度的细节。 3. 实验内容 准备实验 按照下面的步骤准备实验: 1. 启动OS Lab。 2. 新建一个EOS Kernel项目。 阅读控制台命令“rr”相关的源代码阅读ke/文件中第690行的ConsoleCmdRoundRobin函数,及该函数用到的第649行的Thread

2、Function函数和第642行的THREAD_PARAMETER结构体,学习“rr”命令是如何测试时间片轮转调度的。在阅读的过程中需要特别注意下面几点: 在ConsoleCmdRoundRobin函数中使用ThreadFunction函数做为线程函数,新建了20个优先级为8的线程,做为测试时间片轮转调度用的线程。 在新建的线程中,只有正在执行的线程才会在控制台的对应行(第0个线程对应第0行,第1个线程对应第1行)增加其计数,这样就可以很方便的观察到各个线程执行的情况。 控制台对于新建的线程来说是一种临界资源,所以,新建的线程在向控制台输出时,必须使用“关中断”和“开中断”进行互斥(参见Thr

3、eadFunction函数的源代码)。 由于控制台线程的优先级是24,高于新建线程的优先级 8,所以只有在控制台线程进入“阻塞”状态后,新建的线程才能执行。 新建的线程会一直运行,原因是在ThreadFunction函数中使用了死循环,所以只能在ConsoleCmdRoundRobin函数的最后调用TerminateThread函数来强制结束这些新建的线程。 按照下面的步骤执行控制台命令“rr”,查看其在没有时间片轮转调度时的执行效果: 1. 按F7生成在本实验中创建的EOS Kernel项目。 2. 按F5启动调试。 3. 待EOS启动完毕,在EOS控制台中输入命令“rr”后按回车。 命令开

4、始执行后,观察其执行效果(如图1),会发现并没有体现“rr”命令相关源代码的设计意图。通过之前对这些源代码的学习,20个新建的线程应该在控制台对应的行中轮流地显示它们的计数在增加,而现在只有第0个新建的线程在第0行显示其计数在增加,说明只有第0个新建的线程在运行,其它线程都没有运行。造成上述现象的原因是:所有20个新建线程的优先级都是8,而此时EOS只实现了基于优先级的抢先式调度,还没有实现时间片轮转调度,所以至始至终都只有第0个线程在运行,而其它具有相同优先级的线程都没有机会运行,只能处于“就绪”状态。图1:没有时间片轮转调度时“rr”命令的执行效果调试线程调度程序 在为EOS添加时间片轮转

5、调度之前,先调试一下EOS的线程调度程序PspSelectNextThread函数,学习就绪队列、就绪位图以及线程的优先级是如何在线程调度程序中协同工作的,从而加深对EOS已经实现的基于优先级的抢先式调度的理解。 3.3.1 调试当前线程不被抢先的情况 正像图1中显示的,新建的第0个线程会一直运行,而不会被其它同优先级的新建线程或者低优先级的线程抢先。按照下面的步骤调试这种情况在PspSelectNextThread函数中处理的过程。1. 结束之前的调试。 2. 在ke/文件的ThreadFunction函数中,调用fprintf函数的代码行(第680行)添加一个断点。 3. 按F5启动调试。

6、 4. 待EOS启动完毕,在EOS控制台中输入命令“rr”后按回车。“rr”命令开始执行后,会在断点处中断。 5. 查看ThreadFunction函数中变量pThreadParameter-Y的值应该为0,说明正在调试的是第0个新建的线程。 图2 执行效果6. 激活虚拟机窗口,可以看到第0个新建的线程还没有在控制台中输出任何内容,原因是fprintf函数还没有执行。 7. 激活OS Lab窗口后按F5使第0个新建的线程继续执行,又会在断点处中断。再次激活虚拟机窗口,可以看到第0个新建的线程已经在控制台中输出了第一轮循环的内容。可以多按几次F5查看每轮循环输出的内容。 图3 第一轮循环通过之前

7、的调试,可以观察到第0个新建的线程执行的情况。按照下面的步骤调试,查看当有中断发生从而触发线程调度时,第0个新建的线程不会被抢先的情况。 1. 在ps/文件的PspSelectNextThread函数中,调用BitScanReverse函数扫描就绪位图的代码行(第384行)添加一个断点。 2. 按F5继续执行,当有定时计数器中断发生时(每10ms一次),就会在新添加的断点处中断。 3. 在“调试”菜单的“窗口”中选择“监视”,激活“监视”窗口(此时按F1可以获得关于“监视”窗口的帮助)。 4. 在“监视”窗口中添加表达式“/t PspReadyBitmap”,以二进制格式查看就绪位图的值。此时

8、就绪位图的值应该为1,表示优先级为8和0的两个就绪队列中存在就绪线程。(注意,如果就绪位图的值不是1,就继续按F5,直到就绪位图变为此值)。 5. 在“调试”菜单中选择“快速监视”,在“快速监视”对话框的“表达式”中输入表达式“*PspCurrentThread”后,点击“重新计算”按钮,可以查看当前正在执行的线程(即被中断的线程)的线程控制块中各个域的值。其中优先级(Priority域)的值为8;状态(State域)的值为2(运行态);时间片(RemainderTicks域)的值为6;线程函数(StartAddr域)为ThreadFunction。综合这些信息即可确定当前正在执行的线程就是新

9、建的第0个线程。关闭“快速监视”对话框。 图4 快速“监视”窗口6. 在“监视”窗口中添加表达式“ListGetCount(&PspReadyListHeads8)”,查看优先级为8的就绪队列中就绪线程的数量,值为19。说明除了正在执行的第0个新建的线程外,其余19个新建的线程都在优先级为8的就绪队列中。ListGetCount函数在文件rtl/中定义。 7. 按F10单步调试,BitScanReverse函数会从就绪位图中扫描最高优先级,并保存在变量HighestPriority中。查看变量HighestPriority的值为8。 图5 “监视”窗口8. 继续按F10单步调试,直到在PspS

10、electNextThread函数返前停止(第465行),注意观察线程调度执行的每一个步骤。 第0个新建的线程在执行线程调度时没有被抢先的原因可以归纳为两点: (1) 第0个新建的线程仍然处于“运行”状态。 (2) 没有比其优先级更高的就绪线程。 3.3.2 调试当前线程被抢先的情况 如果有比第0个新建的线程优先级更高的线程进入就绪状态,则第0个新建的线程就会被抢先。按照下面的步骤调试这种情况在PspSelectNextThread函数中处理的过程(注意,接下来的调试要从本实验3.3.1调试的状态继续调试,所以不要结束之前的调试)。 1. 选择“调试”菜单中的“删除所有断点”,删除之前添加的所

11、有断点。 2. 在ps/文件的PspSelectNextThread函数的第395行添加一个断点。 3. 按F5继续执行,激活虚拟机窗口,可以看到第0个新建的线程正在执行。 4. 在虚拟机窗口中按下一次空格键,EOS会在之前添加的断点处中断。 5. 在“监视”窗口中查看就绪位图的值为0001,说明此时在优先级为24的就绪队列中存在就绪线程。在“监视”窗口中添加表达式“ListGetCount(&PspReadyListHeads24)”,其值为1,说明优先级为24的就绪队列中只有一个就绪线程。扫描就绪位图后获得的最高优先级的值HighestPriority也就应该是24。 图6 “监视”窗口就

12、绪位图为00016. 按F10单步调试一次,执行的语句会将当前正在执行的第0个新建的线程,放入优先级为8的就绪队列的队首。“监视”窗口中显示的优先级为8的就绪队列中的线程数量就会增加1,变为20。 图7 “监视”窗口线程数量7. 继续按F10单步调试,直到在第444行中断执行,注意观察线程调度执行的每一个步骤。此时,正在执行的第0个新建的线程已经进入了“就绪”状态,让出了CPU。线程调度程序接下来的工作就是选择优先级最高的非空就绪队列的队首线程作为当前运行线程,也就是让优先级为24的线程在CPU上执行。 8. 按F10单步调试一次,当前线程PspCurrentThread指向了优先级为24的线

13、程。可以在“快速监视”窗口中查看表达式“*PspCurrentThread”的值,注意线程控制块中StartAddr域的值为IopConsoleDispatchThread函数(在文件io/中定义),说明这个优先级为24的线程是控制台派遣线程。 图8 快速“监视”窗口9. 继续按F10单步调试,直到在PspSelectNextThread函数返回前(第465行)中断执行,注意观察线程调度执行的每一个步骤。此时,优先级为24的线程已经进入了“运行”状态,在中断返回后,就可以开始执行了。在“监视”窗口中,就绪位图的值变为1,优先级为24的就绪队列中线程的数量变为0,就绪位图和就绪队列都是在刚刚被调

14、用过的PspUnreadyThread函数(在文件ps/中定义)内更新的。 图9 “监视”窗口10. 删除所有断点后结束调试。 为EOS添加时间片轮转调度 3.4.1 要求 修改ps/文件中的PspRoundRobin函数(第337行),在其中实现时间片轮转调度算法。 代码如下:VOIDPspRoundRobin( VOID )/*+功能描述: 时间片轮转调度函数,被定时计数器中断服务程序 KiIsrTimer 调用。参数: 无。返回值: 无。-*/ 3.4.2代码修改完毕后,按F7生成EOS内核项目。 2. 按F5启动调试。 3. 在EOS控制台中输入命令“rr”后按回车。应能看到20个线程

15、轮流执行的效果,如图10。 图10:进行时间片轮转调度时“rr”命令的执行效果3.4.3 提示 PspRoundRobin函数具体的流程可以参考图5-11。 在PspRoundRobin函数中,全局变量PspCurrentThread指向的线程控制块就是被定时计数器中断的线程的线程控制块,通过对PspCurrentThread指向的线程控制块的各个域进行修改,就可以改变被中断线程的各种属性。全局变量PspCurrentThread的定义参见ps/的第45行。线程控制块结构体的定义参见ps/的第58行。 被中断线程的状态有可能不是“运行”状态,而是“阻塞”状态。所以,在进行时间片轮转调度前,要先

16、判断一下被中断线程是否仍处于“运行”状态。只有当被中断线程仍处于“运行”状态时,才需要进行时间片轮转调度。在PspRoundRobin函数中的第一行代码可以如下(线程状态的定义可以参见ps/的第93行): if (NULL != PspCurrentThread & Running = PspCurrentThread-State) 在OS Lab的“项目管理器”窗口中找到ps/文件,双击打开此文件。 2. 将ps/第104行定义的TICKS_OF_TIME_SLICE的值修改为1。 3. 在EOS控制台中输入命令“rr”后按回车。观察执行的效果。4. 按F7生成EOS内核项目。 5. 按F5

17、启动调试。图11 线程示意还可以按照上面的步骤为TICKS_OF_TIME_SLICE取一些其它的极端值,例如20或100等,分别观察“rr”命令执行的效果。通过分析造成执行效果不同的原因,理解时间片的大小对时间片轮转调度造成的影响。 (规律:将TICKS_OF_TIME_SLICE取100时依次出现再循环依次出现)图12 时间片的大小对时间片轮转调度造成的影响。4. 思考与练习1. 结合线程调度执行的时机,说明在ThreadFunction函数中,为什么可以使用“关中断”和“开中断”的方法来保护控制台这种临界资源。一般情况下,应该使用互斥信号量(MUTEX)来保护临界资源,但是在Thread

18、Function函数中却不能使用互斥信号量,而只能使用“关中断”和“开中断”的方法,结合线程调度的对象说明这样做的原因。 答:关中断后CPU就不会响应任何由外部设备发出的硬中断(包括定时计数器中断和键盘中断等)了,也就不会发生线程调度了,从而保证各个线程可以互斥的访问控制台。这里绝对不能使用互斥信号量(mutex)保护临界资源的原因:如果使用互斥信号量,则那些由于访问临界区而被阻塞的线程,就会被放入互斥信号量的等待队列,就不会在相应优先级的就绪列中了,而时间轮转调度算法是对就绪队列的线程进行轮转调度,而不是对这些被阻塞的线程进行调度,也就无法进行实验了。使用“关中断”和“开中断”进行同步就不会

19、改变线程的状态,可以保证那些没有获得处理器的线程都在处于就绪队列中。2. 时间片轮转调度发现被中断线程的时间片用完后,而且在就绪队列中没有与被中断线程优先级相同的就绪线程时,为什么不需要将被中断线程转入“就绪”状态?如果此时将被中断线程转入了“就绪”状态又会怎么样?可以结合PspRoundRobin函数和PspSelectNextThread函数的流程进行思考,并使用抢先和不抢先两种情况进行说明。 答:因为由PspRoundRobin 函数和 PspSelectNextThread 函数的流程可知,当时间片轮转调度发现被中断线程的时间片用完后,而且在就绪队列中没有与被中断线程优先级相同的就绪线

20、程时,PspRoundRobin 函数会直接结束,所以不需要将被中断线程转入“就绪”状态。如果此时将被中断线程转入了“就绪”状态,那么比该中断线程更高的就绪进程就无法运行。3. 在EOS只实现了基于优先级的抢先式调度时,同优先级的线程只能有一个被执行。当实现了时间片轮转调度算法后,同优先级的线程就能够轮流执行从而获得均等的执行机会。但是,如果有高优先级的线程一直占用CPU,低优先级的线程就永远不会被执行。尝试修改ke/文件中的ConsoleCmdRoundRobin函数来演示这种情况(例如在20个优先级为8的线程执行时,创建一个优先级为9的线程)。设计一种调度算法来解决此问题,让低优先级的线程

21、也能获得被执行的机会。 答:解决该问题的最简单的方法是实现动态优先级算法。动态优先级是指在创建进程时所赋予的优先级,可以随线程的推进而改变,以便获得良好的调度性能。例如,可用规定,在就绪队列中的线程,随着其等待时间的增长,其优先级以速率X增加,并且正在执行的线程,其优先级以速率y下降。这样,在各个线程具有不同优先级的情况下,对于优先级低的线程,在等待足够的时间后,其优先级便可能升为最高,从而获得被执行的机会。此时,在基于优先级的抢占式调度算法、时间片轮转调度算法和动态优先级算法的共同作用下,可防止一个高优先级的长作业长期的垄断处理器。4. EOS内核时间片大小取60ms(和Windows操作系

22、统完全相同),在线程比较多时,就可以观察出线程轮流执行的情况(因为此时一次轮转需要60ms,20个线程轮流执行一次需要60201200ms,也就是需要1秒多的时间,所以EOS的控制台上可以清楚地观察到线程轮流执行的情况)。但是在Windows、Linux等操作系统启动后,正常情况下都有上百个线程在并发执行,为什么觉察不到它们被轮流执行,并且每个程序都运行的很顺利呢? 答:在Windows、linux等操作系统中,虽然都提供了时间片轮转调度算法却很少真正被派上用场,下面解释原因,在Windows任务管理器中,即使系统中已经运行了数百个线程, 但CPU的利用率仍然很低,甚至为0.因为这些线程在大部

23、分时间都处于阻塞状态,阻塞的原因是各种各样的,最主要的原因是等待I/O完成或者等待命令消息的到达。例如,在编辑Word文档时,每敲击一次键盘,Word就会立即作出反应,并且文档中插入字符。此时会感觉Word运行的非常流畅。事实上,并非如此,Word主线程大部分时间都处于阻塞等待状态,等待用户敲击键盘。在用户没有敲击键盘或没有使用鼠标点击时,Word主线程处于阻塞状态,它将让出处理器给其它需要的线程。当用户敲击一个按键后,Word主线程将会立刻被操作系统唤醒,此时Word开始处理请求。Word在处理输入请求时所用的CPU时间是非常短的(因为CPU非常快),是微秒级的,远远低于时间片轮转调度的时间片大小(Windows下是60毫秒),处理完毕后Word又立刻进入阻塞状态,等待用户下一次敲击键盘。或者拿音乐播放器来分析,表面上感觉播放器在不停地播放音乐,但是CPU的利用率仍然会很低。这是由于播放器将一段声音编码交给声卡,由声卡来播放,在声卡播放完这段声音之前,播放器都是处于阻塞等待状态的。当声卡播放完片段后,播放器将被唤醒,然后它将下一个声音片段交给声卡继续播放。掌握了上面的知识后,就可以很容易解释为什么这么多线程同时在运行而一点都感觉不到轮替现象。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1