Das bitte. Gut, ja, nachdem ich vorgestern,
ja, also dieses Kapitel über Betriebssysteme angefangen hatte und dort
also erst mal so ein bisschen was zur historischen Entwicklung gesagt habe,
also sprich von ursprünglich reiner Einbenutzerrechner dann eben über den Badge-Betrieb,
dann eben bis zum Multitasking bzw. Multi-Programming und dann eben mehr Benutzerbetriebssystemen landen wir jetzt also hier nochmal so ein bisschen so bei dem,
was eigentlich heutzutage aller aktuellen Betriebssysteme auszeichnet.
Eingangs hatte ich ja schon gesagt,
also ich werde jetzt nicht speziell also auf Eigenheiten von Betriebssystem XY
irgendwie darauf eingehen, weil dazu fehlt leider die Zeit.
Ansonsten muss man immer sagen, also bei den meisten Betriebssystemen,
also wenn man zumindest so die weit verbreitet nimmt,
sind eigentlich die Konzepte relativ ähnlich.
Also da gibt es jetzt nicht so die großen Unterschiede zwischen Windows und Linux beispielsweise,
weil zumindest die Art und Weise, wie jetzt mit Prozessen umgegangen wird,
wie der Speicher verwaltet wird und so weiter.
Das ist eigentlich schon vergleichsweise ähnlich, heißt dann,
aber ihr werdet es ein bisschen anders und ist sicherlich im Einzelnen natürlich auch ganz anders implementiert.
Aber die Funktionalität ist eigentlich immer gleichartig. Gut, ja,
also zentrale Elemente eigentlich sind es aktuellen Betriebssystems, sind das,
was man also hier so ein bisschen sehen kann.
Also zum einen hatte ich ja schon gesagt,
als Programmierschnittstelle für das eigentliche Programm hat man dann eben sowas wie ein System-Call.
Das heißt, das Programm ruft halt eben irgendeine Betriebssystemfunktion oder Funktionalität
auf und hat darüber dann eben Zugriff auf ein Ausgabegeräte auf Ressort Sourcen wie Festplatte,
Monitor und, und, und.
Nicht, das ist also im Prinzip das, was da mit drin ist. Dann das,
was jetzt also auch gleich noch als einzelnes Unterkapitel kommen wird,
das Thema Interakt, also Interakt ist im Prinzip,
dass man einfach sagt, es gibt halt im normalen Prozessablauf irgendwie besonderes Ereignis.
Dafür gibt es also relativ viele unterschiedliche Quellen,
die das auslösen können und die steuern dann im Rahmen des Betriebssystems dann nämlich genau diesen Ablauf,
wann läuft der Benutzerprozess auf der CPU und wann laufen Betriebssystemfunktionalitäten auf der CPU.
Das wird dann eben unter anderem durch Interraps letztendlich mitgeregelt und umgeschaltet.
Gut, dann gibt es einen ganzen Satz von unterschiedlichen Warteschlangen.
Wie gesagt, hier sind jetzt nur so einige drin.
Zum einen kann man sagen, für jedes Ein- und Ausgabengerät gibt es sowas,
wo dann also letztendlich die Befehle von unterschiedlichen Prozessen beispielsweise jetzt darauf warten, abgearbeitet zu werden.
Und dann gibt es eben einen ganzen Satz, nicht nur zwei,
sondern in der Regel deutlich mehr unterschiedliche Warteschlangen, wo Prozesse darauf warten,
also quasi die Ressource der CPU zugeteilt zu bekommen,
wo Prozesse dann aber auch Beispielsweise jetzt drin stehen, wenn sie unterschiedliche Prioritäten haben.
Gibt es mehrere Warteschlangen, wenn sie jetzt in unterschiedlichen Systemzuständen sind,
gibt es dann eben auch entsprechende Datenstrukturen, wo das Ganze dann eben letztendlich verwaltet wird.
Gut, und dann eigentlich immer als zentrale Komponente,
also analog zu dem, was bei dem Multi-Programming-System quasi der Monitor war.
Ein Schedular, in der Regel sind das sogar noch mehrere,
wo das ist die Komponente des Betriebssystems,
die jetzt erstmal Als erstes natürlich die zentrale Ressource vergibt.
Das heißt, welcher Prozess darf jetzt auf der CBU rechnen? Gut,
als Architektur zur Betriebssystem muss man dann auch mal sagen,
das kann jetzt also auf unterschiedliche Arten und Weisen geregelt werden. Ich hatte ja schon gesagt,
man hat im Prinzip auch schon bei den relativ einfachen Systemen eine Trennung zwischen dem an Befehlen,
was also ein normaler Benutzer machen darf, nennt sich dann eben User-Mode,
der dann eben nur einen eingeschränkten Satz von Systembefehlen und auch nicht alle Speicheradressen beispielsweise darauf zugreifen kann und das,
was Colonel Mode ist, nämlich das,
was dann das Betriebssystem selber machen darf.
Und da gibt es jetzt also in Bezug auf die Betriebssystemarchitektur
dann eben die Unterscheidung zwischen sogenannten monolithischen Körnern,
wo dann also letztendlich all diese Funktionalitäten,
die ich jetzt also vorher genannt habe,
beziehungsweise was jetzt also hier noch vorgestellt wird.
Im Prinzip Teil des Betriebssystems sind. Das können also durchaus
mehrere getrennte Prozesse sein, sind aber eigentlich alles immer irgendwie
Teile des Betriebssystems,
die sich dann miteinander unterhalten
Oder aber als neueren Ansatz, der jetzt aber noch in,
wenn es gar nicht mehr überlegen, ich glaube,
in noch relativ wenigen Betriebssystemen überhaupt angedacht ist oder implementiert ist,
sogenannte Microcurnal, wo man sagt,
das eigentliche Betriebssystem macht eben nur Zuweisung der CPU an Prozesse,
Speicherverwaltung,
also die Zuweisung der einzelnen Prozesse jetzt irgendwie zu Speicherbereichen und die Kommunikation zwischen Prozessen.
So und alles, was dann quasi in Form von Dateizugriff
in Form von Geräte, Zugriff ist,
läuft dann also quasi wie ein Benutzerprozess letztendlich da mit drin.
Und dann eben noch irgendwie diverse Mischformen. Ansonsten historisch gesehen
sind eigentlich Betriebssysteme in der Regel erstmal noch monolithische Körner,
was da so als Funktion, Funktionalität unter anderem mit drin ist.
Also wie gesagt, die Grafik muss jetzt nicht auswendig lernen.
Hier nur als Beispiel führen Linux-System. Also ich habe hier
auf der Anwendungsseite letztendlich meine einzelnen Prozesse oder meine Threads.
Die kommunizieren quasi mit dem Betriebssystem,
mit dem Colonel über System Calls
Ich habe hier unten letztendlich meine Hardware,
also die CPU natürlich als zentrale Ressource, den Speicher.
Ich habe dann also irgendwelche, ein Ausgabegerede,
die in Linux dann immer noch in Character-Devices unterteilt werden,
also beispielsweise was wie ein Terminal,
also sprich eine Kommandozeile und Ausgabe auf dem Bildschirm, Block-Devices,
also was wie Festplaten und eben irgendwie Netzwerkschnittstellen mit den ganzen unterschiedlichen Protokollen.
So und innerhalb dieses Curnals gibt es dann also einen ganzen Satz von Prozessen bzw. von Funktionalitäten,
die dann letztendlich Ahnen wir hier das Geduling machen,
dann eben jeweils die jeweiligen Geräte oder Geräteklassen ansprechen.
Nicht dann die Art und Weise, wie Interraps verwaltet werden,
wie also jeder Speicher zugeordnet wird und, und, und.
Gut, ich bin mir jetzt auch nicht so ganz sicher,
als ob diese Grafik jetzt vollständig ist, weil zumindest vom Schedium,
meine ich, müsste also auch noch ein paar andere Sachen passieren,
aber gut, jedenfalls da sieht man also schon,
ich hatte ja eingangs gesagt, Betriebssysteme gehören eigentlich zu den komplexesten Programmen,
die wir in der Regel auf unseren Rechnern haben.
Gut, dann etwas, was aktuelle Betriebssysteme auch immer noch können,
ist etwas, was sich dann also bei den Prozessen auch noch vorstellen werde, sogenanntes Multi-Fredding.
Das ist jetzt also nochmal eine etwas feinere Unterteilung jetzt von diesem Prozessbegriff.
Also Prozess steht jetzt eigentlich erstmal nur für irgendein Anwendungsprogramm. Teilweise kann ich aber eben sagen,
in diesem Programm habe ich auch schon irgendwelche Parallelität inherent mit drin,
die kann ich dann eben auch als Programmierer vielleicht, also auch explizit unterstützen,
würde da dann also im Prinzip sowas wie mehrere Threads reinprogrammieren und dann eben zu sehen,
dass dann also gleich mehrere Sachen gleichzeitig laufen.
Wird dann also in dem 15.3 zu den Prozessen dann letztendlich nochmal kommen. Gut,
und dann etwas, was aktuelle Betriebssysteme logischerweise natürlich mitkönnen,
weil inzwischen unsere Prozessoren sind Simultanius, Multi-Processing, das heißt,
die können dann eben entsprechend auch mehrere Prozessoren,
mehrere CPUs irgendwie verwalten und ansprechen, möglicherweise für den Benutzer transparent.
Das heißt, es ist also,
wenn ich jetzt also hier irgendwie ein Betriebssystem installiere,
dann läuft das eben sowohl auf dem alten Rechner,
der jetzt also in einen Kern CBU hat oder irgendein eingebettetes System,
was also irgendwie in ANK ein CPU hat,
genauso gut wie jetzt da so offen, großen Workstation-Prozesse mit 50 CPU-Kernen.
Gut, was man damit dann natürlich erreicht, an Vorteilen ist,
ich habe eine gewisse Skalierbarkeit mit drin, performant stark logischerweise, Verfügbarkeit ist natürlich dann also
auch eine andere Auf der anderen Seite sind natürlich diese ganzen Abhängigkeiten,
die sich im Prinzip zwischen den einzelnen Teilen im Betriebssystem kern ergeben,
dann also nochmal wieder eine Nummer komplizierter, wenn ich mir jetzt überlege,
okay, was passiert jetzt, wenn ich jetzt also hier nicht nur eine CPU habe,
sondern jetzt eben hier mehrere, wo man dann eben sagt,
läuft dieses Betriebssystem dann quasi auf einem ausgewählten Kern oder kann ich das jetzt also über mehrere CPUs verteilen, wie sieht das da dann mit der Kommunikation aus.
Also da gibt es dann eben auch noch einige Sachen. Ansonsten ist es natürlich so,
dass man dadurch, wie gesagt, performance hier angedeutet,
sagen kann, wenn ich jetzt also nur einen Prozessor habe,
also klassisch Multi-Programming, also das, was wir in der Historie,
also quasi vorher da schon hatten, nicht, dass man eben sagt,
Prozess läuft, wird aus irgendwelchen Gründen unterbrochen, sei das,
weil die Zeitscheibe abgelaufen ist, sei das,
weil da auf irgendeine langsame, eine Ausgabe warten muss,
nicht, dann kann eben der nächste Prozess laufen,
der wird gegebenenfalls wieder unterbrochen,
der hier läuft weiter und so habe ich dann eben der Reihe nach immer mit mehrere Prozesse laufen,
wenn ich Multi-Processing-System habe, kann ich also beispielsweise,
wie jetzt hier in diesem Fall,
dann eben entsprechend auch schon zwei Prozesse parallel laufen lassen.
Gut, und wie gesagt, was da noch mit reinkommt,
sind dann eben solche Sachen mit verteilten Betriebssystemen.
Sprich, was passiert jetzt in irgendwelchen größeren Rechenzentren,
wenn ich jetzt also irgendwie ganze Cluster von Rechner habe,
kann ich das jetzt also quasi als ein verteiltes Betriebssystem nehmen und handhaben?
Oder sind das jetzt alles irgendwie getrennt laufende Rechner,
die sich jetzt nur über irgendwelche Signalmechanismen untereinander austauschen was dann eben auch noch mit hinzukommen kann,
sind, entsprechende spezielle Anforderungen,
die jetzt also hier natürlich dann also auch erst mal wegfahren,
also sprich, was ist mit Echtzeitbedingungen, was ist mit Fehlertoleranz.
Also sprich, nehmen wir als Beispiel sowas wie jetzt irgendein System,
wo beispielsweise jetzt Flugzeug, irgendwie Fluglagerregelung ist, dann sollte das System,
also zum einen irgendwie mehr oder minder fehlertolerant sein.
Das heißt, mental Komponenten ausfallen muss es immer noch funktionieren. Demzufolge,
wenn die dann typischerweise redundant ausgelegt, das heißt,
mehrere Hardware-Instanzen am besten noch von Unterschied unterschiedlichen Herstellern, mit unterschiedlicher Software,
sodass dann also nicht irgendwelche Entwurfsfehler einfach nur parallel auftreten.
Wäre auch blöd. Und Echtzeit dann eben auch noch,
wobei Echtzeit, also jetzt auch immer so ein bisschen in dem richtigen Sinne Echtzeit,
was anderes ist als das, was wir häufig darunter verstehen.
Also für uns ist Echtzeit immer, ich mache irgendwas und
das soll möglichst schnell laufen.
Im Sinne von Regelung oder Steuerung heißt Echtzeit eigentlich folgendes.
Ich habe irgendwie einen Prozess, der startet irgendwann zu einem
bestimmten Zeitpunkt
Und dann gibt es eben irgendwie eine Zeitdauer und nach Ende
dieser Zeitdauer gibt es dann eben irgendwie eine Deadline D.
Und bis dahin muss der Prozess ein Ergebnis abgeliefert haben.
Das muss nicht zwingend schnellstmöglich sein, aber verlässlich und muss hundertprozentig eingehalten werden. Nicht,
weil damit kann man dann letztendlich planen und sagen,
okay, wenn der Pilot einen Steuerbefehl gibt,
dass das nach so und so viel Millisekunden letztendlich irgendwo hinten bei der Hydraulik ankommt und dann entsprechend sich da was tut.
Nicht, dass es Echtzeit, der Prozess selber kann sein,
dass der jetzt also in der Rechenzeit hat,
die nur irgendwann hier so lange dauert und das,
was dann eben Betriebssystem beispielsweise passieren kann durch den Schedular,
dass der dann eben sagt, okay,
der Prozess fängt jetzt nicht hier an,
sondern der fängt irgendwann zu dem Zeitpunkt an zu laufen,
es muss halt eben nur gewährleistet sein,
dass er vor seiner Deadline zu Ende ist.
So nicht. Dafür hat man da dann nämlich auch wieder andere Scale-Ulling-Algorithmen,
andere Eigenschaften jetzt in Bezug auf die Prozesse als bei Standardbetriebssystemen.
Bei Standardbetriebssystemen macht man typischerweise Best-Effort, das heißt,
ich versuche möglichst allen gerecht zu werden und ich sehe dann eben auch zu,
dass jeder möglichst schnell ist,
nicht aber wirklich sowas wie hatte Echtzeitbedingungen gibt es da nicht,
weil da kann man sagen, okay,
im Hintergrund läuft irgendwas.
Ich lasse jetzt irgendwo Videostream laufen, lasse mir das anzeigen.
Ja, und Worst Case kann halt sein,
dass durch irgendeine Hintergrundaktivität der Videodeko da ein bisschen langsamer ist.
Okay, dann geht mal ein Bild verloren.
Das ruckelt vielleicht mal im Zweifelsfall, fällt mir das sowieso
nicht weiter auf. Nicht von daher stört das da dann
eigentlich nicht
Gut, hier noch mal zusammengefasst eigentlich so die ganzen Aufgaben des Betriebssystems.
Das ist auch ungefähr jetzt also das, was hier noch
an weiteren Unterkapiteln kommen wird. Also zum einen Prozessverwaltung, also Prozesse,
Staaten und Beenden, die dann eben den CPUs zuweisen,
also Scaduling, was passiert im Falle von Prozesswechseln.
Wie kriege ich Synchronisation zwischen Prozessen hin,
wenn ich jetzt eben sage, ich habe einen Prozess,
der irgendwelche Daten liest irgendwoher, einen Prozess,
der sie irgendwie verarbeitet,
anzeigt,
dann müssen die sich natürlich
irgendwo sinnigerweise miteinander unterhalten
Die Daten übergeben, wie auch immer das sein muss. Also alles, was damit dann zusammenhängt, dann das Thema Speicherverwaltung, wie wird der Hauptspeicher letztendlich betrachtet und den Prozessen zugeordnet. Nicht,
dann gibt es eben noch diesen Effekt des Swapings,
also dass man sagen kann, ich habe zum einen den Hauptspeicher,
ich habe dann aber eigentlich immer noch sowas wie virtuellen Speicher,
das heißt, die Festplatte dann als Ergänzung,
Erweiterung des Hauptspeichers, das was also im Prinzip in Windows,
diese Auslagerungsdatei ist und in Linux kann ich das also entweder in einzelnes Dateisystem oder auch in der Swap-Datei letztendlich reinbringen,
wo da dann eben,
wenn ich jetzt von den Prozessen mehr Speicher bräuchte,
als ich physikalischen im Rechner habe,
Teile ausgelagert werden oder wenn ich in meinem Prozess eben sehr große Datenstrukturen habe,
kann ich das machen, weil dann ist es,
wenn jetzt also zum Beispiel ein Prozess viele Daten benötigt,
würde zwar eigentlich einen Hauptspeicher passen,
er braucht von diesen Daten aber nun
relativ kleinen Blog
Wenn ich das jetzt alles in den Hauptspeicher laden würde,
würde es natürlich das Betriebssystem insofern einschränken,
als dass sich jetzt nicht mehr so viele Prozesse zulassen kann,
weil dann ja also schneller der Hauptspeicher aufgebraucht ist.
Dann kann das Betriebssystem eben beispielsweise sagen, Teile,
die jetzt von dem Prozess gerade nicht benötigt werden,
liegen virtuell letztendlich auf der Festplatte rum.
Ich tue dem Benutzer was Gutes,
lass lieber nochmal drei Prozesse mehr laufen,
weil da also vielleicht irgendwie darauf wartet,
also dass sich der Mauszeiger bewegt oder
irgendwas anderes passiert
Und habe dadurch dann also in dem Fall dann also ein deutlich höhere Responsibilität.
Solche Sachen kommen da dann eben auch noch mit rein. Gut,
also Speicherverwaltung, dann eben Verwaltung der ganzen einen Ausgabegeräte und
dann eben solche Sachen Interaktverarbeitung und was eigentlich auch immer noch passiert.
Accounting, also sprich Ressourcen werden abgerechnet, es werden Sachen protokolliert.
Für uns jetzt im Desktop-Bereich natürlich nicht so sonderlich interessant,
es sei denn,
man möchte jetzt also wirklich performancemäßig dann noch irgendwie an sein Programm was schrauben,
dann würde man also schon ein bisschen an welchen Stellen brauchen welche Programmteile zum Beispiel,
wie lange das kann ich dann eben auch alles durch das Betriebssystem quasi mit protokollieren lassen,
beziehungsweise bestimmte Eigenschaften.
Wichtig wird das aber natürlich spätestens dann,
wenn ich jetzt also irgendwie Betreiber eines Rechenzentrums bin oder von irgendwelchen Webservices,
die Kunden bei mir was gebucht haben und ich das dann quasi darüber abrechne.
Dann kann ich eben sagen, da ein Prozess hat,
so und so viel Speicher und die und die Ressourcen gebraucht
und hat so und so lange auf der CWU gerechnet und
demzuvor gekostet
als irgendwas
Ja, Thema Interrapts. Im Prinzip erst mal dumme Übersetzung des Worts.
Letztendlich wird erst mal nur der sequenzielle Ablauf in der Programmabarbeitung unterbrochen.
Brauche ich eben um den Prozessor entsprechend gut auslassen,
weil ich hatte ja am Mittwoch schon vorgestellt,
wenn ich jetzt also hier im Prinzip irgendwie sowas wie ein Gigahertz schnell getagt in einen Prozessor habe und ich jetzt also irgendwie auf Festplatten oder auf irgendwelche Sachen,
die ich also quasi übers Web angefordert habe,
die dann also vielleicht irgendwie, bist du irgendwie im Sekundenbereich irgendwie warten,
bis da irgendwelche Daten ankommen.
Macht es also jetzt relativ wenig Sinn, die ganze Zeit damit,
also die CBU zu belasten. Insgesamt gibt es mehrere Quellen,
wodurch jetzt letztendlich Indraps ausgelöst werden. Zum einen durch das laufende Programm selber,
also sprich, wenn ich jetzt irgendwelche Acceptions habe oder Ausnahmebehandlung,
also sprich Überläufe, Division durch null,
irgendeine ungültige Anweisung, irgendwelche ungültigen Adressen, irgendeine Anweisung,
die ich jetzt also im Benutzermodus nicht ausführen darf,
weil das eigentlich jetzt irgendwie was Spezielles von dem Betriebssystem wäre und so weiter.
Dann können Tharma-Interrats auslösen, das heißt,
ich kann eben zum einen, um jetzt bestimmte Betriebssystemaufgaben auszuführen,
sagen, es soll nach so und so viel wie ein Risiko,
Mikrosekunden, was auch immer, im Prinzip der normale Ablauf unterbrochen werden.
Es soll da dann irgendwas passieren. Oder ich kann eben in meinem Programm auch sagen,
beispielsweise jetzt also irgendeinen Sensor auslesen, irgendwelche Datenwerte auslesen,
alle so und so viel Millisekunden oder alle so und
so viele Sekunden möchte ich einen neuen Wert haben.
Und in der Zeit dazwischen kann der Prozess quasi schlafen
und muss dann also jetzt nicht weiter die CPU belasten
Gut, dann von den einen Ausgabeeinheiten, die dann ja,
wie gesagt, entsprechend langsam sind. Die können jetzt natürlich sagen,
irgendeine Operation, also lesen von der Festplatte,
ist jetzt bereit oder ist jetzt fertig,
die Daten sind da oder es sind irgendwelche Fehler aufgetreten und letztendlich Hardwarefehler,
also sprich, was passiert, wenn die Spannungsversorgungsprobleme hat,
System überhitzt, wenn ich jetzt also irgendwie, sofern ich,
also zumindest in dem Speicher jetzt irgendwie sowas wie eine Fehlerkennung mit drin habe,
ist damals was aufgetreten,
also sowas wie Speicherparität würde dann eben auch entsprechend über Enter-Ups gemeldet werden.
So, wie funktioniert das im Prinzip mit den Enter-Ups?
Also da hat sie jetzt hier folgendes Beispiel. Die Folie
würde ich jetzt hier gleich mal an der Grafik erklären.
Also ich habe hier mein Anwendungsprogramm. Das soll also erstmal
hier eine Zeit lang rechnen. Möchte dann also irgendwas auf
die Festplatte schreiben, also irgendwelche Daten. Das heißt,
da habe ich also irgendwie so ein einfaches Ride.
Das, was da im Prinzip dann passiert, ist,
dass dieser Zugriff umgesetzt wird in System Call.
Das heißt, da läuft dann also im Prinzip das Programm
oder dumm gesagt,
der Treiber für die Festplattenschnittstelle
Oder für die Dateischnittstelle. Das heißt, da wird das
Ganze dann eben umgesetzt, ich habe die Datei geöffnet.
Ich möchte, möchte da jetzt was schreiben,
dass dieses Programm dann letztendlich dem Festplattencontroller sagt,
an der und der Stelle soll was geschrieben werden.
So, das läuft hier auch erst mal irgendwie durch. So,
und dann vergeht in diesem Teil IO-Command hier eben vergleichsweise viel Zeit,
weil sich die Festplatte jetzt erst mal entsprechend positionieren muss.
Das heißt, der Kopf muss in die entsprechende Position.
Die Platte muss entsprechend weiter rumgedreht werden.
Das heißt, dafür gehen dann also schon mal irgendwie
einige Millisekunden
Irgendwann dann, sagt der Plattencontroller, diesem IO-Programm, okay,
jetzt kannst du die Daten lesen, das wird dann passieren.
Wenn das fertig ist, geht die Kontrolle dann quasi jetzt
wieder an mein Programm. Ich habe die Daten geschrieben,
rechne letztendlich weiter und beim nächsten Write passiert genau das Gleiche.
So, wenn ich das jetzt mit Interrupts mache,
kann man das jetzt eben insofern deutlich effizienter machen,
als dass man jetzt eben sagt, okay, ich schicke hier das Writer ab.
Der Treiber für die Platte macht im Prinzip genau das Gleiche,
schickt denen also quasi die Informationen da und da im Hauptspeicher
liegen die Daten und schreibe davon also irgendwie 50 Blöcke auf die Platte.
Und gebe dann die Kontrolle wieder direkt an das Programm zurück,
weil das, was hier eben diese Millisekunden warten,
sind, die müssen hier ja nicht mehr passieren,
weil im Prinzip die Informationen und alles, was geschehen soll,
ist quasi in Richtung Festplatte bzw. Festplattenhardware quasi rausgegangen.
Und das Programm kann eben hier an der Stelle
erstmal entsprechend weiterarbeiten
Irgendwann kommt der Interrabt. Sprich,
da meldet die Festplatte, ich habe das jetzt geschrieben,
beziehungsweise ich bin jetzt eben bereit zum Schreiben.
Dann würde eben quasi diese Programmabarbeitung an dieser Stelle hier unterbrochen werden.
Der Interrabthändler würde dann eben letztendlich diesen Befehl irgendwie abschließen.
Vielleicht jetzt eben die Daten da dann da dann eben noch
irgendwie zur Platte senden. Anschließend läuft das Programm eben an
dieser Stelle weiter und beim nächsten Writern eben genau das Gleiche.
So, und dann ist es eben letztendlich jetzt wieder davon abhängig,
wie schnell ist Diese Bearbeitung hier im Vergleich zu den Programmablauf.
Nicht, weil wenn diese Zeit hier jetzt erstmal vergleichsweise kurz ist,
dann kann ich hier meinetwegen jetzt noch irgendwie ein paar hunderttausend Prozesse,
Takte arbeiten und dann kommt eben der Interrabt.
Wenn dieses jetzt hier entsprechend länger dauert, dann habe ich die Situation,
wie sie auf der rechten Seite ist, nämlich,
dass der Befehl hier wird entsprechend abgeschickt.
Das Programm läuft weiter. Wie jetzt quasi hier
das nächste Ride machen
Es wurde aber inzwischen ja noch nicht mal dieses erste hier bestätigt.
Und in dem Fall würde an der Stelle das Ganze dann eben
auch erst mal hier dieses hier auch noch mal wieder in die Ausgabe geschicken.
An der Stelle hätte ich jetzt also quasi schon zwei Write-Befehle, wartend. Das heißt,
da brauche ich dann eben auch, das ist eben das,
was hier als IOQ bezeichnet ist, nämlich also quasi irgendwelche Warteschlangen,
wo gegebenenfalls dann also irgendwie die Befehle auch noch irgendwie der Reihe nach reingeschrieben werden.
Nicht irgendwann würden der erste Interabkommen,
das Ganze könnte dann also hier einmal durchlaufen,
wo wir dann hier wieder zurückgehen,
wo dann immer noch erstmal auf den zweiten Interab warten und
anschließend könnt das Ganze dann eben hier entsprechend dann erst wieder weiterlaufen.
Ja, in Bezug auf die Programmabarbeitung,
was muss sich jetzt ändern, um jetzt Interraps abzuarbeiten?
Also bislang hatten wir ja immer irgendwie von Neumann-Zyklus beziehungsweise das,
was so im Pipelining haben, also irgendwie Operantholen,
dekodieren und so weiter,
Execute und irgendwann läuft das Ganze dann eben zum nächsten Befehl
Das wird dann quasi, wenn jetzt Interraps aktiv sind,
eben noch dadurch ergänzt, dass man sagt,
am Ende der Programmarbeitung eines Befehls wird halt letztendlich noch geprüft,
sind Interraps aufgetreten.
Und wenn ja, muss dann eben dafür gesorgt werden,
dass dann eben letztendlich nicht die nächste Operation passiert,
sondern der Interrap abgearbeitet wird.
Das heißt also irgendwo im Programmablauf laufe ich jetzt eben hier
durch meine Instruktion, der Interrap taucht auf.
Dann wird also quasi jetzt hier ein Kontextwechsel gemacht
Interraptabgearbeitet und wenn das fertig ist,
geht das dann erst wieder mit dem Programmablauf weiter. Gut,
hier nochmal so die Abläufe für dieses eine Beispiel mit kurzer und mit langer Wartezeit,
wie man das jetzt also hier einmal ohne Interrapt habt und
wie das dann eben gegebenenfalls mit Interrapts dann eben noch ineinander geschachtelt ist.
Werde ich jetzt aber aus Zeitgründen auch hier überspringen.
Ja, was muss passieren, wenn jetzt ein Interrapt kommt?
Also zum einen liefert also irgendwie jetzt also irgendwelche Hardware den Interrapt.
Darauf muss natürlich in meinem Prozessor irgendwas darauf reagieren.
Das wird also erstmal irgendeine Hardware-Einheit sein
Die wird dann dafür sorgen, dass also quasi der aktive Befehl letztendlich beendet wird, liest sich jetzt immer einfach.
Also wenn ich jetzt also auch gerade hier sowas nehme,
rein praktisch habe ich natürlich das Problem,
dass ich eigentlich ein Pipelining mache und was ist dann gerade der aktuelle Befehl. Das,
was dann typischerweise passiert, ist, dass wenn Interrapt auftaucht,
quasi jetzt keine neuen Befehle mehr in die Pipeline kommen,
der Interrapt aber jetzt nicht sofort irgendwas tut,
sondern erstmal so und so viele Takte kommen,
um letztendlich die Pipelines zu lernen,
bis man sich ja sagen kann,
im Programmcode alle Befehle bis zu dieser Stelle sind fertig ausgeführt und alles danach müsste ich dann nach dem Ende des Interraps dann wieder neu aufsetzen und damit neu starten.
Das, was dann passiert, ist,
dass der Prozessor im Prinzip den Interrap hinsichtlich oder jetzt also
auf das aufrufende Gerät dann eben nochmal entsprechend bestätigt und kann es in Hardware oder in Software passieren,
dass also der Programmstatus geändert wird, also Programmzähler,
Registerinformationen, wie sieht die Speicherzuordnung aus,
wird auf eine interne Datenstruktur gesichert
Ähnlich wie bei Unterprogrammen aufrufen wird,
ist das Ganze eben als Deck organisiert. Nicht so,
dass von einem laufenden Prozess, wenn der unterbrochen wird,
quasi dessen Status irgendwo gesichert wird, interrabt,
fängt dann eben entsprechend an, wenn der Prozess wieder aufgesetzt wird,
wird das dann eben von diesem Stack aus wieder zurückgesichert,
also Program-Counter, Inhalt der ganzen Register und sowas alles.
Dann, um den eigentliche Interraptbearbeitung zu starten,
wird dann eben letztendlich der Programm-Counter mit der Startadresse initialisiert und
Das System wechselt dann eben quasi in diesen Curnal-Mod,
weil während der Interratbearbeitung werden dann letztendlich also privilegierte Befehle ausgeführt.
So, in dem Code von dem Interrat passiert dann eben das
gegebenenfalls jetzt also noch weitere Informationen hier von den Programmen irgendwie gesichert wird.
Nicht, dann kommt die eigentliche Abarbeitung. Wenn das fertig ist,
wird dann eben entsprechend der Programmstatus, der hier gesichert wurde
, wiederhergestellt. Der Programmstatus, der hier gesichert wurde,
Der Programm-Counter dann quasi jetzt mit dem nächsten Befehl aus meinem Programm initialisiert.
Und dann wird die Kontrolle eben wieder an das Programm übergeben
und das System wechselt dann eben wieder in den Usermuch.
Ist hier im Prinzip dann also noch einmal so aufgezeigt.
Also ich habe hier mein Benutzerprogramm, das läuft jetzt eben hier irgendwie bis zur Adresse N.
Im Prozessor würde jetzt quasi der Programm-Account auf N plus 1 stehen.
Das wäre der nächste Befehl, der dann abzuarbeiten ist.
Jetzt ist der Ingel-Up aufgetaucht. Das,
was dann passiert durch die Hardware, ist,
dass im Prinzip diese Folgebefehl aus dem Programm dann eben in diesem Control-Stack gespeichert wird.
Alles, was hier an Prozessoregistern ist, wird hier gespeichert.
Und der Stackpoint von dem Control-Stack wird dann ebenentsprechend passend aktualisiert.
Und für die Abarbeitung des Interraps wird dann eben eine Programmzähler
quasi jetzt hier mit der Startapresse von dem Interrap, also mit Y initialisiert.
Wenn ich dann läuft, dass der Interrap-Händler letztendlich,
also nichts anderes als ein stinknormales Programm,
Nur, dass es dann eben dem Betriebssystem gehört,
aber von der Funktionalität her auch erstmal nichts anderes.
So, wenn das fertig ist, hier dieser Rücksprung ist,
dann sind wir genau bei dieser Situation. Forger-Adresse wäre dieses hier,
es wird eben festgestellt, Interrab ist fertig,
Programm soll hier weiterarbeiten, also wird der Programm-Counter hiermit zurückgeladen,
die gespeicherten Register werden quasi zurückgeladen,
dieser Stack-Pointer für den Control-Stack wird eben hierhin wieder zurückgesetzt und
anschließend kann dann eben der nächste Befehl des Benutzerprogramms,
nämlich das hier gesicherte NPlus 1 dann quasi ausgeführt werden
Gut, das ist also erstmal so grob das,
was also jetzt bei so einem Interrakt,
beziehungsweise auch generell bei Kontextwechseln von Programmen basiert.
So, jetzt kann man sich fragen, was passiert,
wenn diese Interrapsis irgendwie geschachtelt auftreten,
also sprich während der Interrap-Verarbeitung kommt irgendwie ein weiterer Interrap.
Auch da habe ich theoretisch zwei Möglichkeiten. Zum einen,
ich kann sagen, Interraps werden abgeschaltet. Dann kann während der Interrap-Verarbeitung oder während dieser Interrap-Center läuft,
also nichts anderes dazwischen funken, hat natürlich den Nachteil,
dass Andere Interraps gegebenenfalls verloren geben können oder dass man sich da dann eben noch irgendwelche Mechanismen ausdenken muss,
um die dann eben auch noch irgendwo gegebenenfalls zwischenzuspeichern.
Das, was man meistens hat, sind unterschiedliche Prioritäten bei den Enterraps.
Weil es gibt halt Sachen, die haben eben eine relativ geringe Priorität,
war die beispielsweise jetzt also mit irgendwelchen Aktionen vom Benutzerprogramm zu tun haben.
Es gibt Interraps, die haben eine sehr hohe Priorität,
weil die mit dem, jetzt mal mit der Überlebensfähigkeit des Systems und mit dem Betriebssystem zu tun haben.
Also sprich, wenn die Hardware irgendwie per Interrapt meldet,
das Netzteil sagt Spannungsversorgung, geht gerade runter,
dann hat das natürlich eine andere Priorität, als wenn jetzt ein Interrap sagt,
der Benutzer hat irgendeine Taste auf der Tastatur gedrückt.
Die Kodierung von diesen Interrap-Prioritäten hatten wir übrigens,
als es in dem Thema Schallnetze, um solche Sachen ging,
kennengelernt, nannte sich Priority and Coda,
dass man unterschiedliche Prioritäten hat und eine hohe Priorität, alle niedrigeren quasi wegmaskiert.
Das ist also eine Hardwareeinheit, im Prinzip ein Schalennetz,
was, also genau so war es, dann also letztendlich macht. Gut,
ansonsten kann man jetzt, wenn mehrere Interraps auftreten,
sagen, ich kann die zum einen ineinander schachteln,
das heißt im Programm tauchten Interrapbau, der wird abgearbeitet,
währenddessen ab Erweiterung kommt der nächste Interrap,
dann kann ich natürlich genauso Diese Zustände hier auch irgendwie auf diesen Control-Stack sichern und das Ganze dann letztendlich wie so einen rekursiven Aufruf behandeln.
Man kann aber eben auch sagen, die Interraps werden sequenziell
abgearbeitet und irgendwelche Informationen zu dem Interraps müssen dann eben entsprechend zwischengespeichert werden.
Gut, hier also auch nochmal so ein Beispiel,
wenn man sich beides letztendlich vorstellen kann.
Also ich habe hier irgendwie mal Benutzerprogramm
Sage jetzt also irgendwie dem Printer soll was machen,
so was wie so ein Druckjob hat in der Regel eine relativ geringe Priorität.
Nicht jetzt kommt also meinetwegen von AIFA Net-Schnittstelle irgendwie noch ein Enterrab,
der wird dann Assi hier im Zweifelsfall dazwischen reingrätschen,
der soll dann aber auch komplett abgearbeitet werden und irgendein Interrab von der Festplatte
wird dann eben entsprechend zwischen gespeichert und nachdem dessen Ende hier abgearbeitet,
er hat aber immer noch eine höhere Priorität als die Printer
Gut, das waren im Schnelldurchgang.
Interrazz kommen wir jetzt also zu den Prozessen bzw. Prozessbegriffen.
Also Prozess kann ich mir erst mal vorstellen,
hatte ich ja schon gesagt, also eigentlich laufendes Programm.
Grob gesagt ist das immer dezentrale Einheit, die also jetzt im Betriebssystem verwaltet wird.
Je nachdem, wo man in der Literatur guckt,
findet man also viele unterschiedliche Definitionen, was Prozesse sind.
Also umgangssportlich kann ich mal sagen, Programm während der Ausführung,
eine Instanz eines laufenden Programms, Einheit, die dem Prozessor zugewiesen wird,
beziehungsweise die Formprozessor ausgeführt wird oder eben eine Aktivität,
bestehen aus einem einzelnen sequenziellen Ablauf, einem Zustand und zugehörigen Systemressourcen.
Also hier ist schon so ein bisschen mehr an Informationen mit drin,
wo da nämlich also sowas wie irgendwelche Zuständende und Zugehörigkeiten von irgendwelchen Ressourcen zu Programmen mit drin sind.
Ansonsten kann man sich das eben immer vorstellen, dass man sagen kann,
es gibt im Betriebssystem bzw. Betriebssystem kamen dann eben irgendwelche Datenstrukturen,
wo ich letztendlich Prozesslisten habe, wo dann eben beispielsweise drinsteht,
also der eine Prozess liegt an der Stelle im Speicher,
der andere Prozess liegt also an der Stelle im Speicher.
Und der Prozess selber ist dann eben immer dadurch gekennzeichnet,
dass ich natürlich sagen kann, ich habe jetzt also hier irgendwie den,
irgendeinen Bezeichner, also sprich diesen Index aus dieser Liste.
Ich habe dann also hier quasi meine Register und den Programmzähler und man hat dann eben häufig noch,
hier ist es jetzt relativ einfach geregelt,
irgendwelche Informationen in Bezug auf die Art und Weise,
wie jetzt also beispielsweise die Speicherzuordnung geregelt ist.
Hier ist das jetzt so, dass man sagen kann,
okay, der Prozess ist jetzt ein zusammenhängender Speicherblock,
wo ich also quasi so ein bisschen Informationen zu dem Prozess habe,
wo ich die eigentlichen Daten aus meinem Prozess habe,
also sprich alles,
was ich an Datenstrukturen in meinem Programm hier angelegt habe und den eigentlichen Programmcode.
Das liegt hier alles jetzt irgendwie als zusammenhängender Block im Speicher.
Und um jetzt quasi dafür zu sorgen, dass Prozess B,
nicht auf Prozess A drauf zugreifen kann,
gibt es dann eben quasi letztendlich in dieser Kontextinformation mit drin,
so was wie eine Basisadresse.
Das heißt, da beginnt der Adressraum von dem Prozess
und so und so groß ist er. Das heißt,
da gibt es dann eben irgendein Limit und alle Adressen,
die kleiner sind als Basisadresse oder größer als Basisadresse plus Limit,
sind dann halt für diesen Prozess nicht zugreifbar.
Das ist erstmal so die allereinfachste Variante,
wie im Prinzip dann so ein Speicherschutz realisiert wird,
rein praktisch sieht das bei aktuellen Betriebssystemen noch deutlich anders aus.
Auch das werden wir dann Nächste Woche noch kurz kennenlernen,
wo es dann also im Prinzip um virtuellen Speicher geht,
weil so eine Zuordnung von Prozessen zu speichern wäre jetzt also vergleichsweise ineffizient.
Gut, was kann bei der Abarbeitung von Prozessen alles schiefgehen?
Hier sind so ein paar typische Fehler eigentlich irgendwie aufgelistet.
Also ich habe einen Prozess, der will jetzt meinetwegen auf
die Festplatte schreiben, muss jetzt warten.
Also das, was sie eben beim Interrap beschrieben habe. Das heißt,
er wird dann eben durch diesen Enterrapt, beziehungsweise dadurch,
dass dann also letztendlich der Enterrap-Servicehändler, also dieses Programm,
der System-Call, den ich da so quasi gestartet habe,
dann sagt, okay, es ist entsprechend fertig,
dann eben weiterarbeiten.
So, was passiert jetzt, wenn dieses Ereignis gar nicht
ausgelöst wird oder wenn es mehrfacher ausgelöst wird?
Also das können Probleme sein. Dann habe ich letztendlich immer Probleme,
wenn ich jetzt mehrere Prozesse oder mehrere Freds habe,
die miteinander kommunizieren über Shared Memory beispielsweise
Weil da kriegt man im Prinzip Effekte, wo sich Programme gegenseitig Werte überschreiben.
Und das ist dann eben letztendlich abhängig davon,
wie das Betriebssystem diese Prozesse im zeitlichen Ablauf laufen lässt.
Weil, was kann jetzt passieren, bei Kommunikation über
Shared Memory, also ich habe hier einen Prozess P.
Und hier habe ich jetzt beispielsweise als Anweisung jetzt in meinem Programmcode,
if e, kleiner 5, Und dann soll jetzt hier irgendwie eine Zuweisung sein,
wo ich jetzt meinetwegen, I ist gleich I plus 1. Rechne.
So, und jetzt habe ich hier irgendwie einen Prozess.
Kuh. Und irgendwo in der Abarbeitung dieses Prozesses Kuh habe ich eine Zuweisung. I ist Live 5. So,
wie logischerweise natürlich ersichtlich ist, wenn diese Prozesse,
die jetzt also quasi über diese gemeinsame Variable I kommunizieren,
in einer Reihenfolge ausgeführt werden,
dass also erst dieser Prozess quasi hier läuft,
die Abfrage läuft, es wird festgestellt, IS Klarna 5,
der Prozess würde jetzt quasi an dieser Stelle mit diesem Befehl weiterarbeiten.
So und jetzt ist beispielsweise die Zeitscheibe von dem Prozess abgelaufen.
Dann sagt der Schedular, okay, es wird unterbrochen,
alles wird gesichert, Prozess, Kuh läuft weiter.
So Prozess, Kuh macht jetzt eine Zuweisung,
IS gleich
Irgendwann kommt der zu seinem Ende und dann läuft dieser Prozess an dieser Stelle weiter. Und das,
was ich da natürlich habe, ist,
hier habe ich, aus welchem Grund auch immer mal,
quasi mir die Zusicherung geholt,
IS Kleiner 5. Jetzt komme ich also hier in den Fall,
dass ich also auf einmal I trotzdem inkrementiere und da mit dem Wert I gleich 6 dann irgendwie weiterrechne.
So, das ist im Prinzip also das,
was an Problemen jetzt beim Multi-Prozessing passieren kann,
wenn jetzt quasi die Systeme entsprechend sich gegenseitig
da überschreiben können
Und da kann man jetzt also beliebig viele Fälle konstruieren.
Also bei dem Symagical Multi-Processing-Beispiel hatte ich also auch diese Sachen,
wo jetzt also vier Prozesse quasi auf einen gemeinsamen Speicherbereich, was gelesen, geschrieben haben.
Und je nachdem, in welcher Reihen folge ich das ausführe,
kann da eben oder können dadurch dann eben sehr unterschiedliche Ergebnisse rauskommen.
Nicht. Das heißt, das ist ein Problem,
was dann man da natürlich macht oder typischerweise macht,
ist, dass man sagt, okay,
ich habe in meinen Prozessen sogenannte kritische Sektionen, kritische Abschnitte,
die ich durch irgendwelche programmiertechnischen Mechanismen quasi schütze,
wo ich jetzt eben sage,
diese beiden Operationen dürfen nicht voneinander getrennt werden.
Das heißt, die müssen adomar stattfinden. Das heißt,
das Betriebssystem darf von hier nach hier letztendlich das nicht unterbrechen,
beziehungsweise wenn es das unterbricht, was es also im Zweifelsfall natürlich darf,
darf dieser Prozess diese Anweisung nicht ausführen.
Und das, was man da dann machen muss,
ist mit quasi als Programmierer selber etwas einbauen,
was dann eben so ein Synchronisationsmechanismus darstellt.
Gibt es unterschiedliche Mechanismen, Seemafuhre, Mutexe, Monitore,
werde ich von der Grundidee auch noch kurz vorstellen,
wo man dann eben letztendlich diesen gleichzeitigen Zugriff in solchen Critical Sections vermeiden kann.
Und das kann eben sein, sowas wie Speicher,
das war jetzt also dieses Beispiel,
das kann aber auch eben irgendein Dateizugriff sein oder was auch immer.
Also lassen sich
mehrere Sachen sein
So, wenn ich sowas eingebaut habe,
kann ich zwar gelegen, im Zweifelsfall dafür sorgen,
dass sich die Prozesse da jetzt nicht gegenseitig ins Geheh gekommen,
was man dann aber wieder schön machen kann, ist,
dass man sogenannte Deadlocks produziert,
sprich die Prozesse haben jetzt über eine Simmer vor,
also irgendwie einen exklusiven Zugriff auf eine Ressource und brauchen jetzt einen Zugriff auf irgendeine andere Ressource und warten darauf.
Jetzt gibt es einen zweiten Prozess,
der aber den entsprechenden Log auf diese Ressource hat und dann kann man eben relativ schnell irgendwelche Mechanismen aufbauen,
wo dann eben die Prozesse zyklisch aufeinander warten und keiner weiterrechnen kann. Also auch dazu wird dann also im nächsten Kapitel da noch ein bisschen was folgen. Gut,
ansonsten, wie gesagt, boah, es besteht ein Prozess,
einmal natürlich aus dem ausführbaren Programm,
aus den zugehörigen Daten und dann eben dem,
was ich jetzt mal hier so als Programmkontext beschreibe,
also sprich irgendwelche spezifischen Daten des Betriebssystems zur Verwaltung des Prozesses,
dann die Inhalte der Prozessorregister,
wobei da dann natürlich eben nicht nur die eigentlichen Register,
sondern wir haben ja auch kennengelernt,
wenn ich sowas wie Parallelisierung in der CPU mache,
dass ich dann eben beispielsweise ein Registery-Naming mache,
um eben entsprechend bei Superskalan rechnen, also alle Recheneinheiten auszunutzen,
dass man da dann eben auch diese René-Register mit drin hat,
mich dann Als Information wartet der Prozess auf irgendwelche Ereignisse,
was sind die Rechte des Prozesses,
wie sind also bestimmt vielleicht irgendwelche Prioritäten gesetzt und,
und,
und.
Also da gibt es also relativ viel an Informationen.
Das Ganze wird dann eben typischerweise etwas zusammengefasst, was sie dann Prozesskontrollblocken nennt,
wo dann im Prinzip diese ganze Information letztendlich mit drinsteht.
So, wenn ein Prozess jetzt quasi abläuft,
kann man dann auch immer noch betrachten, etwas,
was dann Trace genannt wird,
also Trace ist dann immer die Sorge der Instruktion,
die im Prinzip bei der Abarbeitung eines Prozesses anfällt,
für einen einzelnen Prozess, sehe ich damit im Prinzip das Laufzeitverhalten.
Das heißt, da könnte ich dann eben nachvollziehen,
bin ich gesprungen, bin ich nicht gesprungen?
Sprich, welche Befehle sind der Reihe nach Hausgeführt worden? Wenn ich das jetzt für den gesamten Prozessor mache,
dann sehe ich eben natürlich an der Stelle dann eben auch,
wie entsprechend der Prozess oder Prozesse dann also zwischen mehreren Prozessen,
A, wie und C beispielsweise wechselt und zwischenzeitlich dann eben diese Komponente,
die die Prozessumschaltung macht, Also der Scheduler oder die Spatche,
wie auch immer ich das jetzt nennen mag,
dann eben aktiv wird.
Also ist jetzt also hier zu sehen,
ich habe hier einmal die Treyses jetzt von irgendwie den Reiheprozessen,
A, B und C, die jetzt also hier irgendwie an bestimmten Speicheradressen,
das ist dieses hier dann dementsprechend starten.
Und der gesamte Trey ist jetzt quasi von dem Prozess oder
Ablauf im Prozessor wäre dann eben dieses hier,
wo man sieht, ich fange eben mit dem Prozess an.
Nicht an dieser Stelle kommen dann beispielsweise jetzt ein Timeout.
Dann wird also quasi hier der Dispatcher aufgerufen. Das ist
eben das, was jetzt hier so blau hinterlegt ist.
Nicht, dann startet der zweite Prozess. Der hat jetzt
an dieser Stelle beispielsweise eine IO-Request, muss es wieder irgendwie warten.
Dispatcher schaltet sie jetzt wieder um auf den Prozess C.
Dann kommt irgendwie ein Timeout, der Dispatcher sagt jetzt,
okay, jetzt ist A wieder dran,
der darf weiterlaufen und so weiter und so fort
Gut, wodurch werden jetzt Prozesse gestartet?
Wodurch werden sie beendet? Also starten kann sein,
dass ich als Benutzer letztendlich einen neuen Bettstrop starte.
Starten kann sein, dass ich mich jetzt interaktiv an den Systemen anmelde.
Also sprich jetzt also über so eine Kommandozeile, beziehungsweise übers Einloggen, mein System starte.
Ansonsten gibt es natürlich jetzt noch vom Betriebssystem diverse Dienste,
die dann also dafür sorgen, dass Prozesse letztendlich gestartet werden.
Und durch laufende Prozesse, also sprich in diesem Fall in Form von expliziter Parallelität, werden dann eben auch immer Prozesse gestartet. Durchlaufende Prozesse wäre jetzt eben zum Beispiel,
wenn ich jetzt also irgendwie so ein Betriebssystem nehme,
grafische Oberfläche, mich dort einlogge,
also beispielsweise ist das irgendwie ein Windows habe,
mich da jetzt also irgendwie als Meter anmelde, nicht,
dann geht also für mich hier irgendwie Bildschirm auf,
ich habe dann also irgendwie die Grafik,
ich sehe jetzt also hier irgendwie mein Explorer,
um jetzt also irgendwie im Dateisesystem zu machen und kann dann eben entsprechend,
also mit der Maus jetzt irgendwie über Startmenü oder über irgendwelche Verknüpfungen Prozesse starten.
Und das wäre dann eben etwas,
das ich direkt nach dem Einloggen quasi einen ersten laufenden Prozess habe,
der mir jetzt quasi die grafische Oberfläche erzeugt und irgendwie Maus und Tastatur-Events irgendwie erst mal nur weiterleitet.
Und wenn ich damit jetzt also irgendwie irgendeinen alten anklicke,
aus dem Startmonie irgendwas auswähle,
dann startet dieser Prozess dann eben das entsprechende Programm,
was dann eben letztendlich in dem Fall dann also darunter fallen würde.
Gut, das Ganze ist dann mit den Begriffen,
Parrent und Child-Prozess dann eben quasi hierarchisch organisiert. Das heißt,
ich habe letztendlich sowas wie so eine mehr oder minder große Baumstruktur.
Kann man sich unter Windows im Prinzip, ich glaube,
auch mit dem Process Explorer mit anzeigen lassen.
Unter Linux gibt es dann also auch unterschiedliche Sachen,
also hier nun mal als Einfassstes, weil das jetzt also ohne Grafik auskommt.
Hardhop, also hier, das wäre jetzt zum Beispiel das,
was jetzt also hier gerade auf dem Desktop läuft und hier
rechts sind jetzt also letztendlich die Prozesse als Baum,
die hier jetzt irgendwie gerade in dem System laufen.
In der Regel sind das jetzt hier erst,
wenn nur irgendwelche Benutzerprozesse und irgendwo hier an ab der Stelle,
sie sind jetzt also irgendwie in dem Fall beispielsweise irgendwelche Prozesse,
die ich mal gestartet habe,
die dann also irgendwie mir da gehören,
die in dem Fall jetzt also im Hintergrund von der grafischen Oberfläche gestartet werden.
Gut, das heißt also da sieht man dann eigentlich
immer so typischerweise die Prozesse dann also baumartig organisiert.
So, wodurch können Prozesse beendet werden?
Also hier eine ganze lange Liste von möglichen Sachen, das,
was er natürlich erst mal haben möchte, ist ein normales Programmende.
Programm ist letztendlich mit der Aufgabe fertig. Ansonsten kann es
sein, dass das Betriebssystem sowas wie Zeitlimits hat.
Das heißt, eine maximale Laufzeit oder irgendwie ein maximal langes
Warten auf irgendeine Ereignisse, eine Benutzereingabe.
Nicht, und wenn da jetzt also irgendwie nach so und
so viel Zeit dann also immer noch nichts gekommen ist,
dass das Betriebssystem dann also quasi eingreifendem Prozess beendet
Nicht dann im Prinzip sowas wie Timeouts,
wenn ich also jetzt irgendwie auf Ereignisse warte,
wenn ich Speicher anfordere und in dem System keinen Speicher mehr zur Verfügung steht.
Auch dann würde der Prozess sofort beendet werden.
Nicht dann solche Sachen wie Adressverletzung, also sprich ich versuche
jetzt also auf irgendeine Speicheradresse in meinem Programmlauf zuzugreifen,
die mir nicht gehört.
Das Gleiche gilt dann eben auch bei Zugriffen auf irgendwelche Ressourcen,
auf die ich entweder keinen Zugriff habe oder eben irgendwie sowas wie einen ungültigen Zugriff.
Also sprich, ich habe eine Datei,
read only
Geöffnet, möchte da was reinschreiben. Würde dann eben auch nicht funktionieren. Ein Ausgabefehler,
arathmetische Fehler, falsche Typen in Datenstrukturen,
können sowas auslösen, dann generell ungültige Befehle,
sprich Program-Counter sagt, lies von dir und der Speicheradresse,
da ist jetzt irgendwie Nährcode drin,
denen das System aber eigentlich gar nicht irgendwie jetzt als Assembler-Befehl kennt,
beziehungsweise den gibt es gar nicht.
Auch das wurde dann eben entsprechend sofort den Prozess beenden.
Wäre in dem Fall dann also typischerweise ein Indiz dafür,
dass ich also jetzt auf einmal mit einem Programm-Counter nicht mehr in die Instruktion,
sondern irgendwelche Daten reinzeige und dort also irgendwas stehen habe,
was also keiner Instruktion entspricht.
Dann generell natürlich erstmal unerlaubte Befehle. Das heißt, ich bin im User-Mod,
möchte aber jetzt irgendwie privilegierten Befehl ausführen. Nicht dann,
wenn ich jetzt eine Hierarchie habe, der Parent kann dem Charles sagen,
Prozessende oder wenn der Parent selber jetzt also letztendlich irgendwie terminiert wird,
dann wird also auch quasi da alle,
jeder andere Prozesse davon abhängt, dann also auch runtergerissen.
Auch das wäre dann also ein klassisches Beispiel,
was dann in dem Fall ist oder eben Abbruch durch Betriebssystem,
Operate oder den Benutzer selber.
Parent terminiert mal sehen, ob ich das sehr schnell hinkriege.
Also ich habe hier meine Schelle,
da machen wir mal ein starten also hier dieses
wunderbare Programm XIs
So, und wenn ich jetzt diese Shell hier einmal bösartig beende,
ja, dann wird also auch das XIs entsprechend mit runtergerissen.
So, ja, also wie gesagt, das, zack,
so, nur mal so ein Beispiel, was da alles passiert.
Ja, bei den Prozessen selber hier mal wieder ein allgemein
beliebtes Beispiel für Automatendarstellung. Was passiert ist mit den Prozessen,
die werden ja irgendwie dynamisch gestartet und beendet,
jetzt kann es sein, dass die Prozesse waren,
die jetzt also beispielsweise einen System-Call rausschieben auf irgendwelche Ereignisse warten
Oder dass sie eben unterbrochen werden, weil ich also im Time-Sharing-Betrieb
bin und quasi die Zeitscheibe für den Prozess abgelaufen ist.
Da werden die ja dann im Prinzip durch dieses Programm,
was jetzt eben sagt, welcher Prozess jetzt gerade die CPU zugeteilt bekommt, verwaltet.
Und das Ganze kann man dann eben darstellen,
eigentlich auch immer irgendwie durch so ein Automatenmodell oder Prozesszustand,
wie ich das dann also nennen mag, wie auch immer.
Nicht, dass man sagt, okay,
ein Prozess kann quasi neu gestartet werden,
wird also quasi erstmal vom System aus freigegeben,
landet dann quasi in einer Warteschlange von Prozessen,
die auf die CPU dürfen
Nicht, die wären dann ready. Nicht,
dann kann es sein, dass der Dispatcher sagt,
okay, jetzt darfst du rechnen, dann wäre er Running.
So, dann kann es sein, dass der Prozess beendet wird,
dann würde er hier quasi rausfallen. Oder dass ein Timeout kommt,
dann wird er unterbrochen und ein anderer Prozess darf weiterarbeiten. Oder er wartet auf irgendwelche IO,
würde dann quasi hier als blockiert eingestuft werden und darf jetzt also vielleicht nicht weiterarbeiten,
wenn das jetzt ein Blockierendes Warten ist,
wenn das jetzt also quasi über so ein System-Call ist,
wie das also vorhin ein Beispiel war,
dann würde er dann letztendlich über ready dann wieder weiterarbeiten können.
Und an der Stelle wird dann im Zweifelsfall dann nochmal
der entsprechende Disc-Prozess, war das da dann also gestartet.
So, je nachdem, wie fein granulär man das macht,
müssen das jetzt also nicht zwingend fünf Zustände sein,
sondern gibt es dann auch Modelle mit deutlich mehr Zuständen.
Nicht aber das zeigt erstmal so grob, die Idee,
was eigentlich dahinter steht, was das jetzt gemalt ist mit solchen Prozessen oder Prozessmodellen. So,
und wenn ich das Ganze dann zeitlich ablaufen lasse,
nicht also hier nochmal wieder so ein Trace-Prozess A, Ist dann,
also sie wird dann eher aus irgendwelchen Gründen hier unterbrochen,
nicht dann läuft der Dispatcher, dann nächster Prozess,
der wartet jetzt auf IO,
würde dann quasi hier unterbrochen werden, Dispatcher,
sucht jetzt wieder den nächsten Prozess raus und der Reihe nach habe ich dann,
also in diesem Fall hatten wir hier ein Ein-Prozessor-System,
dann so ein Ablauf von mehreren Prozessen.
Gut, was damit dann einhergeht,
ist dann eben letztendlich so eine Warteschlange oder im Klaus Ameere Warteschlangen,
wo ich dann eben sagen kann, Prozess kommt neu rein.
Ich habe hier jetzt also irgendwie erstmal so eine Q,
wo ich die ganzen Prozesse verwalte
Abhängig davon, wie das Scheduling aussieht,
würde das Bachelor dann eben entweder den ersten oder eben irgendeinen anderen Prozess aus der Q nehmen,
dass es dann eben letztendlich jetzt wieder von einem Algorithmus abhängig,
habe ich hier unterschiedliche Prioritäten,
beziehungsweise nach welchen Kriterien suche ich jetzt hier Prozesse raus.
Nicht, wenn ich jetzt hier nur so eine,
ganz einfach, so eine Q hätte,
dann wäre das also First Come, First, Surf.
Nicht, das heißt, der erste Prozess,
der hier reinkommt, wird dann eben auch als Erster bedient.
Und wenn du jetzt hier nicht gerade mit einem Timeout oder mit irgendeinem Warten auf ein externes Ereignis rausfällt,
wird dann eben hier bis zum Ende auf einen Prozess durchrechnen
und dann würde dann eben wenn der fertig ist,
dann eben der Nächste hier rausgenommen werden.
Gut, und für dieses Blockieren, das heißt,
wenn die Prozesse jetzt also aufblockierend auf irgendwas Externes warten,
gibt es dann eben auch wieder eine eigene Warteschlange.
Und wenn eben dann so ein Ereignis eingetreten ist,
würden die dann eben wieder in diese Ready Q wandern.
Gut, das kann man jetzt also noch beliebig für komplizieren.
Also zum Beispiel jetzt also bei diesen Ereignissen dafür dann,
also für jedes Ereignis, noch eine eigene Q anlegen,
beziehungsweise in dem späteren Kapitel,
wo es sonst um Scheduling geht,
dann tauchen im Prinzip auch wieder
so ähnliche Sachen auf
Gut, was er dann auch immer noch hat.
Also hier ist da nochmal eine so eine Erweiterung von diesem Modell jetzt mit den fünf Zuständen,
also wo jetzt also hier noch ein Sechser hinzukommt,
ist jetzt eben, wenn ich diesen Effekt des Walkings habe,
das heißt also von dem Prozess werden Teile auf den sekundären Speicher,
also sprich Hartes, Goda Solid Statis, ausgelagert.
Dann wird eben der Prozess typischerweise auch Unterbrochen,
das heißt also, der ist dann eben nicht nur blockiert,
sondern läuft dann eben noch in so einen Zustand, das Band.
Weil da geht es dann eben auch darum, dass man sagen kann,
okay, wann kann das auftauchen? Also zum einen,
wenn Teile des Prozesses jetzt also nicht mehr im Hauptspeicher sind,
er dann, also von daher sowieso erstmal nicht, weiterarbeiten kann,
solange nicht diese Information jetzt wieder in den Hauptspeicher eingelagert wurde.
Wenn ich bei periodischen Ausführungen sage, der Prozess,
also sprich dieses Beispiel, soll irgendwelche Daten von irgendeinem Sensor einsammeln,
ich einmal pro Sekunde nicht, dann sage ich, okay,
hol mir den Wert und in meinem Programm-Code schreibe ich dann eben Sleep,
was weiß ich,
wie lange und dahinter verbirgt sich dann eben im Prinzip ein Unterprogrammaufruf,
was dann ein Timer startet, den Prozess in den Sus-Band-Modus legt.
Im Hintergrund läuft der Timer und wenn der Timer abgelaufen ist,
gibt es dann interrabt und der Prozess würde dann eben wieder neu aktiviert werden können.
Gut, Parent-Anfrage an Child. Also wenn ich jetzt mehrere Sachen nebenläufig laufen habe und dazwischen eine Synchronisation machen will,
auch damit kann ich sowas,
also Prozesse quasi in so einem Suspens-Zustand versetzen oder eben durch Befehle sagen,
das Betriebssystems, beispielsweise jetzt hier, also irgendwie,
jetzt will ich jetzt nicht nochmal wieder zurückschalten,
aber irgendwas zeigen, also im Prinzip Job-Control in der Shell,
beim Unix kann ich das also machen,
indem ich da so Prozesse in den Hintergrund schiebe,
beziehungsweise zwischenzeitlich anhalte,
irgendwas anderes in der Shell machen und im Prozess wieder in den Vordergrund habe.
Also solche Sachen würden da im Prinzip
dann also auch sind
Anhalten und Suspend letztendlich bewirken und den Prozess dann eben gegebenenfalls wieder in den Vordergrund tun.
So wie wir an die Prozesse verwaltet. Zum einen
habe ich da jetzt seitens des Betriebssystems einiges an Kontrollstrukturen,
nämlich einmal also diese Prozesstabelle,
mit denen ich dann im Prinzip auf alle Prozesse,
die in dem System jetzt gerade laufen bzw. aktiv sein sollen, verweisen kann.
Und dann gibt es eben noch einen ganzen Satz an auch ähnlichen Kontrollstrukturen,
wo ich dann eben die Speicherzuordnung,
die Zuverordnung von AR-Ausgabegeräten oder von Dateien, entsprechend mitverwalten kann,
wo ich dann eben beispielsweise jetzt für einen Speicher sagen kann,
wie sieht das jetzt mit dem sogenannten virtuellen Speicher aus?
Während wir auch nächste Woche oder noch kurz kennenlernen,
wie sieht das mit Attributen für den Speicher aus?
Das heißt, gibt es Sachen im Speicher, auf die
der Prozess dann eben auch eine Read-Only darauf zugreifen darf?
Das sind natürlich jetzt logischerweise Seine Programmstrukturen, das können aber
auch Teile der Daten sein. Das können auch Sachen sein,
wenn ich jetzt also im Prinzip mehrere Prozesse sich speicher oder Speicherbereiche teilen.
Da könnte man sowas dann eben auch entsprechend mit implementieren, also Logs funktionieren im Prinzip dann also auch über solche Eigenschaften. So,
für die Ein- und Ausgabegeräte gibt es dann eben auch entsprechend Tabellen,
wo verwaltet wird, welches Gerät jetzt, welchen Prozess zugeordnet ist,
wie der Status von irgendwelchen IO-Befehlen ist, also sprich,
wie viele Rides habe ich da schon in der Warteschlange nicht und insgesamt habe ich jetzt,
also wenn da jetzt also mehrere Prozesse,
die jetzt parallel arbeiten und alle irgendwie in der Datei schreiben wollen,
die dann natürlich dann auch noch irgendwo in irgendwelchen größeren Warteschlangen,
wo dann eben sowas mit drin ist.
Und dann eben für die Dateiverwaltung selber entsprechende Datenstrukturen, wo drin steht,
welche Dateien, wo sind die auf der Platte letztendlich abgelegt,
wie sind die benamst, wie ist deren Status,
also sprich sind die geöffnet von irgendeinem Prozess Mit welchen Attributen?
Reed fright, lesen, schreiben oder read only oder was
immer man da also letztendlich jetzt seitens des Vertriebssystems bzw. von Bibliotheken da vorsehen kann.
Und Zugriffsrechte, Zeit, Stempel und so weiter. Gut,
der Prozess selber, also sprich das, was hier dieser blaue Kasten ist,
ist dann eben gekennzeichnet eigentlich durch folgende Sachen,
also zum einen natürlich den Programmcode, die Datenstrukturen,
die der Prozess drin hat, also sprich alles,
was ich an dann in meinem Programm selber drin habe,
statisch oder aber eben auch dynamisch, also sprich mit Speicheranforderungen,
also mit Marlock beispielsweise unter C angefordert.
Das würde dann eben entsprechend dazu gehören.
Dann der Stack natürlich von dem laufenden Prozess,
wo dann entsprechende Aufrufhierarchie die Informationen hinterlegt sind.
Und dann gibt es eben das,
was jetzt an Verwaltungsinformationen vom Betriebssystem hinzukommt,
eben dieser Prozesskontrollblock
Irgendwie Identifier, wer Esparent gibt es, also irgendwelche Chiles,
dann eben die Inhalte aller Register, dann Statusinformationen bzw. Statusregister,
also dazu gehören dann eben Programmzähler, das Flag-Register,
irgendwelche Register, wo dann also im Prinzip dieser Prozessmodus drinsteht,
dann sind Interrapts eingeschaltet oder nicht eingeschaltet,
sofern man die als Benutzer jetzt überhaupt abschalten darf.
Dann eben der Stackpointer, Informationen jetzt für das Scheduling-Programm,
wie sieht das also mit irgendwelchen Prioritäten der Prozesse aus und so weiter und so fort.
Also da gibt es so einen ganzen Satz von unterschiedlichen Informationen,
die dann also letztendlich damit reingehören. So,
und das wird quasi jetzt hier als Prozesskontrollblock für jeden Prozess,
der läuft irgendwo vorgehalten. Das heißt, das ist das,
was seitens des Betriebssystems erzeugt wird. Das ist das,
was seitens des Programms erzeugt wurde,
nämlich also einmal der Stack und dann eben Adressen und Programmcode,
vom Programm selber und gegebenenfalls dann eben auch noch irgendwelche Speicherbereiche,
die jetzt von mehreren Prozessen gemeinsam genutzt werden können.
Gut, mit der Unterteilung jetzt hinsichtlich dieses Prozessmodells kann man jetzt eben sagen, okay,
jeder Prozess besitzt dann eben so ein Prozesskontrollblock und diese ganzen unterschiedlichen Cues jetzt hinsichtlich dessen,
wo bin ich diesen Prozesszuständen, also sprich, was ist Running?
Beim einen Prozessor-System ist das dann logischerweise natürlich nur ein einzelner Prozess.
Welche Prozesse sind ready und warten darauf,
dass der hier mal die CPU freigibt und welche sind eben blockiert,
weil sie beispielsweise jetzt auf irgendwelche Events von außen warten.
Nicht all das wird dann eben durch solche Verkettungen von diesen beispielsweise Prozesskontrollblöcken implementiert. Gut,
Kontextwechsel ist dann eben dieser Mechanismus eigentlich analog zu dem,
was also beim Interrapt und dem Aufruf des Interrap-Zändlers passiert,
wo dann eben im Prinzip Prozess Dezesse von der CPU genommen werden und der Scheduling-Algorithmus dann eben sagt,
ein anderer Prozess soll laufen und der Dispatcher,
die dann eben entsprechend vorbereitet, dass man sagt, okay,
aufgerufen wird das Ganze dann eben entweder durch einen Interrab,
durch einen System-Call oder durch einen Trap, also sprich einen Interrab,
der ausgelöst wird durch die Programmabarbeitung selber,
also beispielsweise dieses berühmte Division durch Null oder Zugriff auf irgendeine ungültige Speicheradresse.
Und wenn jetzt also kein Interrab wartet,
dann wurde Entsprechend werden die Befehle weiter abgearbeitet.
Das war also diese Grafik, die im Prinzip bei dem Tal
vorher zu den Interraps schon da war, wo ich das gezeigt habe.
Ansonsten würde dann eben ein Kontextwechsel ausgelöst werden. Also sprich
, der Programm zur Elive wird mit dem Interrap-Thändler initialisiert.
Das System wechselt dann eben vom User-Mode in den Colonel-Mode.
Und dann wurde dann dementsprechend der Interrap abgearbeitet werden.
Beim Kontextwechsel wird eben alles aus dem Prozess gesichert.
Dieser Prozess-Kontrollblock aktualisiert
In die passende Warteschlange ready oder blockt oder wie viele es
da dann auch geben mag, entsprechend mit eingeordnet.
Und es wurde dann eben ein anderer Prozess von dem Dispatcher,
bzw. von dem Scadular zur Ausführung, gewählt werden,
dessen Kontrollblock wird dann eben passend aktualisiert.
Alles, was dort also zwischengespeichert wurde,
wird dann entsprechend in das System zurückgespielt, sprich die ganzen Prozessoregister,
aber eben auch in Bezug auf die Speicherverwaltung, alles,
was da mit drin ist,
wird quasi jetzt wieder aufgesetzt.
Dann wird dann eben der andere Prozess laufen
So, wie kann man diesen Kontextwechsel jetzt praktisch realisieren?
Da gibt es also auch mehrere Varianten. Zum einen,
kann ich jetzt also bei molithischen Körnern,
das sind also diese beiden Varianten, sagen,
ich habe das jetzt komplett in dem Betriebssystem-Körnel.
Ich kann aber diese Funktionalität,
dass der Prozess quasi jetzt abgebrochen wird und einen Kontextwechsel vorbereitet wird,
eben auch in den Adressraum des Prozesses selber mit reintun,
wobei dann natürlich der Prozess hier im User-Mode und
hier im Colonel-Mode
dann läuft
Das heißt, das wäre dann im Prinzip auch möglich.
Würde dann aber eben auch heißen,
dass Teile des Speicherbereichs vom Körner, das ist das,
was hier also mit diesem weißen Teil dann angedeutet ist,
dann eben auch zu dem Kontextinformation des Prozesses dann eben auch noch mit hinzugehören,
weil die dann natürlich dann also hier dann auch entsprechend ausgeführt werden müssen.
So bei den Mikrokörnern wäre das dann eben auch,
dass an der Stelle dann eben nur ein relativ einfacher Kontext
Switch passiert und alles andere dann eben hier von irgendeinem Service
des Betriebssystems dann abgearbeitet wird
Gut, dann noch zu dem Begriff Thread, was ist damit gemeint?
Also, wir hatten bislang kennengelernt, ein Prozess ist für
das Betriebssystem quasi der gesamte Kontrollblock. Das heißt,
welche Datenstrukturen, welche Ein- und Ausgaben und, und,
und, welche Zugriffsrechte, was Status in der Abarbeitung und, und.
Und so weiter. Das gesamte Speicherlayout, das gehört eigentlich
erst mal zum Prozess. Ein Freiheit ist jetzt,
beziehungsweise man hat da auch oft dann den Begriff Lightweight Process,
ist dann eigentlich innerhalb eines Prozesses der Teil,
wo jetzt also eigentlich nur der Code Durch den Prozess oder durch die CPU ausgeführt wird.
Das heißt, da geht es dann eigentlich nur um den Teil des Programmablaufs,
also sprich das, was also der Dispatcher dann macht.
Und als Begriff hört man dann ja auch immer oft,
beziehungsweise programmiert man vielleicht auch entsprechend dann etwas,
was sie dann Multi-Freading nennt,
dass man eben sagt,
ich habe mehrere Parallele Ausführungen in einem Prozess mit drin
Da muss ich jetzt immer sagen,
das Ganze ist jetzt wieder von der Programmiersprache im Betriebssystem abhängig.
Gibt es mal die Streading, ja oder nein?
Weil also in der Regel wird das natürlich durch Programmiersprachenkonstrukte überhaupt erstmal angestoßen.
Also in Java ist es inhärent mit drin,
in vielen anderen parallelen Programmiersprachen kann ich das also auch mitmachen.
Und dann kann man eben sagen,
ich habe innerhalb eines Prozesses jetzt eben nicht nur einen Ablauf von Code,
sondern mehrere, nicht daher dann eben die Multiple-Threads oder Multifredding.
So und je nachdem, was das Betriebssystem dann kann,
Sprich, wie viele Recheneinheiten habe ich,
kann ich dir dann ja auch wirklich parallel ablaufen lassen,
gegebenenfalls aber auch nicht,
dann ist das im Prinzip auch erstmal nichts anderes als mehrere Prozesse,
die dann also quasi auch sequenziell ablaufen,
beziehungsweise in diesem Fall dann eben mehrere Fräts,
nicht aber wenn die Hardware das unterstützt,
habe ich dadurch dann eben entsprechend also auch die Parallelität oder die Parallelareverbreitung.
Und dann gibt es eben noch die Sache,
dass man dann eben auch noch sagen kann,
mehrere Prozesse, also Multiple-Process,
teilweise auch mit Meer und Strets,
kann man dann
eben entsprechend machen
So, hier nochmal, wie das Ganze jetzt zu sehen ist im Prinzip für ein Srät,
habe ich also natürlich sowas wie einen eigenen Zustand.
Das entspricht dann quasi dem, was wir also vorher als Prozesszustand hatten.
Ich habe einen eigenen Kontext, also sprich Register, Programmzähler,
aus der CPU und ich habe einen eigenen Stack und gegebenenfalls auch einen eigenen Speicher für statische Datenstrukturen.
Ansonsten hart und frei natürlich Zugriff auf alle Datenstrukturen und Ressourcen des Prozesses, teilt die sich aber mit anderen Threats. Das heißt,
gerade beim die Fredding,
also hier habe ich das jetzt mit Prozessen gemacht,
wenn ich das jetzt also im Prinzip mit Freds machen würde,
weil da kann man eben sehr schnell und sehr einfach,
also auch Datenstrukturen gemeinsam nutzen, wird es also noch wichtiger zu sagen,
ich muss eben gegebenenfalls solche Log-Mechanismen selber einbauen und dafür sorgen,
dass ich in der zeitlichen Abarbeitung jetzt eben nicht irgendwie solche Race-Conditions,
um irgendwelche Kritical-Sections habe,
wo dann also die Daten sich gegenseitig überschreiben oder irgendwelche Sachen passieren,
die ich in meinem Code so eigentlich
gar nicht haben möchte
Gut, hier nochmal, die Tali,
die dann also quasi beim Multis-Frading-Tal dann letztendlich vervielfach werden.
Also wenn ich jetzt einen einzelnen Stret habe in meinem Prozess,
ich habe ihm den Pontrollprozesskontrollblock und alles, was also quasi dieses Speicher-Layout betrifft.
Und ich habe dann den Tal vom Stack beim Multi-Frading,
habe ich dann eben gegebenenfalls mehrere Fräts,
dafür dann eben auch nochmal eine Kontrolle,
die dann sowas wie einen Prozesszustand beschreibt.
Das heißt, Idle, Waiting, Running, also im Prinzip diese Information,
dann eben nochmal den eigenen Stack, beziehungsweise da die entsprechenden Datenstrukturen.
Ansonsten werden aber eben vom Prozess alle Daten,
was also hier dieser Azure Space ist, dann eben von allen Sreits gemeinsam genutzt.
Ja, was ist Vor- und Nachteil jetzt von Shreds?
Also zum einen sind sie jetzt für das Betriebssystem erstmal einfacher zu verwalten und zu erzeugen als komplette Prozesse,
beziehungsweise wenn ich jetzt sage, ich habe die Variante,
habe ich zwei Prozesse oder einen Prozess mit zwei Freds.
Das kann man also sich dann schon an dem hier ausdenken,
habe ich hier einfach weniger Informationen, weil ich also hier entsprechend weniger Overhead habe,
bei dem, was jetzt also wirklich im Single-Thread-Modell letztendlich passiert.
Zweits können dann eben auch deutlich schneller beendet werden,
der Kontextwechsel ist natürlich schneller und eben, wie gesagt,
dadurch, dass Freds eigentlich automatisch in dem Prozess alle komplett gegenseitigen Zugriff auf irgendwie globale Datenstrukturen bzw. die entsprechenden Datenstrukturen haben,
ist natürlich dann also eine Kommunikation auch deutlich einfacher,
als wenn ich das jetzt über mehrere Prozesse mache,
weil wenn ich das jetzt nicht, also über irgendwelche Bibliotheken,
beziehungsweise Programmiermechanismen, also dafür sorge,
dann ist natürlich für das Betriebssystem dieses I und dieses I natürlich nicht identischer Speicher,
sondern prozessspezifisch dann irgendwie erstmal was Eigenes.
Das heißt also, so eine Kommunikation zwischen Prozessen lässt sich
dann also natürlich auch nur über entsprechende Betriebssystemmechanismen,
beziehungsweise Programmiermechanismen viel mehr entsprechend dann realisieren
Ja, sowas mit Sreds wird also ganz gerne genommen,
wenn man jetzt also viel auf IO wartet,
also bei bestimmten Serverdiensten kann man das gerne machen,
wenn man relativ viel solche langen Wartezeiten,
also über Remote Procedure Calls hat, das heißt also irgendwelche Sachen,
wo ich jetzt also irgendeinen Aufruf von irgendeinem Server oder von irgendeinem Dienst auf einem anderen Rechner habe und daher meine Daten haben möchte,
also beispielsweise sowas wie Netzwerkdateisysteme funktionieren im Prinzip mit sowas,
sowas wie Browser-Tabs im Prinzip,
also inzwischen haben eigentlich auch sämtliche Browser, sind eigentlich so aufgebaut,
dass wenn ich jetzt also mehrere Tabs in meinem Internet-Explorer,
Firefox, Chromium oder was auch immer habe,
dass eigentlich jeder Tab dann quasi wie ein eigener Thread letztendlich läuft,
was eben auch deutlich effizienter ist von der Abarbeitung,
wenn ich jetzt also irgendwie in einem Tab,
also auf irgendwelche Daten warte,
die es vielleicht langsam aus dem Internet kommen,
dass also irgendwo anders schon Informationen aktualisiert werden können,
als wenn ich sage,
ich habe das in einem Programm,
wo ich dann also jetzt von Hand umschalten muss,
wann wird welcher Inhalt
von welchem Tab
letztendlich bearbeitet
Also das war auch einer der Gründe,
weswegen also die Browser jetzt so vor einigen Jahren,
also dann in diesen ganzen Bandchmarks dann immer deutlich effizienter mal geworden sind,
weil sie dann also im Prinzip so etwas schlauere Programmierung dann
eben genau sowas gemacht haben.
Wie gesagt, das kann man also immer ganz gerne machen,
wird dann eben dadurch deutlich effektiver. Man kann eben Parallelitäten ausnutzen,
gefährlich oder wo man dann eben wirklich aufpassen muss,
ist dadurch, dass alles schwer zum gleichen Adressraum sind mit
der Synchronisierung,
dass sie sich dann nicht gegenseitig irgendwie zerschießen
Gut, bei den Fraps wird dann noch unterschieden zwischen User-Level-Threads und Curnal-Level-Threads.
Da geht das im Prinzip darum, dass man sagen kann, wie werden diese Frats erzeugt?
So wie ich das jetzt bislang erst mal vorgestellt habe und sage,
ja, Thread,
das ist also irgendwie so eine Parallelität innerhalb des Prozesses,
der jetzt also vom Betriebssystem verwaltet wird,
dann habe ich eigentlich eher sowas wie ein Curnal-Level-Threads, das heißt,
das heißt, Und das Betriebssystem sieht wirklich mehrere Freds und verwalte die.
Und hat dann eben auch die Möglichkeit,
wenn beispielsweise ein Fred in einem Prozess,
jetzt also auf irgendwas wartet,
eben ein anderes Trett in diesem Prozess weiterarbeiten kann.
Sogenannte User-Level-Threads ist jetzt was anderes.
Da werden quasi die Freds
über Bibliotheken erzeugt
Und die sind dann also quasi außerhalb von dem, was das Betriebssystem sieht.
Das Betriebssystem sieht jetzt nur einen einzigen Prozess. Und über
die Bibliotheken wird da nämlich quasi ein eigenes Scheduling gemacht.
Vorteil ist, man hat dann an der Stelle eben Freitwechsel,
ohne dass man jetzt also auf Cornal-Privilegien mit einem Kontextwechsel umschalten muss.
Das läuft dann eben auch auf allen Betriebssystemen. Das ist auch ein Riesenvorteil. Nachteil ist,
da das Ganze für den Colonel, aber eben nur ein einziger Ablauf,
also nur ein einziger Prozess ist, Habe ich da jetzt,
also Colonel, seit ich jetzt eben keine Parallelität, das heißt,
wenn irgendwo ein System-Call auftaucht, der jetzt irgendwas blockiert,
in einem Fred, dann ist auch der gesamte Prozess,
das heißt,
auch alle anderen User-Level-Threads sind dann eben auch blockiert.
Das sieht man eben ganz gut hier an dieser Sache,
also User-Level-Threads, wo das Ganze dann hier über eine Bibliothek
erzeugt wird und eben diese Colonel-Level schwätzt.
Gut, dann lassen sich das auch noch beliebige Mischformen letztendlich erzeugen.
Gut, dann werde ich jetzt noch kurz im nächsten Teil anfangen.
Was passiert jetzt eben mit solchen Nebenläufigkeiten
Jetzt haben wir jetzt also mehrere Prozesse, die irgendwie Art laufen oder im Idealfall
dann also in den Prozessen auch noch mehreres räts. Nicht das heißt,
wir haben zum einen Nebenläufigkeit jetzt im Sinne von Multi-Programming,
wo ich jetzt eben erstmal sage,
ich habe nur einen Prozessor und mehrere Prozesse,
die da drauf laufen, die jetzt eben sich abwechseln,
weil einzelne Prozesse jetzt eben irgendwie auf langsames IO warten oder auf irgendwelche Events warten.
Oder ich habe eben das,
was wir inzwischen eigentlich typischerweise haben, also einen Multi-Prozessing,
das heißt also auch noch
mehrere Prozessoren
Und letztendlich, wenn ich sowas wie ein fataltes Rechnen,
also irgendwie so ein Plastersystem habe,
dann hätte ich eben auch da drin Nebenläufigkeit. So,
das führt eben dazu, dass man dann eben zum einen,
also irgendwie so ein abwechselndes Rechnen hat durch irgendwelche Kontextwechsel,
wo sich dann einzelne Abläufe überlappen, vielleicht auch abwechseln.
Und wo ich dann eben auch sagen kann,
letztendlich diese Abarbeitungsgeschwindigkeit oder das Timing ist nicht vorhersehbar.
Weil Ich starte ein Programm und einmal kann das jetzt,
also hier irgendwie wunderbar durchlaufen, weil es also im Hintergrund nichts anderes passiert.
Es kann aber sein, dass das also irgendwie dann
deutlich langsamer oder ganz anders läuft vom zeitlichen Ablauf her,
weil also jetzt irgendwelche anderen Hintergrundaktivitäten da sind,
weil also in einem Mehrbenutzersystem jetzt irgendwie andere Benutzer eingeloggt sind und so weiter.
Und dadurch dann eben entsprechend das Gheduling ganz anders ist,
andere Interraps dann irgendwie ankommen und so weiter.
Das dann übrigens auch eins der Riesenprobleme eigentlich bei so Echtzeitsystemen wenn ich garantieren muss,
dass bis da nun dann irgendein Ergebnis da ist.
Diese Garantie eben wirklich hundertprozentig sicher zu machen,
wenn ich jetzt nicht genau vorhersehen kann, wie ist jetzt die Systemlast vielleicht noch,
wenn jetzt andere Prozesse damit reinfunken oder dazukommen.
Das ist dann eben letztendlich die Schwierigkeit,
die da dann eben auch zu ganz anderen Scheduling-Algorithmen führt,
beziehungsweise dann eben auch zu entsprechenden Systemrestriktionen,
die dann eben sagen,
also es gibt nicht mehr als so und
so viele Prozesse und da dann eben teilweise auch mit
sehr starken Priorisierungen arbeiten
Gut, dazu dann erst noch mal hier grundlegende Begriffe.
Also zum einen Atomare Operation, das sind im Prinzip jetzt immer
irgendwelche Aktionen, die nicht unterteilt oder nicht unterbrochen werden kann.
Auch wenn sie aus mehreren Schritten besteht. Also im Prinzip
sowas wie diese EFA-Frage und dann eben das Inkrementieren des Wertes,
okay, das wäre jetzt also hier auf relativ hoher Ebene,
nicht aber im Prinzip, dass man sagt, okay,
wenn ich sowas hinkriege, daraus eine Atomare Operation zu machen,
heißt, entweder Die wird komplett ausgeführt oder sie wird gar nicht ausgeführt.
Nicht dann kann ich da entsprechend sicher mit arbeiten.
Auf niedrigere Ebene gibt es das jetzt eben auch,
wo ich jetzt also nur irgendwie einfach auf eine Variable drauf zugreife und dann eben versuche zu sagen,
es gibt Mechanismen, wo ich sagen kann,
ein Prozess kann eine Variable lesen und verändern und das aber nicht gleichzeitig mit einem zweiten Prozess.
Und darüber bauen dann nämlich eigentlich diese ganzen Log-Mechanismen Sind wir vor,
Mutex und so weiter, entsprechend mit auf,
die dann eben im Prinzip also auch auf unterster Hardware-Ebene dann im Prinzip solche atomaren Mechanismen haben.
So, und mit solchen atomaren Mechanismen werden dann eben quasi
solche Teile Programmcode definiert und damit lassen sich jetzt eben wieder in meinem High-Level-Programmcode eben solche Critical Sections ausmachen,
die ich dann eben mit entsprechenden Anweisungen quasi absichern muss,
um zu sagen, okay, ich mache halt eine Abfrage und sage,
hier versuche ich So ein Log, Mutual Extensions zu bekommen.
Wenn das gelingt, weiß ich, dieser Prozess ist hier
nicht in der Abarbeitung. Und wenn ich den habe,
der Prozess wird unterbrochen und hier habe ich auch quasi vor
diesem Teil Critical Section eben auch die Abfrage auf diesen Log,
dann darf dieser Prozess quasi an dieser Stelle nicht weiterarbeiten,
wenn der hier entsprechend unterbrochen wurde.
Dieser falsche Befehl kann hier quasi nicht zwischenzeitlich wirksam werden und
entsprechend würde dieser Prozess dann irgendwann später mal Hier weiter aber
in diese Critical Section wieder freigeben und dann könnt ihr hier noch irgendwie entsprechend was passieren.
So, wie man das dann rein praktisch macht von der Programmierung,
was da also an Ideen noch dahinter steckt,
welche Schwierigkeiten es da gibt, das ist jetzt das,
was dann, also im Prinzip jetzt in diesem Teil,
Synchronisation und Kommunikation, das war jetzt hier die erste Folie davon,
noch kommen wird,
das Ganze dann nächste Woche Mittwoch.
Bis dahin, dann, ja,
erstmal ein schönes Wochenende