计算机如何在不使用所有处理能力的情况下进入睡眠/等待状态?

计算机如何在不使用所有处理能力的情况下进入睡眠/等待状态?

我一直不太明白的是,计算机如何能在不使用全部处理能力的情况下运行。(这种困惑可能源于大学时的一门糟糕的操作系统课程。)

据我所知,一个线程(比如操作系统的调度程序)必须执行某物在任何给定的时间点。如果没有事可做,它就会循环,直到有事要做。我认为,这种性质的循环总是会尽可能快地运行,这会耗尽处理器的所有计算能力。

我猜我的误解是错误的假设,“如果没有事可做,它只会循环”。然而,我不知道它还能做什么。

答案1

计算机有硬件计时器,可用于在特定时间长度过去时向处理器发出信号。其中一项是高精度事件计时器 (HPET),回顾历史,甚至 RTC 也能实现类似的目的。

CPU 还具有暂停执行单元的能力使用 HLT 指令并有效地使自己进入睡眠状态。没有循环运行,并且从各方面来看,CPU 都处于死机状态,只有等待中断线被确认的硬件除外。

处理器不会通过循环进行旋转等待,而是直接告诉硬件在特定时间过去后提醒它,然后让核心执行单元进入休眠状态。一旦时间过去,计时器就会发出中断,从而唤醒 CPU 并重新开始执行。

低精度定时器(如 RTC)的工作方式类似,对于每个滴答数,您都会检查每个滴答的计数并休眠直到下一个滴答出现。这是实现等待状态的一种相对低成本(处理器功率方面)的方法。

答案2

很抱歉操作系统课程没有涵盖这个主题。它确实应该涵盖。当我需要详细了解时,我将参考 Linux,因为它既是开源的,又非常流行,但其他操作系统(只要它们有抢占式多任务) 类似。

您可能熟悉 PC 硬件术语“硬件线程”。Linux 称它们为“CPU”。我还将使用“睡眠”来谈论硬件在等待时节省电量的情况 - 这包括 CPU 未 100% 利用的任何情况。

在任何时候,CPU 可以做以下几件事之一:

  • 中断事件触发的指令 [ hi& si]

  • 提供内核服务所需的指令,例如在基于文件的 I/O 和存储设备之间进行转换。[ sy]

  • 用户模式下的应用程序或服务器指令 [ us& ni]

  • 等待某事发生 [ id& wa]

  • Linux 无法控制的指令 [ st]

[代码见程序top]

中断是理解这一点的关键。每当硬件设备需要其驱动程序的注意时,它就会向中断控制器发送一条消息,中断控制器会将其路由到 CPU,CPU 会记录它正在做什么并切换到相应设备驱动程序的指令。中断也可以由计时器硬件生成或由软件触发。例如,当在 CPU 2 上运行的 CPU 调度程序注意到 CPU 5 应该唤醒或切换到其他任务时,它将发送中断。

有一条指令可使 CPU 不执行任何操作并节省电量,直到收到中断为止。Linux 创建了一个“空闲任务”,该任务在循环内使用此指令 - 以及其他任务。Linux 空闲循环还会检查任务是否已准备好运行,并可能在 CPU 休眠时关闭“jiffy”计时器或执行其他电源管理任务。

然后,该 CPU 的睡眠由切换到空闲任务和退出空闲任务来控制。每个 CPU 都有一个。

CPU 芯片上有实用硬件,用于控制内核在休眠时关闭多少部分 - CPU 2 上的指令可以控制 CPU 5 正在执行的操作等。这是使用 ACPI 固件进行管理的,不同的省电模式称为 ACPI C 状态。如果休眠时间足够短,则该内核仍可接收中断。因此,Linux 还需要告诉中断控制器哪些内核可用于中断。

就像我说的,中断是关键。硬件中会发生一些事情 - 硬盘上的一块数据已准备好,USB 控制器已准备好接收更多数据,数据包已通过以太网到达,时间已到,GPU 需要一块内存 - 然后 CPU 核心做出响应。如果 CPU 处于轻度睡眠状态,该中断将唤醒它。设备驱动程序将运行,CPU 将返回其空闲循环,并检查是否有任务准备运行。如果有,CPU 将切换到该任务,现在它正在运行应用程序指令。

