Als strace
ich die Quelle von betrachtete, fand ich die Verwendung des Klon-Flags, CLONE_IDLETASK
das dort beschrieben wird als:
#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */
Nach eingehenderem Hinsehen stellte ich fest, dass man clone
der 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:
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?)
Ist der Leerlaufprozess wirklich nur ein unendlicher Strom von NOP-Operationen? (oder eine Schleife, die dasselbe tut).
uptime
Berechnet 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.
quelle
Antworten:
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
WAIT
Befehl, 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 imarch/x86/kernel/process.c
Linux-Kernel: der grundlegende ruft nur aufHLT
Die anderen Implementierungen behandeln verschiedene Fehler oder Ineffizienzen ( z. B. bei einigen CPUsMWAIT
anstelle vonHLT
).All dies ist völlig unabhängig von Leerlaufzuständen in Prozessen, wenn sie auf ein Ereignis warten (E / A usw.).
quelle
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 CPUWenn 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.
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.
quelle
HLT
konnte SL-Varianten des 386 und 486 ausschalten , bevor der DX4 herauskam (der Wikipedia-Artikel ist falsch).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".
quelle