空闲的CPU进程有什么作用?


73

查看源代码,strace我发现使用了克隆标志CLONE_IDLETASK,该标志被描述为:

#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */

在更深入地研究它之后,我发现,尽管该标志未涉及该标志,但man clone内核实际上在引导过程中使用了该标志来为机器上的每个CPU创建空闲进程(所有进程都应具有PID 0)。即,具有8个CPU的计算机将至少有7个(请参见下面的问题)这样的进程“正在运行”(注释引号)。

现在,这使我对“闲置”过程的实际作用提出了两个问题。我的假设是,它将连续执行NOP操作,直到其时间范围结束为止,并且内核分配了一个实际的进程来运行或再次分配了空闲进程(如果未使用CPU)。但是,这是一个完整的猜测。所以:

  1. 例如,在具有8个CPU的计算机上,将创建7个这样的空闲进程吗?(而一个CPU将由内核本身持有,而没有执行任何用户空间工作?)

  2. 空闲过程真的只是无限的NOP操作流吗?(或执行相同操作的循环)。

  3. CPU使用率(例如uptime)是否仅通过空闲时间在CPU上存在了多长时间,在一段时间内不存在多少时间来简单地计算出来?


PS:这个问题很可能是由于我不完全了解CPU的工作原理。即我了解程序集,时间范围和中断,但是我不知道例如CPU如何根据执行的内容使用更多或更少的能量。如果有人也能启发我,我将不胜感激。


17
看到标题时,我不得不抵制只写“一无所有”的诱惑。

4
当闲置或处于低负载时(动态频率缩放,例如Intel CPU的SpeedStep),大多数现代CPU将动态降低其时钟速率和功耗。如果对CPU超频,通常会禁用此行为,从而导致CPU即使在空闲时也能保持最大时钟速率。
纳特

2
另请参阅“ ACPI电源状态”:处理器可以通过多种方式停止执行指令但仍可唤醒。
pjc50

Answers:


85

空闲任务用于过程记帐,还可以减少能耗。在Linux中,为每个处理器创建一个空闲任务,并将其锁定到该处理器。只要该CPU上没有其他进程可以运行,就计划空闲任务。在诸如之类的工具中,用于空闲任务的时间显示为“空闲”时间top。(正常运行时间的计算方式有所不同。)

Unix似乎总是有某种类型的空闲循环(但不一定是实际的空闲任务,请参见Gilles的回答),甚至在V1中,它也使用了一条WAIT指令来停止处理器直到发生中断(它代表“等待……”)。打断”)。其他一些操作系统则特别使用繁忙循环,DOS,OS / 2和Windows的早期版本。现在,很长一段时间以来,CPU都使用这种“等待”指令来减少其能耗和热量产生。您可以arch/x86/kernel/process.c在Linux内核中看到各种空闲任务的实现,例如:基本调用HLT,它使处理器停止运行,直到发生中断(并启用C1节能模式)为止,其他实现则处理各种错误或效率低下的问题(例如MWAITHLT在某些CPU上使用代替)。

当它们等待事件(I / O等)时,所有这些都与进程中的空闲状态完全分开。


3
嘿,我现在明白了,谢谢。 play_dead()是用于执行HALT的非常好的助记符名称。将HALT发送到每个CPU并因此挂起,是否存在风险?(即达到这种情况,暂停每个CPU,是否会正确解决内核中的错误?)
grochmal

30
CPU通过中断从HALT唤醒。
约翰·迈伦(JohanMyréen)

1
@JohanMyréen-太好了,这很有道理。在这种情况下,即使来自输入设备的IRQ中断也会将其唤醒。谢谢。
grochmal

