允许调度程序切换正在执行的线程的机制是什么?

What is the mechanism that allows the scheduler to switch which threads are executing?

我明白 cpu 调度器使用时间片并且有一个线程 运行 指定的时间量然后切换线程,但我不明白的是 CPU知道停止执行线程并切换任务。它不能在每条指令后重复检查时钟,对吗?那将花费太多开销,这将是非常浪费的。我不认为它在线程上使用一些确定性计算来在某些指令处放置中断,它假设在到达该指令时时间已经过去,那么上下文切换是如何发生的? CPU 如何在不不断检查时钟或其他东西的情况下停止执行?

是定时器中断

Interrupts 是超出图灵完备的事物之一。图灵完备machine/language不需要实现中断。但是如果没有中断,你将很难实现时间片或抢占式多任务处理 OS.

没有中断

仍然可以在不中断的系统上实现多任务处理 OS - 您可以使用协作式多任务处理。旧的 MacOS(在 OSX 之前)就是这样做的。您只需告诉应用程序开发人员,他们 必须 通过调用 yield() 之类的方法将执行移交给 OS。这个 "yield" 函数实际上就是 OS 本身。协作式多任务处理当然并不理想——您可以想象程序崩溃会导致 OS 永远不会执行,从而导致整台机器瘫痪。协作式多任务处理的优势在于,您可以在非常简单的 CPU 上完成,无需中断支持。它还通常需要更少的 RAM 和 CPU 资源。而且,作为一名程序员,您可以更好地控制 CPU - 例如,如果您需要真正使用 100% 的 CPU,您可以阻止 OS 占用任何 CPU 时间。

中断

中断只是 CPU 的一项功能,您可以在其中配置 CPU 以在发生某些事情时调用函数(称为中断处理程序)。对于 OS 程序员,最有用的是定时器中断 - 您可以在其中配置定时器来触发中断。当中断被触发时 OS 到达 运行 并且在执行结束时 OS 将简单地安排另一个定时器中断 - 这是时间片多任务处理。

有些 OS 像 Linux 或实时 Windows 允许您配置这个计时器。 Linux 称它为 jiffy,一些 OS 称它为 tick

如果您做过任何 javascript 编程,您会觉得这很熟悉 - 这几乎就像 setTimeout() 对程序员的行为方式。

I/O

另一种重要的中断类型是I/O中断。您的键盘实际上可以使用 I/O 中断。普通 PC 根本不会扫描键盘。相反,I/O 控制器(现在通常是 USB 控制器)查询键盘,如果有按键,将向 CPU 发送中断信号。这将触发 OS 并且 OS 将检查密钥属于哪个进程并将切换到允许它接收输入的进程 - 这是抢占式多任务处理。显然,抢占式多任务处理在后台使用时间片,以防长时间没有 I/O activity.

"It can't check a clock repeatedly after every instruction - right?" CPU 有特殊装置 - 计时器。它有一个寄存器,其中包含警报的剩余时间,并在每个时钟滴答时递减。一旦它变为零,就会引发中断。中断完全作为过程调用实现,尽管对该过程的调用不存在于当前正在执行的程序代码中。中断程序可以做一些规定的活动,设置另一个定时器值和return,那么当前正在执行的程序就不会注意到这个调用。或者它可以决定停放当前线程并让另一个线程在该处理器上执行。在那种情况下,中断过程重新加载特殊寄存器,以便它们指向下一个线程,并且还使 return 和 returns 指向前一段时间在另一个线程上执行的过程。

这样处理器从一个线程切换到另一个线程,线程在主动和被动状态之间切换。