Kernelmodusbit

Kernelmodusbit

Ich habe das Folgende im Buch „Betriebssysteme und Konzepte“ von Galvin gelesen.

"Ein Bit, das sogenannte Modusbit, wird der Hardware des Computers hinzugefügt, um den aktuellen Modus anzuzeigen: Kernel(0) oder Benutzer(1). Mit dem Modusbit können wir zwischen einer Aufgabe unterscheiden, die im Auftrag des Betriebssystems ausgeführt wird, und einer, die im Auftrag des Benutzers ausgeführt wird."

Wenn es sich nun um ein Mehrprozessorsystem handelt, nehmen wir an, dass ein Prozess einen Systemaufruf ausführt und das Modusbit von 1 auf 0 ändert.

Da es sich um ein Mehrprozessorsystem handelt, laufen möglicherweise noch andere Prozesse parallel im Benutzermodus, doch das Modusbit ist auf 0 gesetzt, was auf den Kernelmodus hinweist und Inkonsistenzen verursacht.

Ist also die Anzahl der Register (erforderlich zum Speichern des Modus-Bits) von der Anzahl der Prozessoren abhängig?

Antwort1

Ihr Buch vereinfacht die Dinge zu sehr. In Wirklichkeit hängt es von der CPU ab, wie der Modus eingestellt wird, und es ist nicht unbedingt ein „Bit“, noch gibt es unbedingt nur zwei Modi.

Für die Zwecke dieser Frage gehen wir von Linux, Intel x86 und Multicore aus.

Multitasking wird durch Kontextwechsel implementiert, der unter Linux softwarebasiert ist. Ein Kontextwechsel stoppt einfach die aktuelle Tätigkeit des Prozessors (eines Kerns oder einer CPU), speichert seinen Zustand im RAM und ersetzt ihn dann durch einen anderen Kontext.

x86 implementiert Schutzringe, die auf jedem Prozessor gesetzt werden können, bevor die Ausführung auf Prozessebene erfolgt. Der Linux-Kernel handhabt dies, indem er Prozesse auf Ring 3 (unprivilegiert) setzt, bevor die Ausführung in ihrem Speicherbereich beginnt. Durch die Implementierung des zuvor erwähnten Kontextwechsels behält der Kernel das Konzept eines Prozesses bei, der auf einem bestimmten Thread ausgeführt wird (bei Intel häufig 2 Threads pro Kern), denn wenn der Code dieses Programms ausgeführt wird, setzt der Kernel den Ring immer wieder auf 3 zurück, obwohl der Prozessor Kontextwechsel feststellt, die mehrmals pro Sekunde stattfinden, sodass viele Prozesse auf demselben Kern ausgeführt werden. Dies kann im Wesentlichen auf die gleiche Weise mit einem oder mehreren Kernen erfolgen.

Wenn ein Thread unter Linux mit x86 von Ring 3 zu Ring 0 (Supervisor) wechseln möchte, kann er dies nur mit einem Software-Interrupt tun. In den Ringen 1 und 2 ist dies auch mit speziellen Anweisungen möglich, aber Linux implementiert dies nicht. Da Linux den Software-Interrupt-Handler steuert, kann es sicherstellen, dass der Thread, obwohl er sich jetzt in Ring 0 befindet, nur Code im „Kernelbereich“ ausführt, d. h. in Code, der Teil des Kernels ist, obwohl es derselbe Thread ist, der Code im Benutzerbereich ausgeführt hat. In der Sprache der Betriebssysteme wird dies einfach als Systemaufruf bezeichnet, da dies das ist, was er wirklich tut. Ob Sie dies als Wechsel des „Prozesses“ in den Kernelmodus und zurück betrachten oder als effektiv angehalten betrachten, da nur Code im Kernelbereich ausgeführt wird, bis er wieder in den Benutzerbereich übergeht, bleibt Ihnen überlassen.

Da x86 es denjenigen in hohen Ringen erlaubt, zu niedrigeren zu wechseln, kann es nach Abschluss des Interrupt-Handlers wieder zu 3 wechseln. Dies geschieht mit allen Systemaufrufen, daher können alle Systemaufrufe aus der Hardwareperspektive alles auf dem System tun. Es könnte jede Anweisung Ihres Programms rückwärts ausführen und dann Ihren gesamten Code aus dem Speicher löschen, wenn es wollte. Oder es könnte zu Ring 0 wechseln und die Ausführung am Anfang Ihres Programms beginnen. Wie Sie sehen, zerstören diese Beispiele die Idee des „Kernel/Benutzer“-Modus, da ein solches Konzept in der Hardware nicht existiert. Unter Linux wird es jedoch immer als Aufruf in den Kernel-Speicher und als Rückkehr in den Benutzer-Speicher implementiert (effektiv ist der Speicher unter x86 nicht vor Ring 0 geschützt).

Aus diesem Grund wird die Umschaltung zwischen Kernel- und Benutzermodus mithilfe eines Software-Interrupt-Handlers implementiert, der aus dem Thread-Schutzring ausbrechen kann, jedoch so implementiert ist, dass die Ausführung nur dann im Kernelbereich erfolgt und dann wieder in den Benutzerbereich zurückgegeben wird, genauer gesagt an den Benutzerbereichsprozess, der den Systemaufruf ausgeführt hat, jedoch erst nach der Rückkehr zu Ring 3.

verwandte Informationen