15
或更可靠的是,计时器中断了((滴答作响的处理又是一锅鱼。)
Stephen Kitt

3
实际上,@ EJP是一条非常普通的指令,即使它在不同的体系结构中具有不同的名称。
immibis

50

在进程调度程序的教科书设计中,如果调度程序没有任何要调度的进程(即,如果所有进程都被阻塞,等待输入),则调度程序将等待处理器中断。中断可以指示来自外围设备的输入(用户操作,网​​络数据包,从磁盘完成的读取等),也可以是计时器中断,它会触发进程中的计时器。

Linux的调度程序没有针对无用情况的特殊代码。而是将无用情况编码为一个特殊过程,即空闲过程。仅当没有其他进程可调度时,才对空闲进程进行调度(它实际上具有无限低的优先级)。空闲进程实际上是内核的一部分:它是内核线程,即在内核中执行代码的线程,而不是进程中的代码。(更确切地说,每个CPU都有一个这样的线程。)当空闲进程运行时,它将执行等待中断操作。

等待中断的工作方式取决于处理器的功能。采用最基本的处理器设计,这只是一个繁忙的循环-

nothing:
    goto nothing

处理器永远保持运行分支指令的作用,但没有执行任何操作。除非它们运行在没有更好的处理器的机器上,并且大多数处理器都有更好的机器,否则大多数现代OS都不会这样做。理想情况下,应该关闭处理器,而不是花费精力为房间供暖。因此,内核运行指示处理器自动关闭或至少关闭大多数处理器的代码。至少有一小部分保持通电,即中断控制器。当外设触发中断时,中断控制器会将唤醒信号发送到处理器主处理器(部分)。

实际上,诸如Intel / AMD和ARM之类的现代CPU具有许多复杂的电源管理设置。操作系统可以估计处理器将在空闲模式下停留多长时间,并据此选择不同的低功耗模式。这些模式在空闲时的功耗与进入和退出空闲模式所需的时间之间提供了不同的折衷。在某些处理器上,如果OS发现进程没有占用太多CPU时间,它也可以降低处理器的时钟速率。


5
请注意,即使最基本的嵌入式CPU(如基于AVR的微控制器)也具有WFI(等待中断)指令,即使该指令根据确切的型号可能等同于NOP。
乔纳斯·谢弗(JonasSchäfer)

@JonasWielicki我以为如果您无事可做,通常会进入一个紧密的循环,否则您可能会进入低功耗状态并等待中断将您从中退出(低功耗状态通常需要更多的“金属”中断)。
尼克T

1
@JonasWielicki专为嵌入式系统设计的体系结构关心电源管理,因此WFI在那里很重要。许多较旧的体系结构都没有这种东西。最初的8086体系结构没有,AFAIR。68k有WFI吗?它是MIPS的标准功能吗?我对低级编程的熟悉主要是在ARM上,其中低功耗是理所当然的事,而WFI只是电源管理冰山一角。
吉尔斯

1
@Gilles 8086暂停了指令。请参阅en.m.wikipedia.org/wiki/HLT_(x86_instruction)。该说明仅从80486 DX4起才包含节电功能。回顾历史HLT早在8080年就已经衍生出来(例如Z80)。
pabouk '17

1
HLT在DX4出现之前,@ pabouk 可以关闭386和486的SL变体(维基百科的文章不正确)。
斯蒂芬·基特

0

不,空闲任务不会浪费CPU周期。调度程序根本不会选择一个空闲进程来执行。空闲进程正在等待某些事件发生,以便它可以继续。例如,它可以等待read()系统调用中的输入。

顺便说一下,内核不是一个独立的进程。内核代码总是在进程的上下文中执行(嗯,内核线程的特殊情况除外),因此说“内核本身将持有一个CPU而不会执行用户空间工作”是不正确的。


3
嗯...我不认为这是CLONE_IDLETASK创建的那种空闲过程。如果那样的话,根本就不需要创建它,即,如果调度程序忽略了CPU上的内核空闲进程,那么它将不需要在启动期间为其创建任何进程。(尽管DW不是我的:))
恶作剧时间:

稍作谷歌搜索后发现,CLONE_IDLETASK是一个内核内部标志,于2002年在内核
2.5.14

“一个”空闲进程,但不会“ ”空闲进程。
immibis
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.