首页 > 解决方案 > 是否可以在调度程序的帮助下或在运行时以某种方式更改硬件计时器的时间?

问题描述

我正在学习操作系统的入门课程,我正在尝试开发一个调度程序,它可以在进程的周转时间和响应时间之间做出很好的权衡。

我想知道是否可以更改定时器中断的间隔。如果我能做到这一点,也许我可以根据在给定的更大时间间隔内完成的进程数在不同的计时器间隔之间切换。例如,如果我在最后 10 毫秒内完成了 7 个进程,则将计时器间隔从 10 毫秒切换到 15 毫秒,因此,在响应式调度程序和最小化周转时间的调度程序之间切换,从而获得更好的平均值。

谢谢你。

标签: operating-systemhardwarescheduler

解决方案


让我们把它分成多个部分..

计时器

许多现代内核是“​​无滴答”的。这意味着(而不是让定时器以固定频率生成 IRQ)定时器以“一次性”模式运行(当请求的时间过去时生成一个 IRQ),并且内核确定下一个时间事件何时需要发生并设置下一次事件应该发生时生成 IRQ 的时间。这种方法有利于电源管理(没有不必要的 IRQ 使空闲的 CPU/s 退出节能状态)和精度优势(例如,如果定时器恰好在 1 MHz 时钟下运行,那么内核可以向定时器请求 IRQ具有 1 微秒的粒度,而没有 100 万个 IRQ 的开销,它需要以固定的频率获得相同的粒度)。当然定时器有很多用途(网络超时、sleep()、

注意:现代硬件也可能有定时器以 CPU 的频率运行(例如,最近 80x86 芯片的本地 APIC 定时器中的“TSC 截止时间模式”),其中“tickless”意味着您通常可以获得“优于 1 纳秒”的精度。

当然对于“tickless”,因为每次发生 IRQ 时内核都会为计时器设置一个新计数(对于新的“最快”时间事件),调度程序非常容易使用它喜欢的任何时间片长度,无论出于何种原因喜欢。

任务切换原因

对于真实的操作系统,大多数任务切换是因为当前运行的任务必须等待某些东西(等待来自文件或交换空间的数据,等待来自网络的数据包,等待缓冲区变得“未满”,所以它可以将更多数据放入其中,等待数据通过管道或消息从另一个进程到达,等待释放互斥锁等);或者因为某个任务正在等待发生。调度程序的计时器只是为恶意 CPU 占用和罕见的 CPU 绑定任务提供上限,这些任务不需要等待任何东西。

请注意(对于使用固定频率计时器的循环调度程序)这会导致问题。例如,如果给每个任务一个 10 毫秒的时间片,但任务切换必须在 4.321 毫秒之后发生,因为该任务必须等待某些东西,那么您不想浪费 5.679 毫秒的 CPU 时间等待下一个timer 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 时间而没有做任何可能导致它阻塞/等待的事情,或者减少它的优先级或将其终止为“无响应”)。

如果您查看现代操作系统中的调度程序,您会发现它们都没有单独使用循环。通常“循环”仅在 2 个或更多任务具有相同优先级时使用(但这并不是一个好主意,我将在下一节中告诉你为什么)。此外,大多数操作系统提供多种调度策略(例如,操作系统可能会提供使用“最早期限优先”的软实时调度策略,以及使用“最高优先级获胜”的“低延迟”调度策略,以及“可能使用“优先级确定多少时间片”的“通用”策略,以及可能使用“优先级确定时间片大小”的“空闲任务”策略);调度程序将 CPU 时间分配给具有最佳策略的任务(例如

平均作业完成时间

假设只有一个 CPU;一个任务想要处理一个网络数据包并发送一个响应,这个处理需要 50 毫秒的 CPU 时间;同时另一个进程想要处理来自用户的按键,所涉及的处理也将花费 50 毫秒。如果调度程序每 1 毫秒在任务之间切换,那么第一个任务将在 99 毫秒后完成,第二个任务将在 100 毫秒后完成,一个任务完成其作业的平均时间为 99.5 毫秒。但是,如果调度程序在任何时间后都没有在任务之间切换(例如,只是让当前正在运行的任务运行直到它完成它的工作并等待下一个工作完成),那么第一个任务将在 50 毫秒后完成,并且第二个任务将在 100 毫秒后完成,

换句话说,对于事件驱动的任务(例如,发生某事并且任务在处理它的同时运行,然后等待下一个事件),循环调度程序(以固定频率切换任务)可以使平均完成时间减少近 50%比大多数其他调度算法(例如“最早开始时间优先”,“最高优先级获胜”,...)。

结论

a) 是的,完全可以通过使用无滴答设计或通过使用固定频率定时器设计的“每个时间片的 IRQ”的不同值来调整时间片长度。

b) 对于循环调度器,调整时间片长度不会对延迟有太大帮助(尤其是在负载下)。

c) 介绍性课程是介绍性的——它们旨在提供(在未来某个时候)将帮助您学习更高级概念的信息(而不是提供在实践中“按原样”使用的信息)。循环调度是经常放在介绍中的内容之一,部分原因是它们很简单,但部分原因是它们自然会引发关于它们为什么糟糕以及如何避免问题的讨论(这是大多数人的开始先进的概念)。


推荐阅读