Was macht ein CPU-Prozess im Leerlauf?


73

Als straceich die Quelle von betrachtete, fand ich die Verwendung des Klon-Flags, CLONE_IDLETASKdas dort beschrieben wird als:

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

Nach eingehenderem Hinsehen stellte ich fest, dass man cloneder Kernel dieses Flag zwar nicht behandelt , aber tatsächlich während des Startvorgangs verwendet, um inaktive Prozesse (die alle PID 0 haben sollten) für jede CPU auf dem Computer zu erstellen. dh eine Maschine mit 8 CPUs hat mindestens 7 (siehe Frage unten) solche Prozesse "laufen" (Anführungszeichen beachten).

Das führt mich nun zu ein paar Fragen darüber, was dieser "Leerlauf" -Prozess tatsächlich macht. Ich gehe davon aus, dass die NOP-Operation kontinuierlich ausgeführt wird, bis der Zeitrahmen abgelaufen ist und der Kernel einen realen Prozess zum Ausführen oder erneuten Zuweisen des Leerlaufprozesses zuweist (wenn die CPU nicht verwendet wird). Das ist jedoch eine vollständige Vermutung. Damit:

  1. Werden auf einer Maschine mit beispielsweise 8 CPUs 7 solche Leerlaufprozesse erzeugt? (und eine CPU wird vom Kernel selbst gehalten, während keine Userspace-Arbeit ausgeführt wird?)

  2. Ist der Leerlaufprozess wirklich nur ein unendlicher Strom von NOP-Operationen? (oder eine Schleife, die dasselbe tut).

  3. uptimeBerechnet sich die CPU-Auslastung einfach daraus, wie lange der Leerlaufprozess auf der CPU war und wie lange er während eines bestimmten Zeitraums nicht vorhanden war?


PS Es ist wahrscheinlich, dass ein Großteil dieser Frage auf die Tatsache zurückzuführen ist, dass ich nicht vollständig verstehe, wie eine CPU funktioniert. Das heißt, ich verstehe die Assembly, die Zeitrahmen und die Interrupts, aber ich weiß nicht, wie eine CPU zum Beispiel je nach Ausführung mehr oder weniger Energie verbraucht. Ich wäre dankbar, wenn mich auch jemand aufklären könnte.


17
Ich musste der Versuchung widerstehen, einfach "Gar nichts" zu schreiben, als ich den Titel sah.
Vality

4
Die meisten modernen CPUs senken im Leerlauf oder unter geringer Last dynamisch ihre Taktrate und ihren Stromverbrauch ( dynamische Frequenzskalierung , z. B. SpeedStep für Intel-CPUs). Wenn Sie eine CPU übertakten, wird dieses Verhalten normalerweise deaktiviert, sodass die CPU auch im Leerlauf die maximale Taktrate beibehält.
Nat

2
Siehe auch "ACPI-Energiezustände": Es gibt verschiedene Möglichkeiten, wie ein Prozessor die Ausführung von Anweisungen beenden kann, aber dennoch aktiv sein kann.
pjc50

Antworten:


85

Die Leerlaufaufgabe wird zur Prozessabrechnung und zur Reduzierung des Energieverbrauchs verwendet. Unter Linux wird für jeden Prozessor eine inaktive Task erstellt und an diesen Prozessor gebunden. Wenn auf dieser CPU kein anderer Prozess ausgeführt werden kann, wird die inaktive Task geplant. Die für die inaktiven Aufgaben aufgewendete Zeit wird in Tools wie z top. (Die Betriebszeit wird anders berechnet.)

