Ich lese Robert Loves "Linux Kernel Development" und bin auf folgende Passage gestoßen:
Keine (einfache) Verwendung von Gleitkommazahlen
Wenn ein User-Space-Prozess Gleitkomma-Anweisungen verwendet, verwaltet der Kernel den Übergang vom Ganzzahl- zum Gleitkomma-Modus. Was der Kernel bei der Verwendung von Gleitkommaanweisungen tun muss, hängt von der Architektur ab. Der Kernel fängt jedoch normalerweise eine Falle und leitet dann den Übergang vom Ganzzahl- zum Gleitkommamodus ein.
Im Gegensatz zum User-Space bietet der Kernel nicht den Luxus einer nahtlosen Unterstützung für Gleitkommazahlen, da er sich nicht leicht selbst einfangen kann. Die Verwendung eines Gleitkommas im Kernel erfordert unter anderem das manuelle Speichern und Wiederherstellen der Gleitkommaregister. Die kurze Antwort lautet: Tu es nicht! Außer in den seltenen Fällen befinden sich keine Gleitkommaoperationen im Kernel.
Ich habe noch nie von diesen Modi "Ganzzahl" und "Gleitkomma" gehört. Was genau sind sie und warum werden sie gebraucht? Gibt es diese Unterscheidung bei gängigen Hardwarearchitekturen (wie x86) oder ist sie spezifisch für einige exotischere Umgebungen? Was genau bedeutet ein Übergang vom Integer- zum Gleitkomma-Modus, sowohl aus Sicht des Prozesses als auch des Kernels?
kernel_fpu_begin()
kernel_fpu_end()
, um sicherzustellen, dass der FPU-Status des Benutzerbereichs nicht beschädigt wird. Dies ist, was Linux-md
Code für RAID5 / RAID6 tut.Antworten:
Weil...
... kann ein Betriebssystemkern die FPU einfach ausschalten. Presto, kein Status zum Speichern und Wiederherstellen und daher schnellerer Kontextwechsel. (Dies ist, was Modus bedeutete, es bedeutete nur, dass die FPU aktiviert wurde.)
Wenn ein Programm eine FPU-Operation versucht, wird das Programm in den Kernel eingefangen, der Kernel schaltet die FPU ein, stellt den möglicherweise bereits vorhandenen gespeicherten Status wieder her und kehrt dann zurück, um die FPU-Operation erneut auszuführen.
Zum Zeitpunkt des Kontextwechsels weiß es, dass es tatsächlich die Statusspeicherlogik durchläuft. (Und dann kann es die FPU wieder ausschalten.)
Übrigens glaube ich, dass die Erklärung des Buches aus dem Grund, warum Kernel (und nicht nur Linux) FPU-Operationen vermeiden, ... nicht ganz korrekt ist. 1
Der Kernel kann in sich selbst einfangen und tut dies für viele Dinge. (Timer, Seitenfehler, Gerätealarme, andere) . Der wahre Grund ist , dass der Kern vor allem nicht braucht FPU ops und muss auch ohne FPU überhaupt auf Architekturen laufen. Daher wird einfach die Komplexität und Laufzeit vermieden, die zum Verwalten des eigenen FPU-Kontexts erforderlich sind, indem keine Operationen ausgeführt werden, für die es immer andere Softwarelösungen gibt.
Es ist interessant festzustellen, wie oft der FPU-Status gespeichert werden müsste, wenn der Kernel FP verwenden möchte . . . Jeder Systemaufruf, jeder Interrupt, jeder Wechsel zwischen Kernel-Threads. Selbst wenn gelegentlich Kernel-FP 2 benötigt würde , wäre es wahrscheinlich schneller, dies in Software zu tun.
1. Das heißt, absolut falsch.
2. Ich kenne einige Fälle, in denen Kernel-Software eine Gleitkomma-Arithmetik- Implementierung enthält. Einige Architekturen implementieren herkömmliche FPU-Operationen in Hardware, überlassen jedoch einige komplexe IEEE-FP-Operationen der Software. (Denken Sie: Denormale Arithmetik.) Wenn ein seltsamer IEEE-Eckfall auftritt, werden sie in einer Software abgefangen, die eine pedantisch korrekte Emulation der Operationen enthält, die abfangen können.
quelle
Bei einigen Kernel-Designs werden die Gleitkommaregister nicht gespeichert, wenn eine "Kernel" - oder "System" -Aufgabe ausgeschaltet wird. (Dies liegt daran, dass die FP-Register groß sind und sowohl Zeit als auch Platz zum Sparen benötigen.) Wenn Sie also versuchen, FP zu verwenden, werden die Werte zufällig "puffen".
Darüber hinaus verlassen sich einige Hardware-Gleitkomma-Schemata darauf, dass der Kernel "Oddball" -Situationen (z. B. Nullteilung) über einen Trap behandelt, und der erforderliche Trap-Mechanismus befindet sich möglicherweise auf einer höheren "Ebene" als die derzeit ausgeführte Kernel-Task.
Aus diesen (und einigen weiteren) Gründen werden einige Hardware-FP-Schemata abgefangen, wenn Sie zum ersten Mal in einer Aufgabe einen FP-Befehl verwenden. Wenn Sie FP verwenden dürfen, wird in der Aufgabe ein Gleitkomma-Flag aktiviert. Wenn nicht, werden Sie vom Exekutionskommando erschossen.
quelle
kernel_fpu_begin()
/kernel_fpu_end()
vor / nach Ihrem Code, um das Speichern / Wiederherstellen des FPU-Status des Benutzerbereichs auszulösen (und ich schätze Ihren Kernel-FPU-Status gegen Vorkauf).