相反的过程,即进入睡眠状态,发生在应用程序请求某些东西并要求在必要时进入睡眠状态时。例如,您的 Web 浏览器可能会询问数据是否已从网络到达或是否已从用户界面收到输入。它通过切换到内核模式的特殊指令来实现这一点。然后 Linux 以查看整个系统所需的权限运行。它会检查“输入就绪”状态。如果就绪,它会返回到浏览器的代码,该代码继续接收和处理输入。

但是,如果 Linux 检测到某个应用程序尚未就绪,它会记录该应用程序正在等待的服务,将该任务标记为休眠,并寻找其他任务来执行。如果找不到任何任务,它会切换到空闲任务,该任务负责让该 CPU 进入休眠状态。

稍后,当发生中断并且设备驱动程序运行时,这些注释将标识浏览器已准备好再次运行。

还有一些代码路径可以根据负载决定是否将任务移至其他 CPU、更改其他 CPU 的睡眠状态以及唤醒深度睡眠的 CPU。只有一个 CPU 的简单计算机不需要那么复杂,但现在 PC 通常是多核的。

总结一下:

  • 当软件需要某些功能但该功能尚未准备好或尚未发生时,操作系统会让该软件进入睡眠状态。然后它会尝试寻找其他软件来运行。

  • 这仅当软件向操作系统请求某些东西(系统调用)时才会发生。如果应用程序进入无限循环,它将使用操作系统为其提供的所有 CPU 时间。

  • 如果 CPU 没有任何软件可运行,操作系统就会使用其空闲任务使其进入睡眠状态。

  • (切换到空闲任务意味着,如果需要,前一个任务可以自由地移动到另一个 CPU 上 - 它不会被加载到 CPU 上,卡在那里什么也不做。单 CPU 操作系统可能不会需要一项空闲任务,但通常仍被使用。

  • 当硬件需要某些东西或数据到达时,就会产生中断。这会中断正在运行的 CPU 或唤醒处于轻度睡眠状态的 CPU,并导致设备驱动程序运行。此时,操作系统会记录哪些睡眠软件现在已准备好运行。此时至少有一个 CPU 处于唤醒状态 - 即运行设备驱动程序的 CPU - 并且如果操作系统需要,其他 CPU 可能会被唤醒。操作系统决定应该运行哪个任务(CPU 调度)并在必要时进行切换。

  • 如果应用程序被中断,操作系统会记住它正在做什么并最终切换回该操作。

  • 如果多个任务同时准备运行,则计时器中断(Linux 称之为“jiffy”)最终会导致操作系统切换任务,即使该 CPU 上没有其他中断。

  • 如果在 CPU A 上注意到一个事件,这意味着 CPU B 应该被唤醒或者可能需要切换任务,则在 A 上运行的操作系统会向 B 上的自身发送中断。在强制软件停止等异常情况下,CPU B 甚至可能会被中断以告诉它进入睡眠状态。

  • 系统调用中的“尚未准备好”条件会使软件进入睡眠状态,硬件中断或软件事件会导致硬件和软件唤醒。

  • 还可以强制软件进入睡眠状态。Linux 有“stop/trace”功能,主要用于暂停软件进行调试,还有“freeze”功能,用于暂停整个系统以节省电量。两者都是由软件事件触发的,例如调试器启动程序或用户单击“suspend to RAM”按钮。

答案3

Mokubai 给出了睡眠通常如何工作的正确答案。但即使计算机处于自旋循环状态,它仍然可以比正常情况下消耗更少的电量。不同的指令消耗的电量不同,具体取决于它们执行的操作。从 RAM 读取将比从 CPU 缓存读取消耗更多的电量,当它处于微小的自旋循环中时,它应该只使用缓存。当它循环时,执行算术或与外部设备交互的 CPU 部分处于非活动状态,因此它们不消耗任何电量。

除了事件计时器之外,这一切都不如几乎完全停止运行那么好。但我认为一些操作系统有“低功耗模式”,介于正常运行和睡眠之间,可能会包含其中的一些功能。

相关内容