Unix scheint immer eine Leerlaufschleife gehabt zu haben (aber nicht unbedingt eine eigentliche Leerlaufaufgabe, siehe Gilles 'Antwort ), und selbst in V1 verwendete es einen WAITBefehl, der den Prozessor anhielt, bis ein Interrupt auftrat (es stand für „Warte auf“) unterbrechen"). Einige andere Betriebssysteme verwendeten insbesondere Busy Loops, DOS, OS / 2 und frühere Versionen von Windows. CPUs verwenden diese Art von "Warte" -Anweisung schon seit geraumer Zeit, um ihren Energieverbrauch und ihre Wärmeerzeugung zu senken. Sie können verschiedene Implementierungen von Leerlaufaufgaben sehen, zum Beispiel im arch/x86/kernel/process.cLinux-Kernel: der grundlegende ruft nur aufHLTDie anderen Implementierungen behandeln verschiedene Fehler oder Ineffizienzen ( z. B. bei einigen CPUs MWAITanstelle von HLT).

All dies ist völlig unabhängig von Leerlaufzuständen in Prozessen, wenn sie auf ein Ereignis warten (E / A usw.).


3
Heh, ich sehe es jetzt, danke. play_dead()ist ein sehr schöner mnemonischer Name für die Ausführung von HALT. Wäre es nicht riskant, HALT an jede CPU zu senden und folglich zu hängen? (Das heißt, diese Situation zu erreichen, jede CPU
anhalten

30
Die CPU wacht über einen Interrupt aus HALT auf.
Johan Myréen

1
@ JohanMyréen - Cool, das macht Sinn. In einem solchen Fall würde sogar ein IRQ-Interrupt von einem Eingabegerät es wieder aufwecken. Vielen Dank.
Grochmal

15
Oder zuverlässiger, die Timer-Unterbrechung ... (Tickless Handling ist ein weiterer Kessel von Fisch.)
Stephen Kitt

3
@EJP ist in der Tat eine ziemlich häufige Anweisung, obwohl sie in verschiedenen Architekturen unterschiedliche Namen hat.
user253751

50

Wenn im Lehrbuchentwurf eines Prozessplaners kein Prozess zu planen ist (dh wenn alle Prozesse blockiert sind und auf Eingaben warten), wartet der Planer auf eine Prozessorunterbrechung. Die Unterbrechung kann eine Eingabe von einem Peripheriegerät anzeigen (Benutzeraktion, Netzwerkpaket, abgeschlossenes Lesen von einer Platte usw.) oder kann eine Zeitgeberunterbrechung sein, die einen Zeitgeber in einem Prozess auslöst.

Der Scheduler von Linux hat keinen speziellen Code für einen Fall, in dem nichts zu tun ist. Stattdessen verschlüsselt es den nicht zu erledigenden Fall als einen speziellen Prozess, den Leerlaufprozess. Der Leerlaufprozess wird nur eingeplant, wenn kein anderer Prozess planbar ist (er hat effektiv eine unendlich niedrige Priorität). Der inaktive Prozess ist in der Tat Teil des Kernels: Es ist ein Kernel-Thread, dh ein Thread, der Code im Kernel ausführt, anstatt Code in einem Prozess. (Genauer gesagt, es gibt einen solchen Thread für jede CPU.) Wenn der Leerlaufprozess ausgeführt wird, führt er die Warten-auf-Interrupt-Operation aus.

Wie das Warten auf Unterbrechung funktioniert, hängt von den Fähigkeiten des Prozessors ab. Bei dem grundlegendsten Prozessordesign handelt es sich lediglich um eine Besetztschleife.

nothing:
    goto nothing

Der Prozessor führt für immer einen Verzweigungsbefehl aus, der nichts bewirkt. Die meisten modernen Betriebssysteme tun dies nur, wenn sie auf einem Prozessor laufen, auf dem es nichts Besseres gibt, und die meisten Prozessoren haben etwas Besseres. Im Idealfall sollte der Prozessor ausgeschaltet sein, anstatt nur Energie für die Beheizung des Raums zu verbrauchen. Der Kernel führt also Code aus, der den Prozessor anweist, sich selbst oder zumindest den größten Teil des Prozessors auszuschalten. Es muss mindestens ein kleiner Teil eingeschaltet bleiben, der Interrupt-Controller. Wenn ein Peripheriegerät einen Interrupt auslöst, sendet der Interrupt-Controller ein Wecksignal an den Hauptprozessor (einen Teil davon).

In der Praxis haben moderne CPUs wie Intel / AMD und ARM viele komplexe Einstellungen für die Energieverwaltung. Das Betriebssystem kann abschätzen, wie lange der Prozessor im Leerlaufmodus verbleibt, und wählt abhängig davon verschiedene Energiesparmodi aus. Die Modi bieten unterschiedliche Kompromisse zwischen dem Stromverbrauch im Leerlauf und der Zeit, die zum Aufrufen und Verlassen des Leerlaufmodus erforderlich ist. Auf einigen Prozessoren kann das Betriebssystem auch die Taktrate des Prozessors senken, wenn es feststellt, dass Prozesse nicht viel CPU-Zeit verbrauchen.


5
Beachten Sie, dass selbst die einfachsten Embedded-CPUs wie AVR-basierte Mikrocontroller einen WFI-Befehl (Wait For Interrupt) haben, obwohl dieser Befehl je nach Modell möglicherweise NOP entspricht.
Jonas Schäfer

@JonasWielicki Ich dachte, du würdest normalerweise nur in eine enge Schleife geraten, wenn du nichts zu tun hättest, oder du könntest in einen Energiesparmodus wechseln und warten, bis der Interrupt dich davon abhält (Energiesparmodus erfordert normalerweise mehr). Metall "unterbricht).
Nick T

1
Bei @JonasWielicki-Architekturen für eingebettete Systeme geht es um die Energieverwaltung, daher ist WFI dort wichtig. Viele ältere Architekturen haben so etwas nicht. Die ursprüngliche 8086-Architektur hat es nicht getan, AFAIR. Hat 68k WFI? Ist es eine Standardfunktion bei MIPS? Meine Vertrautheit mit der Low-Level-Programmierung liegt hauptsächlich bei ARM, wo ein geringer Stromverbrauch eine Selbstverständlichkeit ist und WFI nur die Spitze des Power-Management-Eisbergs ist.
Gilles

1
@ Gilles 8086 hatte eine Halt-Anweisung. Siehe en.m.wikipedia.org/wiki/HLT_(x86_instruction) Die Anweisung enthielt nur Energiesparfunktionen seit 80486 DX4. Rückblick auf die Geschichte HLT war bereits in 8080 und Derivaten (wie Z80).
Pabouk

1
@pabouk HLTkonnte SL-Varianten des 386 und 486 ausschalten , bevor der DX4 herauskam (der Wikipedia-Artikel ist falsch).
Stephen Kitt

0

Nein, eine inaktive Task verschwendet keine CPU-Zyklen. Der Scheduler wählt einfach keinen inaktiven Prozess zur Ausführung aus. Ein Leerlaufprozess wartet auf das Eintreten eines Ereignisses, damit es fortgesetzt werden kann. Beispielsweise kann es auf eine Eingabe in einem read()Systemaufruf warten .

Der Kernel ist übrigens kein separater Prozess. Kernel-Code wird immer im Kontext eines Prozesses ausgeführt (naja, mit Ausnahme des Sonderfalls eines Kernel-Threads), daher ist es nicht korrekt zu sagen, dass "und eine CPU vom Kernel selbst gehalten wird, während keine Userspace-Arbeit ausgeführt wird".


3
Hmmm ... ich glaube nicht, dass dies die Art von Leerlaufprozess ist, der von CLONE_IDLETASK erstellt wird. Wäre dies der Fall gewesen, müsste es überhaupt nicht erstellt werden, dh hätte der Scheduler die Kernel-Leerlaufprozesse auf den CPUs ignoriert, müsste er während des Startvorgangs keine Prozesse für sie erstellen. (die DW ist aber nicht meins :))
Grochmal

Ein bisschen googeln zeigt, dass CLONE_IDLETASK ein kernelinternes Flag ist, das um die Kernel-Version 2.5.14 im Jahr 2002 eingeführt und später im Jahr 2004 entfernt wurde.
Johan Myréen

"ein" Leerlaufprozess, aber nicht " der " Leerlaufprozess.
user253751
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.