我正在研究操作系统的入门课程,并且试图开发一个调度程序,该调度程序可以在进程的周转时间和响应时间之间做出很好的权衡。
我想知道是否可以更改计时器中断的间隔。如果可以的话,也许可以在给定的较大时间间隔内完成的进程数之间在不同的计时器间隔之间进行切换。例如,如果我在最近的10毫秒内完成了7个进程,则将计时器间隔从10毫秒切换到15毫秒,因此,在响应式调度程序和调度程序之间进行切换,以最大程度地缩短周转时间,从而获得更好的平均值。
谢谢。
答案 0 :(得分:0)
让我们把它分成几部分。
计时器
许多现代内核都是“滴滴答答”的。这意味着(而不是让计时器以固定的频率生成IRQ),计时器以“单发”模式运行(在请求的时间过去时生成一个IRQ),内核确定下一次事件何时需要发生并设置下次事件发生时生成IRQ的时间。这种方法对电源管理有好处(没有不必要的IRQ碰撞,否则空闲的CPU会退出省电状态),并且对精度有好处(例如,如果计时器恰巧以1 MHz时钟运行,则内核可以向计时器请求IRQ粒度为1微秒,而没有100万个IRQ的开销,则需要以固定的频率获得相同的粒度)。当然,计时器有很多用途(网络超时,sleep()等),因此当当前任务消耗其时间片时,“最短时间事件”可能与它无关。
注意:现代硬件也可能具有以CPU频率运行的计时器(例如,最近的80x86芯片的本地APIC计时器中的“ TSC截止日期模式”),其中“滴答”表示您通常可以获得“优于1纳秒”的精度。
当然,对于“滴答滴答”,因为内核会在每次IRQ发生时为计时器设置一个新的计数(对于新的“最快”时间事件),因此调度程序非常容易使用它喜欢的任何时间片长度无论喜欢什么理由。
任务切换原因
对于真正的OS,大多数任务切换是由于当前正在运行的任务必须等待某些东西(等待来自文件或交换空间的数据,等待来自网络的数据包,等待缓冲区变为“未满”而引起的) “,因此它可以将更多的数据放入其中,等待数据通过管道或消息从另一个进程到达,等待互斥量被释放,等等);或因为正在等待任务。调度程序的计时器仅用于为恶意CPU吞吐和不需要等待任何事情的罕见CPU绑定任务提供上限。
请注意(对于使用固定频率计时器的循环调度程序而言),这会引起问题。例如,如果为每个任务分配了10毫秒的时间片,但是由于任务必须等待某些任务,因此必须在4.321毫秒后进行任务切换,那么您就不想浪费5.679毫秒的CPU时间来等待下一个任务计时器IRQ,但您也不想给下一个任务5.679毫秒,而不是应该获得的10毫秒。取而代之的是,您可以将计时器配置为每1毫秒生成一个IRQ,以便可以将下一个任务给出的时间四舍五入到最接近的值(例如,给下一个任务9.679毫秒而不是5.679毫秒而不是10毫秒)。但是,这增加了处理不必要的IRQ的开销并损害了性能,并且是使用“ tickless”(摆脱不必要的IRQ并减少“四舍五入”错误)的原因之一。
轮回的延迟时间
对于循环调度程序,“负载延迟”是一个残酷的笑话,与计时器无关。问题是需要低等待时间的任务必须等待其他数量未知的任务轮到。例如,如果有200个任务本应最多占用10毫秒的CPU时间,而这200个任务中的每一个实际上平均消耗5毫秒的CPU时间(因为大多数阻止/等待时间在它们的时间片之前)结束);那么“低延迟”任务可能需要等待1000毫秒才能获得CPU时间。将计时器的间隔从10毫秒更改为5毫秒可能意味着这200个任务每个平均消耗4毫秒的CPU时间,而“低延迟”任务仍然需要等待800毫秒。
注意:从理论上讲;避免此问题的一种方法是,将一个最近停止等待的任务放在“哪个任务将使下一个CPU时间”列表的开头,这样,当当前正在运行的任务完成使用CPU时,它就会获得CPU时间。在实践中,通过在每个时间片的末尾非常短暂地等待以快速获取一个新的时间片,任务可以故意占用CPU时间,并且通过使用一对协作任务,恶意软件可以确保没有其他任务获得任何CPU时间。因此,您永远不会将任务放在“哪个任务会使下一个CPU时间”列表的开头。
任务优先级
如果您为每个任务分配了优先级,以便调度程序知道任务的重要性,该怎么办?
在这种情况下,如果任务需要低延迟,则可以告诉调度程序它具有较高的优先级,并且当任务停止等待某些内容时(例如,等待用户按下键,等待网络数据包到达等) ),调度程序可以将任务的优先级与当前正在运行的任务的优先级进行比较,以实现“低延迟”任务具有更高的优先级,并立即进行任务切换(而无需等待其他200个任务轮到)。在这种情况下,即使操作系统负载很重,延迟也可以“几乎为零”。
这确实会造成潜在的问题(高优先级的CPU吞噬),但是以其他方式解决该问题很简单(例如,如果高优先级的任务占用了太多的CPU时间却没有做任何可能导致其阻塞/等待的事情,降低优先级或将其终止为“无响应”。
如果您查看现代操作系统中的调度程序,您会发现它们中没有一个单独使用轮询。通常只有在两个或多个任务具有相同优先级时才使用“循环”(但这并不是一个好主意,在下一节中将告诉您原因)。此外,大多数操作系统都提供多种调度策略(例如,操作系统可能会提供使用“最早截止日期优先”的软实时调度策略,再加上使用“最高优先级获胜”的“低延迟”调度策略,再加上“可能使用“优先级决定多少个时间片”的“通用”策略,以及可能使用“优先级决定时间片的大小”的“空闲任务”策略);调度程序将CPU时间分配给具有最佳策略的任务(例如,如果有一个实时任务需要CPU,那么甚至不考虑空闲任务),并且每个策略都有不同的规则。
平均工作完成时间
让我们假设只有一个CPU;一个任务要处理网络数据包并发送响应,并且此处理将花费50毫秒的CPU时间;同时另一个进程要处理用户的按键操作,所涉及的处理也将花费50毫秒。如果调度程序每1毫秒在任务之间切换一次,则第一个任务将在99毫秒后完成,而第二个任务将在100毫秒后完成,并且任务完成其工作所需的平均时间为99.5毫秒。但是,如果调度程序在任何时间后都未在任务之间切换(例如,仅让当前正在运行的任务运行直到完成任务并等待下一个任务执行),则第一个任务将在50毫秒后完成,并且第二个任务将在100毫秒后完成,任务平均完成工作所需的时间为75毫秒(而不是99.5毫秒)。
换句话说,对于事件驱动的任务(例如,发生某事并且任务在处理任务时运行,然后等待下一个事件),循环调度程序(以固定频率切换任务)可以使平均完成时间几乎比大多数其他调度算法(例如“最早的开始时间优先”,“最高优先级获胜”等等)差50%。结论
a)是的,完全可以通过使用无滴答设计或通过对固定频率计时器设计的“每时间片IRQ”使用不同的值来调整时间片长度。
b)对于循环调度器,调整时间片长度不会对延迟有很大帮助(尤其是在负载下)。
c)入门课程是一种介绍-它们旨在提供信息(在将来的某个时候)将帮助您学习更高级的概念(而不旨在提供在实践中按原样使用的信息) )。循环调度是引言中经常提到的事情之一,部分是因为它们很简单,但部分是因为它们自然引发了关于为什么吸吮以及如何避免问题的讨论(这是大多数问题的开始)。先进的概念)。