Ich möchte im anderen hier noch einen Aspekt zu den Betriebssystembefehlen noch mal aufgreifen.
Und der bezieht sich auf den sogenannten Laufzeitkontext, der bei der Ausführung
solcher Betriebssystembefehle relevant ist. Nun so ein Laufzeitkontext ist allgemein der Kontext
eines Programmablaufs. Es ist also ein gewisser Zustand, der bei der Ausführung eines Programms,
nicht nur eines Maschinenprogramms, sondern eigentlich jeglichen Programms definiert wird.
Und dieser Zustand ist der, sagen wir mal, für diesen Programmablauf relevante Prozesserstatus,
der sogenannte Prozesserstatus. Dieser Status ist eigentlich in dem Programm selbst definiert,
nämlich aufgrund der Berechnungsvorschrift des Programms. Er ist aber in Art und Mächtigkeit,
in Abhängigkeit von den Maschinenbefehlen, die in dem Programm codiert sind, durchaus
unterschiedlich groß. Nun der Prozesserstatus allgemein ist der im Programmiermodell der CPU
definierte Zustand für einen bestimmten Prozessor. Der manifestiert sich eben im Registersatz dieser
CPU und zwar in den Daten, die in diesem Registersatz gespeichert sind. Wenn wir jetzt einen Kontextwechsel
durchführen, dann sagt man, dass für diesen Prozesserstatus die Konsistenz zu wahren ist.
Und der Kontextwechsel findet jetzt hier typischerweise zum Beispiel statt, wenn wir Unterprogrammaufrufe
haben, Systemaufrufe bis hin zu sogenannten Coroutinenaufrufen. Die Coroutinen werden wir
später kennenlernen, wenn wir den Begriff des Prozesses ein bisschen weiter auseinandernehmen.
Hier sind die Aufrufkonventionen des jeweiligen Prozessors in Abhängigkeit vom Compiler,
der verwendet wird und des Betriebssystems eben auch relevant, um sagen zu können, wie groß denn
dieser Kontext eigentlich ist und was denn bei einem Kontextwechsel zur Konsistenzwahrung zu
berücksichtigen ist. Hier unterscheidet man zwischen sogenannte flüchtige und nicht flüchtige
Register, die praktisch diesen Prozessorstatus mehr oder weniger definieren würden. Die flüchtigen
Register sind diese CPU-Register, deren Inhalt als unbeständig gilt. Man geht davon aus, dass
diese Registerinhalte zu beliebigen Zeitpunkten eigentlich verändert werden und dass, wenn es
wichtig ist, dass diese Registerinhalte konsistent bleiben, dann sind diese Registerwerte auf der
aufrufenden Ebene zu speichern, zu sichern. Das sind die sogenannten Caller-Saved-Register. Bei
dem x86, bei der 32-Bit-Familie vom x86 sind das typischerweise diese drei Register EAX, ECX und
EDX, die in diese Kategorie fallen. Alle anderen Register dieses Prozessors sind die sogenannten
nicht flüchtigen Register. Hier geht man davon aus oder hier wird gefordert, dass diese Inhalte
der Register eben beständig sein müssen. Das heißt, ihr muss unverändert bleiben, so ein
Registerinhalt. Das bedeutet letztendlich, dass falls Register innerhalb einer aufgerufenen
Prozedur etwa verwendet werden und verändert werden, dann sind diese Registerinhalte vor
Verwendung in der Prozedur zu speichern, zu sichern und vor Rückkehr aus dieser Prozedur
wiederherzustellen. Das sind die sogenannten Caller-Saved-Register, die man als Bestandteil
eines solchen Laufzeitkontextes hat. Mal hier ein Beispiel, um das ein bisschen zu verdeutlichen,
mit einem ganz einfachen Programm, wo dann diese Register eine Rolle spielen und wir eben auch ein
bisschen weiter sehen können, wie der Prozessorstatus oder welcher Prozessorstatus hier
praktisch bei der Ausführung einer solchen Prozedur, einer solchen Aufrufsrelevant ist.
Und zwar geht es darum, einfach eine Prozedur zu haben, die in der Lage ist, Inhalte zweier
Speicherzellen auszutauschen, die Swap-Prozedur. Die bekommt dann als Parameter zwei Zeiger für
die eine Speicherstelle und für die andere Speicherstelle, um die es halt geht. Ja,
und dann werden die hier ausgetauscht. Man hat dann typischerweise diese drei Anwendungen,
die auf der C-Ebene dann durchgeführt werden. Die muss ich nicht im Einzelnen durchgehen,
wir sehen es gleich noch ein bisschen später. Die sind relativ einfach. Der Aufruf dieser
Prozedur würde dann so stattfinden, Swap, und man übergibt dann letztendlich die Adressen auf,
die beiden Speicherzellen, deren Inhalte dann praktisch auszutauschen wären. Nun,
wenn wir uns anschauen, wie diese Prozedur auf der Ebene 4 oder im subolischen Maschinencode auf
weiter tieferen Ebenen dann halt aussieht, dann haben wir diese Implementierung letztendlich hier.
Aber die greifen wir gleich noch mal später auf. Zunächst wollen wir mal rein vom logischen Ablauf
für diesen Austausch uns anschauen, wie denn praktisch die Ausführung geschieht und welche
Schritte dort durchlaufen werden und wie sich denn eigentlich der Prozessorstatus so entwickelt.
Presenters
Zugänglich über
Offener Zugang
Dauer
00:28:40 Min
Aufnahmedatum
2020-05-09
Hochgeladen am
2020-05-10 02:36:05
Sprache
de-DE