Die andere Sache ist, dass ich noch einmal daran erinnern möchte, dass
die Anmeldung zur Klausur läuft.
Noch diese Woche, also wenn sie sich noch nicht angemeldet haben,
teilnehmen möchten, dann müssen sie sich doppelt anmelden.
Einmal bei uns am Rechner und zum anderen eben durch Einwurf des
blauen Scheins bei Herrn Raths in den Briefkasten.
Herr Raths sitzt, wenn sie den Aufzug rauffahren in unser Gebäude, so
ziemlich gegenüber vom Aufzug.
So, dann haben wir ja eine Bonusprüfung dieses Semester, das erste
Mal.
Die findet statt am 24.
Januar um 10.30 Uhr.
Es haben sich, so wie es aussieht, so ziemlich alle angemeldet.
Also wir haben so rund 450 Anmeldungen.
Die Belegungspläne hängen ja schon aus.
Es war uns noch nicht so ganz klar, wie wir genau diese Bonusprüfung
gestalten.
Inzwischen haben wir uns das genauer überlegt und die Details sehen
eben aus wie folgt.
Die Dauer der Bonusprüfung wird 45 Minuten sein.
Wir werden Ihnen drei Aufgaben stellen, wobei das, wie schon
angekündigt, eben im wesentlichen Aufgaben von den Übungsblättern sein
werden.
Leicht modifiziert, im Allgemeinen etwas vereinfacht, auch aus
Zeitgründen eben.
Und wenn Sie von diesen drei Aufgaben zwei richtig bearbeiten, dann
bekommen Sie den Bonus.
Welche Aufgaben Sie sich daraus suchen, ist egal.
Sie können auch alle drei bearbeiten.
Notwendig ist nur, dass Sie eben zwei korrekt bearbeiten.
Ja, also im Wesentlichen vollständig richtig.
Das macht uns die Korrektur einfach sehr viel einfacher.
Wir werden zur Not mal ein Auge zudrücken, aber es reicht also nicht
nur die Hälfte hinzuschreiben, so viel ist klar.
Also die Idee ist vollständig richtig, einfach aus Gründen der
Korrigierbarkeit.
Die HIWIs und wir müssen eben jetzt zusätzlich zur normalen Klausur
auch noch diese Bonusprüfung korrigieren und das muss sich
einigermaßen im Rahmen halten.
Wenn Sie den Bonus bekommen, dann sind das vier Punkte für die
Klausur.
Das entspricht so ungefähr einer Drittelnote.
Dieser Bonus ist dann nur gültig für die Klausur jetzt im Februar und
für die Klausur im Sommer, also für die Nachtklausur.
Nächstes Jahr verfällt der Bonus.
Und ja, Einsicht wird wahrscheinlich nicht notwendig sein, weil es
eben relativ klar ist, wenn Sie den Bonus kriegen, ist es sowieso
egal.
Es geht ja nicht darum, mit wie vielen Punkten.
Und wenn Sie den Bonus nicht kriegen, dann wissen Sie wahrscheinlich
auch warum, wenn Sie nicht drei Aufgaben oder wenn Sie überhaupt keine
zwei Aufgaben bearbeitet haben zum Beispiel.
Wenn Sie trotzdem einsehen wollen, dann machen wir das zusammen mit
der Klausureinsicht.
Also die Klausureinsicht für die Klausur, die jetzt geschrieben wird,
wird im April stattfinden, Anfang des Semesters.
Und da zusammen können Sie auch die Bonusprüfung einsehen.
Okay, Fragen noch dazu?
Wenn das nicht der Fall ist, dann schauen wir uns noch mal kurz an,
was wir letzte Woche gemacht haben.
Da haben wir uns mit Programmiersprachen beschäftigt.
Sie wissen, wir haben uns die Maschinensprachen angeschaut und Sie
haben gesehen, da sind nur sehr sehr einfache Konstrukte erlaubt.
Also Sie haben keine Arrays oder solchen Dinge.
Sie haben keine Schleifen, also zumindest keine For-While-Schleifen
oder ähnliches.
Sie haben nur einen relativ einfachen Befehlssatz und die
Programmierung ist relativ kompliziert.
Also Sie erinnern sich vielleicht, wir haben hier diese ein, zwei oder
drei Adressbefehle und andere Befehle haben wir im Prinzip nicht.
Wir hatten hier so ein kurzes Beispiel angeschaut, wie dann so ein
Programm aussieht zur Berechnung einer Akultät.
Also kurz und gut, eigentlich möchten Sie so nicht programmieren und
so möchte eben niemand programmieren, sondern man möchte vielmehr
problemnah programmieren, eben die Strukturen ausnutzen, die uns
geläufiger sind.
Und so hat man so eine Sprach-Hierarchie eingeführt, angefangen unten
von der Maschinensprache oder sogar Mikrobefehls-Ebene,
Maschinensprache, Assembler.
Assembler war dann einfach nur im Prinzip ähnlich wie die
Maschinensprache, aber erlaubte Ihnen eben nicht in Nullen und Einsen
zu programmieren, sondern symbolische Notationen zu verwenden und
darauf aufbauend dann eben auch höhere Programmiersprachen und wir
hatten uns letzte Stunde dann einige angeschaut.
Ich gehe da mal ganz schnell durch.
Ich hatte Ihnen Beispiele genannt für diese vier Kategorien von
Programmiersprachen.
Ihnen am bekanntesten sind sicher die objektorientierten
Programmiersprachen, die auch heute am weitesten verbreitet sind, wo
zu denen auch Java gehört.
Imperative Programmiersprachen waren lange Jahre der Standard, also
Pascal oder C wäre da zu nennen.
Und dann gibt es noch die funktionalen Programmiersprachen, die sich
mehr darauf auf die Zusammenhänge konzentrieren und nicht so genau auf
den Ablauf spezifizieren und die prädikativen Programmiersprachen, die
eher für ganz spezielle Anwendungen wie zum Beispiel in der KI
-Anwendung finden.
Okay, wenn wir solche höheren Programmiersprachen haben, dann müssen
wir letztendlich die doch immer wieder übersetzen hinunter in den
Maschinencode und da gibt es eben zwei Möglichkeiten, die ich Ihnen
vorgestellt hatte.
Die eine Möglichkeit war, dass sie wirklich übersetzen, dass sie also
den Code in einer höheren Programmiersprache schreiben, dann den
Übersetzer anwerfen, der nimmt diesen Code und spuckt ihnen
Maschinencode aus.
Und die andere Möglichkeit war, dass sie einen Interpreter verwenden.
Im Prinzip bedeutet das, wenn sie das Programm ausführen wollen, das
in einer höheren Programmiersprache geschrieben ist, dann starten sie
den Interpreter, der simuliert eine virtuelle Maschine, der tut so,
als könnte er die höhere Programmiersprache verarbeiten, schaut sich
Befehl für Befehl dieser höheren Programmiersprache an und führt diese
Befehle dann, also übersetzt diese quasi on the fly in Maschinencode
und führt die dann aus.
Dann hatten wir uns einige Aspekte der Sprachübersetzung angeschaut.
Zunächst mal hier den Assembler, der hat verschiedene Aufgaben.
Er muss eine Syntaxanalyse machen, er muss Konstanten in
Binärdarstellung überführen, er muss auch den Operationsteil jeweils
in Maschinencode, also in Binärdarstellung überführen.
Er muss so Adressen berechnen, denn wir haben ja jetzt symbolische
Ausdrücke.
Sie erinnern sich vielleicht, dass die Assemblersprache vier geteilt
war.
Also jeder Befehl konnte aus vier Teilen bestehen.
Wir hatten hier eine Marke und dann hatten wir hier die Operationen,
dann die Operanten und hinterher noch ein Kommentar.
Ja und diese Marke, mit dieser Marke konnten sie also bestimmte
Adressen oder also Befehlsadressen markieren und hinterher sagen,
springe jetzt zu dem Befehl, der die Marke XY hat und diese Marken
müssen also jetzt wieder übersetzt werden in die aktuellen Adressen.
Das macht der Assembler.
Okay, dazu muss der Assembler sich den Code zweimal anschauen.
Er muss nämlich beim ersten Mal durchlaufen, eine sogenannte
Symboltabelle erstellen, die ihm quasi sagt, welches Symbol welchen
Wert hat.
Das ist eben genau dann wichtig, wenn sie Sprünge haben, irgendwo an
eine spätere Stelle im Programmcode, dann wenn der Assembler an diese
Stelle kommen würde, könnte er ja gar nicht entscheiden, welche
Adresse das ist, sondern er muss sich erst einmal den gesamten Code
anschauen, muss diese Symboltabelle aufstellen und dann kann er beim
nächsten Mal durchgehen und die entsprechenden Symbole durch die
richtigen Adressen ersetzen.
Gut, ja, dann hatten wir uns den Interpreter näher angeschaut und den
Compiler.
Ich hatte schon ganz kurz eben angesprochen, wie die funktionieren.
Der Interpreter arbeitet eben direkt mit dem Programm in der höheren
Programmiersprache und tut so, als könnte er das verarbeiten.
Er ist selber ein Programm, das nebenher läuft und das hat gewisse Vor
- und Nachteile.
Die Vorteile sind insbesondere bei der Programmentwicklung, weil sie
im Prinzip natürlich, also diese virtuelle Maschine führt ihre Befehle
Schritt für Schritt aus.
Sie wissen jederzeit, können sie abfragen, an welcher Stelle in meinem
Programm, in dem Ursprungsprogramm in der höheren Programmiersprache
bin ich eigentlich, was sind die variablen Belegungen und so weiter.
Das heißt, das Debuggen ist relativ einfach.
Sie müssen auch nicht ständig neu übersetzen.
Wenn sie einen Compiler benutzen, dann müssen sie ja jedes Mal, wenn
sie das Programm geschrieben haben und es jetzt laufen lassen wollen
und testen wollen, dann müssen sie es neu übersetzen.
Das braucht Zeit und das ist unter Umständen lästig.
Die Nachteile sind auch klar, denn dadurch, dass sie dieses
zusätzliche Programmlaufen haben, diesen Interpreter, der auch
Rechenzeit braucht und dass dieser Interpreter im Prinzip jeden Befehl
nehmen muss und übersetzen muss in Maschinensprache während der
Ausführungszeit, haben sie natürlich einen relativ hohen Zeitaufwand
beim Laufenlassen.
Also im Normalfall wird sogar, wenn sie eine Schleife durchlaufen,
eben jeder Befehl jedes Mal neu übersetzt.
Der Kompilierer übersetzt ihnen das Programm direkt in einem
einmaligen Aufwand in die Maschinensprache und sie haben dann als
Ergebnis ein Maschinensprachenprogramm, das sie direkt ausführen
können.
Sie brauchen also nicht erst noch ein anderes Programm zu starten.
Das ist dadurch natürlich sehr viel effizienter und schneller zu
realisieren, als wenn sie ein Programm interpretieren müssen.
Gut, das ist also der Vorteil, im Wesentlichen die
Ausführungsgeschwindigkeit, auch ohne dass eine erneute Übersetzung
notwendig ist.
Der Nachteil ist klar, dadurch dass sie eben immer diesen
Übersetzungsaufwand haben, wird die Fehlererkennung und das Debugging
sehr viel schwieriger, denn das was dann letztendlich abläuft, ist ja
nur noch ihr Maschinencode und den wollen sie nicht debuggen.
Sie wollen also auf höherer Ebene auch debuggen.
Sie brauchen also zusätzliche ausgefeilte, komplexe Werkzeuge, um
Debugging zu machen, die dann ihnen den Zusammenhang herstellen zu dem
aktuellen Maschinenstand und dem aktuellen, also der Zeile in ihrem
Programmcode im Prinzip.
Aber es ist sehr viel schwieriger, als wenn sie jetzt einen
Interpreter benutzen würden.
Außerdem ist ihr übersetztes Programm natürlich rechnerspezifisch,
weil sie Maschinencode haben und der Maschinencode für jeden Prozessor
eben anders aussieht, können sie nicht ohne weiteres sagen, okay ich
nehme jetzt dieses Programm und lasse es auf einem anderen Prozessor
ablaufen.
Das können sie machen, wenn sie einen Interpreter benutzen, weil der
Interpreter, also sie müssen natürlich eine virtuelle Maschine haben
für verschiedene Prozessoren, aber wenn sie die haben, können sie ihr
höhersprachliches Programm einfach dieser virtuellen Maschine geben
und sie übersetzt es ja dann während der Ausführung in die
entsprechende Maschinensprache.
Und da ist es eben ganz egal, das wird dann immer in die richtige
Maschinensprache von der virtuellen Maschine übersetzt.
Okay, so ein Kompilierer hat vier Phasen, er macht erst mal eine
lexikalische Analyse, da versucht er einfach den Programmtext ganz
stark zu vereinfachen und auf die wesentlichen Bestandteile zu
reduzieren, um dann darauf die syntaktische Analyse machen zu können.
Dann kommt noch die semantische Analyse, wo geguckt wird, sind auch
alle Variablen deklariert und Ähnliches und es wird tatsächlich dann
der Code generiert.
Und wir haben unter Umständen noch eine Code-Optimierung anschließend,
da kann geschaut werden, okay, bestimmte Bedingungen sind vielleicht
nie erfüllt, dann kann man die einfach rausschmeißen oder, ja, wenn
sie, ich weiß nicht, ob da jetzt noch was dazu kommt, aber eine
Möglichkeit wäre, wenn sie innerhalb einer Schleife, also sie haben
zum Beispiel eine Vorschleife, da steht irgendwas und innerhalb dieser
Schleife berechnen sie x gleich y hoch z und y und z sind Variablen,
die innerhalb der Schleife nicht verändert werden.
Dann ist das zunächst mal, wenn sie das programmiert haben, spricht
das nicht für sie, weil das ganz klar eine ineffiziente Programmierung
ist.
Diese Berechnung y hoch z ist eine relativ aufwendige Berechnung und
die wird ja dann in der Schleife jedes Mal ausgeführt.
Sie könnten, wenn y und z nicht in der Schleife verändert werden,
könnten sie das einfach vor die Schleife ziehen, einmal eine neue
Variable benennen, Dummy gleich y hoch z und dann würden sie eben hier
y hoch z durch Dummy ersetzen.
Der Ausdruck kann ja noch komplizierter sein hier, das war nur ein
einfaches Beispiel.
Und der Compiler könnte der Code-Optimierung genau sowas erkennen,
könnte erkennen, okay, da hat mein Programmierer nicht effizient
programmiert.
Ich kann die Berechnung von diesem Wert y hoch z aus der Schleife
rausziehen und bin dann einfach schneller bei der Ausführung.
Also solche Dinge können in der Code-Optimierung gemacht werden, wobei
das zum Teil natürlich ein bisschen gefährlich ist.
Ich hatte Ihnen, als wir die Zahlendarstellung durchgenommen haben, ja
gezeigt, dass es unter Umständen bei der Gleitpunkt-Arithmetik auch
auf die Reihenfolge der Operationen auskommt.
Und wenn man eben die Reihenfolge der Operationen verändert,
dann kann unter Umständen ein ganz anderes Ergebnis rauskommen,
aufgrund von Rundungsfehlern, die eben bei der Gleitpunkt-Darstellung
bestehen.
Und da ist das natürlich kritisch, wenn man so eine Code-Optimierung
macht und vielleicht da irgendwelche Berechnungen umstellt.
Okay,
hier, das war die lexikalische Analyse.
Ich glaube, soweit waren wir letzte Stunde gekommen.
Gehe ich nochmal kurz darauf ein.
Da wird versucht, der Programmcode auf das Wesentliche zu reduzieren,
wesentlich jetzt in Bezug auf die Syntaxanalyse.
Für die Syntaxanalyse ist es völlig egal, ob hier eine Variable x oder
y oder z steht.
Für die ist nur wichtig, da steht eine Variable.
Wenn ich überprüfen will, ob das ein syntaktisch richtiges Programm
ist, dann ist für mich nur wichtig, in diesem Befehl steht, wenn eine
Variable kleiner ist als eine reelle Zahl, dann mache irgendwas und
dann kann ich überprüfen, ist das ein syntaktisch richtiger Befehl.
Ob der Befehl wirklich Sinn macht oder ob da statt x, y stehen müsste,
das kann in der syntaktischen Analyse sowieso nicht rauskommen.
Also, in der lexikalischen Analyse überführt man dieses Programm in so
einen Programmcode, wo eben nur noch solche Platzhalter oder
Bezeichner verwendet werden, solche Tokens, wie immer man es nennen
will.
Und damit kann ich dann die syntaktische Analyse machen, also im
Prinzip das, was wir auch im ersten Teil der Vorlesung, im
theoretischen Teil der Vorlesung gemacht haben.
Man erstellt solche Ableitungsbäume und überprüft, ob das Programm
grammatikalisch korrekt ist.
Okay, Sie erinnern sich wahrscheinlich, wie so ein Ableitungsbaum
aussieht.
Die Blätter hier, also so eine Verzweigung wäre immer eine Überführung
einer Grammatik, also eine Bedingung setzt sich zusammen aus Ausdruck,
was relatives Symbol und Ausdruck, also Beziehungssymbol und Ausdruck.
Das wäre so ein Übergang in dieser Grammatik.
Und wenn Sie so einen Ableitungsbaum aufgestellt haben, dann sind eben
gerade in den Blättern die Terminalsymbole, beziehungsweise müsste
dann das Programm stehen.
In unserem Fall steht hier eben if Name kleiner reelle Zahl, dann Name
Doppelpunkt gleich Name plus Name Ende.
Das ist genau das Beispiel, das hier auch aufgeführt ist.
Und wenn ich so einen Ableitungsbaum konstruieren kann, dann weiß ich,
dass das Programm grammatikalisch korrekt ist.
Okay, dann gehört zur semantischen Analyse hier gewisse Überprüfungen,
wie zum Beispiel, dass jede benutzte Variable auch am Programmanfang
deklariert ist, beziehungsweise dann schaue ich mir an, was haben denn
die Variablen für Typen, dass ich nicht hier ganz unkompatible
Variablen miteinander vergleiche oder addiere oder die eine der
anderen zuweise oder so weiter.
Das sind also die Sachen, die man dann in der semantischen Analyse
macht und dann generiert man den Code.
Das heißt, es wird eben das Assembler- oder Maschinenprogramm erzeugt.
Und am Schluss, wie gesagt, die Code-Optimierung, wo man versucht, zum
einen die Laufzeit im Wesentlichen, aber unter Umständen auch den
Speicherplatz zu optimieren.
Ein Beispiel hatte ich Ihnen vorhin vorgeführt, wenn man eben so eine
Schleife hat und dann mehrfach den gleichen Ausdruck berechnet, obwohl
sich der zwischen diesen zwei Berechnungen nicht geändert haben kann,
das wäre so eine Sache, die so ein Optimierer erkennen kann und dann
eben auflösen kann.
Okay, jetzt habe ich Ihnen einiges erzählt über Interpreter und
Sprachen, die interpretiert werden und Compiler und Sprachen, die
übersetzt werden.
Sie kennen alle Java, müssten eigentlich im Prinzip wissen, wie das
bei Java aussieht.
Wer ist denn der Meinung, dass Java eine Sprache ist, die
interpretiert wird?
Relativ wenige.
Wer ist der Meinung, dass Java eine Sprache ist, die kompiliert wird?
Auch nicht viel mehr, also die Mehrheit scheint sich unsicher zu sein.
Also Sie haben bei Java, wenn Sie ein Java-Programm laufen lassen
wollen, müssen Sie es vorher immer erst kompilieren.
Aber Java hat so einen Zwischenweg gewählt, es ist weder eine reine
Interpretersprache noch eine reine Compilersprache, die übersetzt
wird, sondern Java wird erst einmal mithilfe von diesem Befehl mit dem
Java -Compiler in Bytecode übersetzt.
Und dieser Bytecode ist aber noch nicht Maschinensprache, der ist noch
maschinenunabhängig und das ist auch einer der großen Vorteile von
Java.
Aus dem Grund können Sie Java-Plattformen unabhängig ausführen und es
ist völlig egal, was für einen Rechner Sie dahinter hängen haben.
Solange Ihr Rechner den entsprechenden Interpreter für den Java
-Bytecode hat und das ist diese sogenannte Java-Virtual-Machine.
Also hier, das ist der Compiler und das hier ist im Prinzip der
Interpreter.
Das heißt, Java wird sowohl übersetzt und der Bytecode wird dann noch
interpretiert.
Die haben also jetzt beides zusammen und haben als Hauptvorteil
dadurch eben die Plattformunabhängigkeit und die trotzdem noch
einigermaßen effiziente Ausführbarkeit.
Java wird jetzt ganz massiv entwickelt in den letzten Jahren und
verbessert sich kontinuierlich.
Trotzdem ist es immer noch so, dass C, also wenn Sie jetzt ein
Programm schreiben in C und das direkt übersetzt wird in
Maschinencode, so anderthalb bis zweimal schneller ist, würde ich
sagen, so Daumenregel.
Also da gibt es viele Diskussionen drüber und das hängt auch immer
davon ab jetzt, was für ein Compiler und auf welcher Maschine und was
weiß ich, aber so als Daumenregel.
Es ist immer noch etwas langsamer, weil es eben durch die Java-Virtual
-Maschine der Bytecode interpretiert werden muss.
Okay, das heißt eben, Sie brauchen diese virtuelle Maschine, die hat
auch noch einen anderen Vorteil, der bei Java jetzt sehr wichtig ist.
Diese virtuelle Maschine kann dann so eine sogenannte Sandbox
bereitstellen, die eben genau kontrolliert, auf was Sie zugreifen und
auf was Sie nicht zugreifen.
Und dadurch ist Java auch sehr geeignet, um zum Beispiel Webbrowser
-Anwendungen laufen zu lassen, bei denen Sie vielleicht nicht immer
ganz genau wissen, kann ich diesem Programm vertrauen oder kann ich
dem nicht vertrauen.
Dadurch, dass eben Sie nur Bytecode runterladen und der dann nochmal
über die virtuelle Maschine interpretiert wird, können Sie durch die
virtuelle Maschine, die Sie ja auf Ihrem Rechner installiert haben,
die unter Ihrer Kontrolle ist und der Sie vertrauen, können Sie eben
festlegen, was kann eigentlich dieser Bytecode überhaupt machen und er
kann dann eben bestimmte Dinge in Ihrem Programm oder auf Ihrem
Rechner nicht verändern, hat keinen Zugriff auf Ihre privaten Dateien
und so weiter und so fort.
Okay, Nachteil sagte ich schon, ist die Laufzeit ein bisschen, Vorteil
ist die Sicherheit und die Plattform-Unabhängigkeit.
Gut, das könnte man hier dazu schreiben, Sicherheit und Plattform
-Unabhängigkeit.
Platt.
Dann gibt es noch sogenannte Just-in-Time-Compiler, ich weiß nicht, ob
Sie davon schon gehört haben.
Die versuchen die Ausführung von solchen Java-Programmen noch zu
beschleunigen.
Da ist die Idee im Wesentlichen, wenn Sie eine Methode das allererste
Mal benutzen, dann wird diese ja übersetzt.
Das heißt, der Bytecode wird in die Maschinensprache übersetzt und
normalerweise bei so einem Interpreter wird das eben jedes Mal
gemacht, wenn dieser Befehl ausgeführt wird, also wenn dieser Befehl
aufgerufen wird, dann wird er jedes Mal neu übersetzt in
Maschinensprache und dann in Maschinensprache ausgeführt.
Und diese Just-in-Time-Compiler, die merken sich im Prinzip, welche
Befehle schon häufig hervorgekommen sind und welche Befehle schon
übersetzt worden sind und behalten sich die entsprechenden
Maschinensprachenteile im Speicher und versuchen dann eben das, was
sowieso schon übersetzt wurde, nicht nochmal und nochmal und nochmal
und nochmal zu übersetzen, sondern das dann direkt aus dem Speicher zu
holen und direkt den Maschinencode auszuführen.
Das funktioniert teils gut und teils weniger gut, das kommt eben auf
Ihr Programm drauf an, aber damit ist unter Umständen ein gewisser
Zeitvorteil erreichbar.
Das ist nicht viel, aber so 10% Beschleunigung können Sie schon im
Allgemeinen erwarten, wenn Sie so Just-in-Time-Compiler verwenden.
Es gibt auch echte Compiler für Java, bei denen Sie also direkt
wirklich Maschinencode erzeugen.
Dadurch werden Sie natürlich nochmal ein bisschen schneller, aber Sie
verlieren die Vorteile wie die Plattformunabhängigkeit oder die
Sicherheit durch die Sandbox.
Das heißt, da muss man sich überlegen, was einem eben jetzt konkret
wichtiger ist an der Stelle.
Okay, das war also das Kapitel Programmiersprachen.
Ich weiß nicht, ob es da noch Fragen dazu gibt.
Wenn nicht, dann kommen wir zum nächsten Kapitel, Betriebssysteme.
Ich hatte Ihnen gesagt, man versucht die Programmierer zu entlasten,
man will nicht, dass sie jetzt wirklich alles in Maschinencode direkt
programmieren müssen.
Und da gibt es eben diese zwei Dinge.
Zum einen gibt es die Programmiersprachen, die Ihnen erlauben, sehr
viel problemnäher zu programmieren und eben nicht in Form von Nullen
und Einsen.
Und zum anderen gibt es die Betriebssysteme, die auf jedem Prozessor
im Prinzip laufen und die Ihnen gewisse Grundfunktionalitäten einfach
bereitstellen.
Das heißt, Sie möchten sich als Programmierer nicht unbedingt darum
kümmern, wie jetzt genau ein Netzwerkzugriff funktioniert.
Es sollte Ihnen eigentlich egal sein, was der Rechner jetzt für eine
Grafikkarte hat oder ob da jetzt ein Laserdrucker angeschlossen ist,
den man ganz anders ansprechen muss als ein Tintenstrahldrucker.
Sie möchten sich auch nicht um so Dinge kümmern wie Zugriffsschutz
oder Prozessorauslastung oder was passiert, wenn jetzt mehrere
Programme gleichzeitig laufen, dass die sich nicht gegenseitig ins
Gehege kommen.
All diese Dinge, um die möchten Sie sich als Programmierer nicht
kümmern und deswegen werden die in Form eines Betriebssystems
bereitgestellt.
Übersicht über das Kapitel.
Ich werde erst einmal versuchen, genauer zu beschreiben, was
eigentlich ein Betriebssystem ist und was die genauen Aufgaben sind.
Dann schauen wir uns ein paar Beispiele an für Betriebssysteme, die
Ihnen wahrscheinlich geläufig sind.
Dann gucken wir, was gibt es denn für Ziele, die dieses Betriebssystem
haben kann in Bezug auf, in welcher Reihenfolge werden bestimmte
Aufgaben gemacht.
Da kann man eben auf Effizienz achten oder man kann auf schnelle
Antwort achten und so weiter.
Da gibt es verschiedene Grundbetriebsarten, wie man so einen Computer
betreiben kann.
Dann schauen wir uns nochmal an Prozesse und Prozesszustände.
Wir hatten schon mal über Prozesse und Threads geredet.
Jetzt gucken wir uns das nochmal genauer an und was passiert
eigentlich mit so einem Prozess so in der Reihenfolge.
Der muss initiiert werden und dann irgendwann läuft er dann ab, dann
wird er wieder unterbrochen und so weiter.
Dann schauen wir uns einige ganz konkrete Betriebssystemaufgaben an,
nämlich einmal die Rechenzeitzuteilung.
Wenn jetzt mehrere Prozesse laufen, welcher Prozess bekommt jetzt den
Zugriff auf den Prozessor und die Speicherverwaltung.
Und am Schluss schauen wir uns noch an so eine Problematik oder eine
der ganz grundlegenden Problematiken, wenn Sie mit mehreren Prozessen
arbeiten, nämlich die Synchronisation, also wie verhindert man, dass
die sich gegenseitig behindern und gegenseitig ins Gehege kommen und
ein paar Sicherheitsaspekte noch, weiß nicht, ob wir da heute noch
dazu kommen.
Okay, das Ziel dieses Betriebssystems ist, dass Sie die Rechenanlage
oder den Computer inklusive allem, was daran hängt, also der
Peripherie, sowohl einfach benutzen können, also sich nicht um die
Details kümmern müssen.
Ich sagte eben, dass es Ihnen egal sein soll, was da für eine
Grafikkarte drinsteckt und was da für einen Drucker dranhängt.
Das sind Details, um die Sie sich nicht kümmern wollen und die Anlage
soll effizient betrieben werden.
Das heißt, Sie möchten die natürlich möglichst gut auslasten und sie
sollte auch von mehreren Anwendern genutzt werden können, ohne dass
Sie sich jetzt da konkret drum kümmern müssen unter Umständen.
Das Betriebssystem muss dazu natürlich wissen, aus was für Komponenten
sich der Rechner zusammensetzt.
Das ist ja genau das, was Sie als Programmierer dann nicht mehr
interessieren muss.
Das heißt, Sie müssen wissen, was für einen Prozessor, wie viele
Prozessoren sind in dem Computer drin, wie viel Speicher haben Sie.
Das sind ja alles Daten, die Ihnen als Programmierer auch überhaupt
nicht bekannt sind.
Und deswegen ist es sogar nicht nur angenehm, dass dieses
Betriebssystem das übernimmt, sondern es ist absolut notwendig.
Sonst müssten Sie ja für jeden Rechner, der anders konfiguriert ist,
Ihr Programm anders schreiben.
Die einen Ausgabegeräte müssen natürlich dem Betriebssystem bekannt
sein und auch wie sind die Daten strukturiert, wo liegen die Daten und
so weiter und so fort.
Und dann brauchen Sie eben Mechanismen, um jetzt verschiedenen
Benutzerprogrammen, die unter Umständen gleichzeitig laufen, den
Zugriff auf die verschiedenen Betriebsmittel zu geben.
Also wer bekommt jetzt den Prozessor, wer darf mit dem Drucker reden,
wer hat jetzt Zugriff aufs Netzwerk und so weiter und so fort.
Und alle in diesem Rahmen anfallenden Aufgaben werden übernommen von
sogenannten Systemprogrammen und die Summe all dieser Systemprogramme
nennt man dann Betriebssystem.
Das Betriebssystem ist ein Programm, das hat irgendjemand programmiert
und das wird so wie alle anderen auch, als ein ganz normales Programm,
das wird von dem Prozessor ausgeführt und das verbraucht Rechenzeit.
Und wenn der Computer was Sinnvolles machen soll, also
Betriebssystemfunktionen sind zwar notwendig, aber nicht unbedingt
wirklich sinnvoll, die verrichten keine Arbeit, sondern was sie von
dem Computer erwarten ist, dass sie eine Textverarbeitung haben oder
dass sie E-Mail schreiben können oder im Netz surfen können oder was
auch immer.
Das ist die Arbeit, die für sie sinnvoll ist.
Damit der Computer sinnvolle Arbeit machen kann, muss das
Betriebssystem die Kontrolle abgeben und muss den Prozessor an das
entsprechende Anwendungsprogramm übergeben.
Also wir wissen aus den vorherigen Vorlesungen, dass ein Prozessor
immer nur ein Programm gleichzeitig ausführen kann und die Tatsache,
dass sie jetzt unterschiedliche Programme gleichzeitig ausführen
können, das sieht nur so aus, also jeder Prozess bekommt eben dann so
eine Zeitscheibe, bekommt irgendwie ein kleines bisschen Zeit und dann
sieht es für sie so aus, als würden die gleichzeitig abgearbeitet.
Aber im Wesentlichen kann eben immer nur ein Programm abgearbeitet
werden und das kann auch bedeuten, entweder Betriebssystem oder
irgendeine sinnvolle Anwendung.
Und wenn die sinnvolle Anwendung Rechenzeit bekommt, dann bedeutet
das, das Betriebssystem gibt in der Zeit die Kontrolle ab.
Gut, die Aufgaben von solchen Betriebssystemen hatte ich schon ein
paar angesprochen.
Eines ist natürlich die Prozessorverwaltung.
Das heißt, Sie müssen entscheiden, welcher Prozess jetzt Zugriff
bekommt auf den Prozessor, wie viel Rechenzeit er bekommt, bevor dann
der nächste wieder dran ist.
Unter Umständen auch bei mehreren Prozessoren.
Also es ist Ihnen als Programmierer zumindest im Allgemeinen egal, ob
jetzt in Ihrem Rechner ein Prozessor oder zwei Prozessoren oder vier
Prozessoren sind.
Das Betriebssystem entscheidet dann, welcher Prozess auf welchem
Prozessor abläuft.
Das heißt, es ist für den Programmierer transparent oder für das
Programm transparent.
Es muss gar nicht wissen jetzt, wie viele Prozessoren da sind.
Wenn Sie natürlich das speziell ausnutzen wollen und vielleicht sehr
viele Prozessoren haben, dann werden Sie mit entsprechenden
Bibliotheken, die ich auch schon angesprochen hatte, MPI oder sowas,
tatsächlich die Kommunikation zwischen, also wirklich verschiedene
Prozesse auf verschiedenen Prozessoren starten wollen und die
Kontrolle haben wollen.
Aber das Betriebssystem, also die Idee hier ist, dass das eben
transparent läuft.
Hauptspeicherverwaltung, das heißt, es ist Ihnen völlig egal, wie viel
Hauptspeicher in dem Rechner vorhanden ist.
Sie nehmen einfach mal an, ich brauche jetzt so und so viel
Hauptspeicher und der kommt dann irgendwo her.
Sie bekommen irgendeinen Teil im Hauptspeicher zugewiesen, unter
Umständen ist gar nicht genug da.
Dann muss ausgelagert werden auf die Festplatte.
All diese Dinge übernimmt das Betriebssystem.
Auch wenn eben mehrere Prozesse laufen, muss ja der Speicher
aufgeteilt werden.
Es muss sichergestellt sein, dass Sie nicht Zugriff haben auf
Speicherelemente von anderen Programmen und so weiter und so fort.
Programmausführung, das heißt, das Laden des Programms oder der
einzelnen Befehle und Daten in den Hauptspeicher.
Da muss ja auch wieder entschieden werden, an welcher Stelle.
Es muss klar sein, an welcher Stelle die jetzt auch wirklich liegen
und so weiter.
Der Zugriff auf Ein-Ausgabe-Geräte.
Ja, das heißt, Sie müssen natürlich, je nachdem, was für ein Ein
-Ausgabe -Gerät Sie dran haben, unter Umständen ganz unterschiedliche
Steuersignale benutzen.
Dann der Netzzugriff könnte man als weiteres Ein-Ausgabe-Gerät sehen.
Zugriff auf Dateien, das heißt, das Betriebssystem muss die Struktur
auch der Dateien kennen, muss Zugriffsschutz verwalten können, muss
wissen, okay, auf diese Datei darf jeder zugreifen, auf diese Datei
darf vielleicht nur der eine oder andere zugreifen.
Auch das System als Ganzes, also diese Funktionalität, dass Sie sich
am Rechner vielleicht erst einloggen müssen, erst identifizieren
müssen, bevor Sie überhaupt den Rechner benutzen dürfen.
Insbesondere auch, wenn Sie im Internet surfen, dass niemand von außen
irgendwie jetzt auf Ihren Rechner Zugriff hat.
Also solche Dinge sind Teil des Betriebssystems.
Letztendlich auch noch die Buchführung.
Wenn irgendwelche Fehler auftreten, wenn Sie irgendwelche Viren
eingefangen haben, wenn irgendein Hacker auf Ihren Rechner gekommen
ist, dann möchten Sie möglichst das nachvollziehen können.
Das heißt, das System führt einen Systemlog, wo Sie die wichtigsten
Dinge, die in der letzten Zeit passiert sind, nachvollziehen können.
Und dann gibt es noch eine Reihe weiterer Dienste, wo man sich jetzt
streiten kann, gehört das wirklich zum Betriebssystem oder gehört das
nicht zum Betriebssystem?
Editor, Compiler, Debugger, das sind so Dinge, die werden häufig
mitgeliefert.
Also so einen ganz grundlegenden Editor haben Sie eigentlich immer
dabei.
Irgendeinen grundlegenden Compiler im Wesentlichen auch.
In letzter Zeit interessant, naja, zumindest vor ein, zwei Jahren war
das besonders interessant, die Diskussion, gehört ein Browser jetzt
zum Betriebssystem oder gehört er nicht dazu?
Microsoft war ja der Ansicht, das ist unbedingt notwendig, dass man
einen Browser hat im Betriebssystem und wir können das absolut nicht
trennen.
Und andere haben eben die Meinung vertreten, das kann man sehr wohl
trennen.
Der Browser gehört überhaupt nicht zum Betriebssystem.
Und der Grund, warum Microsoft das so stark verknüpft, ist nur, weil
sie eben alle Konkurrenten ausschalten wollen.
Und diese Strategie hat ja auch sehr gut funktioniert.
Also vor fünf Jahren oder was gab es eben im Wesentlichen Netscape und
Mosaik als Browser.
Und dann kam Microsoft und hat mit der Marktmacht und eben auch mit
dieser engen Kopplung, dass sie eben mit dem Betriebssystem
automatisch den Browser mit drin hatten und ihn eigentlich gar nicht
mehr los wurden, alle anderen verdrängt.
Im Prinzip finde ich das gerade auch für Wirtschaftsingenieure oder
Informationswirte, dieses Zusammenspiel von auf der einen Seite
Informatik -Sicht und was sich dadurch alles geändert hat und was da
eben relevant ist und auf der anderen Seite diese wirtschaftlichen
Aspekte, sehr interessant, ich würde Sie ermutigen in die Richtung,
vielleicht auch mal im Hauptstudium sich mal ein paar Sachen
anzuschauen.
Also solche Netzwerkeffekte und solche Marktmachteffekte und
Standardisierungseffekte, dass eben ein Programm immer wertvoller
wird, je mehr Leute es benutzen.
Weil ich dann eben Daten austauschen kann und weil entsprechende
Zweitsoftware oder Ergänzungssoftware oder Handbücher auf den Markt
kommen und so weiter.
Und Microsoft hat das sehr, sehr gut raus, diese Effekte auszunutzen
und hat eben einen absolut dominierenden Marktmacht, was ich
persönlich eher für schon wieder gefährlich halte.
Aber gut.
Okay, schauen wir uns ein paar Betriebssysteme an, ich möchte einfach
nur kurz noch mal ein paar skizzieren.
Ich weiß nicht, wer das von Ihnen noch kennt, MS-DOS, Microsoft Disk
Operating System, Bill Gates hat das im Wesentlichen von jemandem
eingekauft, damals hieß das KUDOS für Quick and Dirty Operating
System.
Also das war irgendwie ziemlicher Schrott, aber das war egal, denn er
hat es geschafft, dieses Betriebssystem IBM zu verkaufen.
Und IBM hatte eben damals die massive Marktmacht, die hatten auf dem
Hardware -Bereich einen riesigen Marktanteil und die haben eben
gesagt, okay, wir benutzen jetzt Microsoft.
Und sie haben sich völlig verkalkuliert, weil sie gedacht haben, das
Wichtige ist, wer die Hardware kontrolliert und wie sich
herausgestellt hat, ist das Wichtige, wer die Software kontrolliert.
Und deswegen sind Bill Gates und Microsoft so groß geworden.
Und IBM hat es dann nicht mehr geschafft, diesen Dämon, den sie da
gerufen haben, wieder loszuwerden.
Sie haben ja versucht, ein alternatives Betriebssystem Wie hieß das
gleich?
Ich weiß schon gar nicht mehr, wie es hieß.
Sie haben versucht, ein alternatives zu entwickeln und sind aber daran
gescheitert, weil einfach diese Effekte, wenn eben alle das haben, das
dann umzustellen, das ist sehr, sehr schwierig.
Okay, so sind wir also zu MS-DOS gekommen.
Das hatte haarsträubende Eigenschaften zu der Zeit im Vergleich mit
anderen Systemen, die eben zu dieser Zeit auch schon verfügbar waren.
Das CPM oder das Macintosh-Betriebssystem, macOS, die waren
unglaublich weit voraus, hat aber nichts geändert an der Tatsache,
dass sich das DOS durchgesetzt hat.
Microsoft hat dann diese inzwischen schon häufiger sehr erfolgreiche
Strategie übernommen oder angewendet.
Es hat dann sich umgeguckt, was machen denn die anderen
Betriebssysteme so, was können die?
Und dann haben sie sich eben hingesetzt und haben das im Wesentlichen
nachgemacht.
Das heißt, das, was sie dann als Windows vielleicht kennengelernt
haben, das war im Prinzip eine schlechte Kopie von dem Macintosh
-System.
Die Mausbedienung ist da erst eingeführt worden.
Also in MS-DOS gab es keine Maus, das war nicht bekannt, obwohl andere
Rechner das schon lange benutzt haben.
Solche Dropdown-Menüs, ähnliches Multi-User-System, Multitasking, also
dass verschiedene Programme gleichzeitig ausgeführt werden konnten und
so weiter.
Das kam alles so mit der Zeit.
Heutzutage mit Windows XP haben wir ein ganz brauchbares Produkt.
Das heißt, sie haben eigentlich all diese Funktionalität, die sie
brauchen.
Windows CE oder Windows gibt es inzwischen auch schon für andere
Plattformen, also nicht nur für Rechner, sondern auch beispielsweise
für diese PDAs, also Primetops oder Handhelds, für Set-Top-Boxen auf
Fernsehern, für Smart-Cards sogar, dass die Funktionalität natürlich
drastisch reduziert.
Aber Microsoft versucht mit Macht, seine Position, die sie auf dem PC
-Bereich haben, auszubauen und zu erweitern, die Xbox, also solche
Spiele -Konsolen, und entwickelt eben Windows-Varianten für
verschiedene Prozessoren und verschiedene Anwendungen.
Die haben dann natürlich auch andere Aufgaben, ist klar.
Das Macintosh-System hatte ich schon angesprochen.
Das war eben zu der Zeit, als MS-DOS rauskam, schon sehr, sehr viel
weiterentwickelt.
Die haben Pionierarbeit geleistet im Bereich der Fenstertechnik, im
Bereich der mausgeführten Benutzung.
Entwickelt hat die Maus das Forschungslabor von Xerox, aber Apple mit
dem Macintosh waren eben die Ersten, die erkannt haben, okay, das ist
wirklich sinnvoll, so eine Maus zu haben, und die, die dann einfach
jedem Rechner beigelegt haben und das wirklich groß gemacht haben.
Ein anderer großer Vorteil von Apple war das Apple-Talk-Protokoll.
Also es war sehr, sehr schwierig, DOS-Rechner irgendwie zu vernetzen,
sodass die kommunizieren konnten.
Das war von Anfang an im Prinzip bei dem Macintosh dabei, und auch da
haben die große Pionierarbeit geleistet.
Seit ein paar Jahren, also als dann dieses Windows so groß wurde und
Macintosh mehr und mehr Marktanteil verloren hat, waren die dann
irgendwann auch nicht mehr so richtig konkurrenzfähig.
Also viele haben schon damit spekuliert, dass die eigentlich nicht
mehr lange überleben.
Was sie dann gemacht haben, war, dass sie Mac OS X rausgebracht haben,
und das ist jetzt UNIX-basiert.
Das heißt, sie haben UNIX als Grundlage genommen, auf UNIX gehe ich
gleich noch ein, und haben darauf dann eine benutzerfreundlichere
Schnittstelle gesetzt, die, denke ich, auch benutzerfreundlicher ist
als Windows.
Also sie haben wieder die Führungsrolle in der Benutzerfreundlichkeit
übernommen, und dadurch, dass sie UNIX als Unterbau haben, haben sie
jetzt auch gleichzeitig wieder die Führungsrolle in Sachen Stabilität
und mehr Prozessorsysteme und so weiter und so fort.
Aus meiner Sicht sind sie damit jetzt wieder eigentlich das beste
Betriebssystem.
Ob es eine Chance hat, sich durchzusetzen, wird sich zeigen.
Also ich verwende heute hier auch Windows XP, auch wenn ich ansonsten
Macintosh und Linux verwende, weil mir eben das Programm zum
Aufzeichnen der Vorlesung, das ist für Macintosh nicht verfügbar, und
deswegen habe ich eben für die Vorlesung ein PC ausleihen müssen.
Gut, UNIX ist also, wie gesagt, der Unterbau von Macintosh, von dem
heutigen Mac OS X, aber entstand eigentlich an der Universität in
Berkeley in den USA im Rahmen eines Studentenprojekts, also erstmal in
einer ganz einfachen Art und Weise, wurde dann immer größer, immer
größer, immer komplexer, war lange Jahre eigentlich das einzige
vernünftige Betriebssystem, was solche Dinge anging wie
Mehrbenutzerbetrieb, also dass sich viele Leute einloggen konnten und
gleichzeitig arbeiten konnten für Workstations und Server.
Also es war im Prinzip das einzige wirklich zuverlässige System,
vielleicht abgesehen noch von den Großrechnersystemen, auf die ich
gleich noch eingehe.
Es ist heutzutage auf, ja, im Prinzip alle wichtigen
Rechnerplattformen, auf allen wichtigen Rechnerplattformen verfügbar,
in verschiedenen Varianten.
Dieses BSD, das ist das Berkeley System, System 5, HP hat ein eigenes
UNIX, IBM hat ein eigenes UNIX, Fun hat ein eigenes UNIX, Solaris und
so weiter und so fort.
Immer noch sehr wichtig im Serverbereich eben.
Also die ganzen großen Server laufen eigentlich unter UNIX, wenn es
eben auf Stabilität ankommt und zum Beispiel bei Banken oder
ähnlichen.
Es gibt so Hochrechnungen, wenn der Rechner einer Bank ausfällt, dass
die Bank nach einem Tag in wesentlichen Pleite ist.
Und dann wird man eben nicht auf so Produkte wie Windows setzen.
Zumindest im Augenblick noch nicht.
Linux ist im Prinzip eine UNIX-Variante, die frei ist, also kostenlos,
die von allen möglichen Leuten in ihrer Freizeit entwickelt wird.
Also auf der ganzen Welt haben die sich so zusammengeschlossen in ein
Netzwerk, haben eine selbstorganisierte Qualitätssicherung, jeder kann
den Code sich anschauen, jeder kann daran mitarbeiten.
Wächst zur Zeit ganz massiv.
Ich weiß nicht, ob Sie mitbekommen haben, dass zum Beispiel München
sich entschlossen hat, all ihre Rechner auf Linux umzustellen, also
weg von Microsoft.
Man muss abwarten.
Also der Marktanteil von Linux ist immer noch relativ gering und man
wird abwarten, wie sich das entwickelt.
Das ist eben, wie gesagt, ein freies Betriebssystem mit den Vorteilen,
also nicht nur den Kostenvorteilen, sondern eben auch
Sicherheitsvorteilen, weil eben jeder reingucken kann, kann man eben
einen Fehler relativ schnell entdecken, relativ schnell korrigieren.
Hat die Nachteile, dass es mit dem Service unter Umständen nicht ganz
so toll ist, dass hier eben solche Sachen wie Qualitätssicherung oder
so ist, unter Umständen einfach schwieriger, langsamer manchmal.
Dann gibt es noch solche Großrechnerbetriebssysteme, so Großrechner
sind nicht mehr so häufig vertreten.
MVS, VMS, BS2000, hat eben auch jeder Hersteller von Großrechnern sein
eigenes Betriebssystem.
Die Rechenanlagen sind sehr unterschiedlich.
Das Ganze hat im Prinzip angefangen, weil die Rechner sehr, sehr teuer
waren, mit Großrechnern und irgendwelchen dummen Terminals, die also
nur eine Kommunikationsschnittstelle waren zum Großrechner.
Dann kam die Zeit, wo man gesagt hat, okay, Großrechner, so ein
Schrott, das brauchen wir überhaupt nicht, das muss jeder seinen
eigenen PC auf dem Schreibtisch stehen haben, also weg mit den
Großrechnern, jeder seinen PC.
Dann hat man gemerkt, das hat auch Nachteile, wenn nämlich jeder
seinen PC auf dem Schreibtisch hat, dann konfiguriert da jeder dran
rum, dann muss der Systemadministrator, wenn er eine neue
Programmversion einspielen will, die nicht nur auf dem Großrechner
einspielen, sondern muss an jeden einzelnen Arbeitsplatz gehen.
Also diese Total Cost of Ownership, was alles dann mit dranhängt, noch
an der Verwaltung und Wartung und so weiter, ist bei diesen PCs
eigentlich einfach sehr, sehr groß.
Dann hat man in den letzten Jahren gedacht, okay, die optimale Lösung
ist, ich habe einen Großrechner, der im Wesentlichen die ganzen Daten
hält, also als Server dient und ich habe dann sogenannte Thin Clients,
also dünne Terminals, die nicht unbedingt, also im Allgemeinen dann
keine eigene Festplatte haben, also nicht ihre Daten separat
speichern, die aber einen eigenen Prozessor haben, die also durchaus
gewisse Rechenkapazität haben.
Das war irgendwie mal Hype in den letzten Jahren, hat sich nicht so
durchgesetzt.
Im Augenblick geht der Trend so dahin, dass man sagt, man will
eigentlich ein Netzwerk von Rechnern haben, die alle untereinander
gegenseitig so peer-to-peer aufeinander zugreifen, die dann
Ausfallsicherheit haben und so weiter und so fort.
Man wird sehen, wohin die Reise noch geht.
Okay, solche Betriebssysteme kann man in unterschiedlicher Art und
Weise programmieren.
Ich sagte Ihnen, das ist im Prinzip die Einheit von verschiedenen
Systemdiensten, von verschiedenen Systemprogrammen.
Die meisten Betriebssysteme sind monolithisch, das heißt, sie haben
verschiedene solche Systemprogramme, die sie alle gegenseitig aufrufen
können und das ist ein großer Block.
Sinnvoll, und dahin geht der Trend, ist, dass man das Betriebssystem
modularisiert und dass man eine Schichtenhierarchie einführt.
Schichten haben wir schon häufiger gehabt, die Informatiker lieben
Schichten.
Das heißt, sie haben verschiedene Schichten und jede Schicht greift
ausschließlich auf Funktionen der darunterliegenden Schicht zu.
Dadurch können sie eben bestimmte Fehler vermeiden und die
Programmierung wird einfacher.
Ein Beispiel für eine Schichtenhierarchie ist hier angegeben.
Sie haben ganz unten die Rechner-Hardware, da haben Sie den
Betriebssystem Kern, wo solche Dinge drin sind wie der
Prozessumschalter, der dann zwischen einem Prozess und dem anderen
eben umschalten kann, Synchronisationswerkzeuge, ähnliches.
Schicht zwei wäre dann zum Beispiel Betriebsmittelverwaltung, und
Schicht drei die Auftragssteuerung auf einer höheren Ebene, also
welche Aufträge kommen jetzt überhaupt in die Schlange der zu
bearbeitenden Aufträge und so weiter.
Man könnte sich andere Schichtenmodelle vorstellen.
Mein Vorschlag wäre, dass man unten sagt, man hat hier die
Prozessverwaltung und Synchronisation,
das heißt, alles was darauf aufbaut, also diese Prozessverwaltung
kümmert sich darum, was passiert, wenn jetzt mehrere Prozesse da sind,
wie werden die aufeinander abgestimmt, wer von denen bekommt jetzt die
Rechenzeit.
Und was darauf aufbaut, muss sich darum schon nicht mehr kümmern, kann
davon ausgehen, dass es im Prinzip der alleinige Prozess ist oder kann
so tun, als wäre es der alleinige Prozess.
Die Schicht darüber könnte dann zum Beispiel Speicherverwaltung sein
und alle Schichten darüber könnten dann mit ihrem virtuellen Speicher
arbeiten und müssten sich jetzt nicht mehr darum kümmern, an welcher
Stelle jetzt genau ist das Programm und wo sind die Daten abgelegt und
wie viele Hauptspeicher habe ich und so weiter.
Und darüber dann zum Beispiel ein Ausgabemanagement,
da könnte dann beispielsweise jedes Programm, alles was darüber ist,
könnte annehmen, okay, ich habe eine Tastatur und ich habe einen
Drucker und dass die Tastatur vielleicht zur Eingabe in verschiedenen
Programmen verwendet wird und der Benutzer von einem Programm ins
andere rüber springt, ist mir egal, also ich habe meinen eigenen Ein-
und Ausgabe-Buffer, wo ich die Sachen rein- und rausschreiben kann.
Also das wäre irgendwie einfach so ein alternatives Schichtenmodell,
aber Sie können sich verschiedene überlegen.
Wichtig ist nur, solche Schichten sind sinnvoll und die
Betriebssystementwicklung geht in die Richtung, dass solche Schichten
immer stärker verwendet werden.
Okay, wenn ich jetzt ein bestimmtes Programm ausführen will, dann muss
ich im Wesentlichen einen Auftrag formulieren.
Ich muss dem Computer sagen, was er machen soll und so ein Auftrag
setzt sich zusammen aus einer Menge von möglicherweise gegenseitigen
Teilaufträgen.
Also mach dies und dies und dies und dies und bevor du dies machst,
musst du das gemacht haben und so weiter.
Jeder dieser Teilaufträge wäre dann eine Folge des
Betriebssystemkommandos und die nötigen Betriebsmittel.
Also ein paar Sachen, die jetzt gemacht werden müssen, zusammen mit
der Angabe, was der eigentlich braucht.
Also ich brauche die Tastatur oder ich brauche den Prozessor, ich
brauche so viel Speicher und so weiter.
Okay, und jetzt ist die Frage, in welcher Art und Weise so eine
Rechenanlage, also ein Prozess, ja überhaupt eine Rechenanlage, diese
Aufträge abarbeitet.
Und da gibt es verschiedene mögliche Arten, auf die ich kurz eingehen
möchte, um Ihnen zu zeigen, was können denn so Ziele sein und auch was
ist historisch, wie ist das historisch gewachsen.
In der Realität haben Sie meistens keine, nicht nur genau einen dieser
Betriebsarten, sondern Sie haben immer so einen Kompromiss.
Sie müssen sich entscheiden, was ist denn jetzt wichtig und was ist
nicht so wichtig.
Fangen wir an mit dem Stapelbetrieb.
Am Anfang, die ersten Rechner waren sehr, sehr teuer.
Das heißt, das oberste Ziel war, eine möglichst optimale Auslastung
der Rechner zu gewährleisten.
Es war völlig egal, wenn der Benutzer, der irgendwas berechnet haben
wollte, wenn dieser Job erstmal irgendwie eine Woche warten musste.
Weil das entscheidende Kriterium einfach war, den Rechner auszulasten.
Und da hat man sich überlegt, das macht man am besten in diesem Batch
-Mode, im Stapelbetrieb.
Da ist die Idee, dass die ganzen Jobs vor Übergabe an die Rechenanlage
komplett definiert sind, also so ein interaktiver Ablauf ist natürlich
nicht möglich, weil ich ja gar nicht genau weiß, wann der Job
ausgeführt wird.
Ich muss also alles in einem Block übergeben.
Klar, ich kann dann natürlich auch nicht garantieren, in welcher
Reihenfolge und wann diese Aufträge fertig sein werden.
Heutzutage verwendet man das eigentlich kaum noch, weil die Rechenzeit
sehr viel billiger geworden ist und das Teure jetzt die Zeit der
Nutzer ist.
Also man möchte eigentlich die Nutzer möglichst schnell bedienen.
Und wenn dann der Prozessor halt nicht super toll ausgelastet ist,
dann ist das nicht so schlimm.
Es gibt noch vereinzelte Anwendungen wie Lohn- und Gehaltsabrechnungen
oder irgendwelche ganz großen wissenschaftlichen Berechnungen, wo so
ein Batch-Mode tatsächlich auch noch benutzt wird.
Also wenn Sie auf dem Parallelrechner hier rechnen wollen, auf der SB2
zum Beispiel, da laufen immer große wissenschaftliche Berechnungen und
da ist es so, dass Sie das im Prinzip in eine Warteschlange stecken
und dann irgendwann das Ergebnis zurückbekommen.
Das wäre so ein Batch-Betrieb.
Ich sagte schon, die Hauptaufgabe ist dann die Maximierung des
Durchsatzes, also die Anzahl der bearbeiteten Aufträge pro
Zeiteinhalt.
Multiprogrammbetrieb oder mehr Prozessbetrieb, wie man eigentlich
besser sagen sollte, ist dann die Idee, dass nicht nur ein Programm
läuft, sondern dass mehrere Programme gleichzeitig laufen sollen.
Dann muss man die verschiedenen Prozesse irgendwie ineinander
verzahnen.
Das heißt, jeder kriegt immer wieder ein bisschen Rechenzeit und das
heißt natürlich, man muss das verwalten, man muss den aktuellen
Prozess dann immer stoppen, man muss all die Informationen, die der
gerade braucht, irgendwo abspeichern, muss den neuen Prozess
reinladen, dem die ganze Information geben, dann darf der ein bisschen
rechnen, dann wird er wieder gestoppt und so weiter.
Das Betriebssystem oder die Hauptaufgaben sind dann hier die Zuteilung
der Betriebsmitteln.
Also man muss sich überlegen, wer darf jetzt als Nächster rechnen und
wie lang.
Man muss die Möglichkeit haben, Prozesse zu aktivieren und zu
blockieren und man muss sie natürlich auch gegenseitig voneinander
isolieren, dass nicht einer auf die Daten des anderen zugreift.
Vorteil?
Ja, bessere Ausnutzung der Betriebsmittel einer Rechenanlage, wenn man
so Dinge hat wie langsame Ein-Ausgabe oder wenn man eben
unterschiedliche Teile des Prozessors hat für Integer und Floating
-Point -Operationen oder sowas, dann kann es helfen, unterschiedliche
Sachen gleichzeitig auszuführen.
Die Idee ist hier, dass man auch wieder Pipelining-Ansätze verwendet.
Wenn ich also Eingabe, Ausgabe irgendwie vom Prozessor trennen kann,
dann kann ich, wenn ich Prozesse habe, die eben hier bestehen aus
Eingabe, Verarbeitung und Ausgabe, wenn ich die nicht alle
nacheinander ausführe, sondern dieses verzahne, dann kann ich das hier
so wie hier zusammenschieben und dann spare ich natürlich Rechenzeit,
weil während der erste Prozess verarbeitet wird, kann schon die
Eingabe des zweiten Prozesses laufen und so weiter und so fort.
Also letzte Woche kam ein Diplomant zu mir und meinte, wie kann denn
das sein?
Er schreibt für seine Diplomarbeit, hat er eben ein
Simulationsprogramm geschrieben und hat eben festgestellt, wenn er
jetzt einen Testlauf macht, dann dauert der so und so lang und wenn er
zwei Testläufe gleichzeitig laufen lässt, dann dauert das nicht
doppelt so lang, sondern nur anderthalb mal so lang.
Und das ist genau dieser Effekt.
Ein Testlauf hat eben viele Eingabe-Ausgabe-Funktionen und wenn er die
zwei gleichzeitig laufen lässt, dann kann dieses Multiprozesssystem
die so ineinander verschieben, dass sich das gut ergänzt und dann habe
ich eben Zeit gespart.
Hier steht dann, wie man die Gesamtzeit schätzen kann.
Okay, wenn ich zeitlich nicht verzahnt habe, habe ich gerade die
Summe.
Wenn ich zeitlich verzahnt habe, steht hier das Maximum.
Wobei das natürlich nicht wirklich die Gesamtzeit ist.
Also die Gesamtzeit für den Auftrag 2 zum Beispiel, die wäre ja hier
von hier bis da und hier von hier bis da, kann sogar länger werden.
Also wenn man von Start bis Ende rechnet, aber wenn man rechnet, in
welcher Frequenz werden die Aufträge abgearbeitet, dann ist eben das
Maximum hier wichtig.
Okay, Dialogbetrieb, das war im Prinzip wichtig, als wir diese Zeit
hatten mit den Großrechnern und den vielen Terminals.
Da habe ich eben Interaktion, das heißt der Auftrag ist nicht von
vornherein bekannt, sondern ich habe eine Dialogsitzung, ich muss auf
Eingaben reagieren können und kann eben deswegen keinen Batchbetrieb
machen.
Da gibt es zwei Möglichkeiten, entweder den Teilhaberbetrieb, alle
Benutzer verwenden dasselbe Programm.
Beispielsweise, wenn sie ein Reservierungssystem haben für das
Reiseprogramm, für ein Reisebüro, dann sind da sehr viele Reisebüros
angeschlossen und die benutzen alle gleichzeitig das gleiche Programm.
Oder Teilnehmerbetrieb, wenn eben jeder unterschiedliche Programme
benutzt.
Okay, Reise hatte ich schon angegeben als typische Anwendungen.
Die Hauptaufgabe ist dann ähnlich wie beim Multiprogrammbetrieb, dass
sie eben verschiedene Prozesse gleichzeitig laufen lassen können
müssen, dass sie die gegeneinander schützen müssen und so weiter.
Plus, hier ist jetzt wichtig, eine schnelle Bedienung der Benutzer.
Das heißt, sie wollen schnelle Antwortzeiten haben.
Der Benutzer ist dadurch, dass er im Dialogbetrieb vor dem Rechner
sitzt, nicht bereit, jetzt irgendwie länger zu warten, sondern wenn er
eine Taste drückt, dann will er den entsprechenden Buchstaben auch
möglichst gleich am Bildschirm sehen.
Echtzeitbetrieb ist noch was, was eben in bestimmten Anwendungen sehr
wichtig ist.
Wenn Sie beispielsweise ein Kraftwerk steuern und es tritt irgendein
Fehler auf, dann ist wichtig, dass dieser Fehler auch wirklich sofort
bearbeitet wird und sofort weitergeleitet wird.
Also Sie haben hier zusätzlich Zeitrestriktionen für die Bearbeitung
eines Auftrags.
Bestimmte wichtige Dinge müssen die Möglichkeit haben, den Lauf zu
unterbrechen, den üblichen Ablauf und müssen sagen, hier jetzt komme
ich, jetzt bin ich dran und ich muss in der Zeit fertig sein, fertig
bearbeitet sein.
Das hat einfach für sicherheitskritische Anwendungen große Bedeutung.
Okay,
das hatte ich eigentlich alles schon gesagt.
Client-Server-Betrieb, das ist in letzter Zeit eben, hat es an
Bedeutung gewonnen.
Da werden zentrale Systemfunktionen wie die Benutzerverwaltung, also
das Einloggen und welche Rechte ein Benutzer hat, die Dateiverwaltung,
Mail -Server, WWW-Server und so weiter nicht auf Ihrem Rechner
ausgeführt, sondern von einem zentralen Server bereitgestellt.
Und die Idee ist dann, dass jeder Client, also jeder angeschlossene
Rechner, sogenannte Remote Procedure Calls absetzen kann, also er kann
eine Funktion auf dem Server aufrufen und kann in dieser Zeit, während
der Server dann die entsprechende Aufgabe bearbeitet, selber andere
Aufgaben bearbeiten.
Da gibt es jetzt, also der Standardfall ist so, wie Sie ihn
wahrscheinlich auch kennen, Sie haben hier verschiedene Clients und
Sie haben einen Mail-Server und einen Web-Server zum Beispiel, die
dann diese entsprechende Funktion für alle Clients ausführen.
Es gibt einen Spezialfall, nämlich wenn jeder Rechner sowohl Client
als auch Server ist, dann nennt man diese Rechner auch Peers, das ist
groß bekannt geworden unter dem Namen Peer-to-Peer-System und da eben
insbesondere, das ist ganz bekannt geworden durch Napster, also durch
diese Musiktauschbörsen, wobei man sagen muss, Napster ist eigentlich
gar kein wirkliches Peer-to-Peer-System gewesen oder nicht so richtig,
denn es gab immer noch einen zentralen Server.
Also was Napster gemacht hat, war im Prinzip, wir haben hier sehr
viele Clients gehabt und die waren alle verbunden mit einem zentralen
Server und wenn Sie jetzt ein Musikstück gesucht haben, dann haben Sie
eine Anfrage gestellt an den Server, der Server hat Ihnen gesagt, das
liegt auf dem und dem Rechner und dann haben Sie eben die tatsächliche
Musikdatei direkt bei diesem Rechner angefragt.
Also dieser Teil, wo Sie die Musik tatsächlich von einem anderen
Rechner holen, das wäre das typische Peer-to-Peer, dieser Teil, wo Sie
über einen Server eigentlich erstmal anfragen, wo Sie die Datei
bekommen und so weiter, das ist nicht so typisch Peer-to-Peer.
Aber egal, also Peer-to-Peer ist zur Zeit ganz groß in Mode und wenn
Sie einen Forschungsantrag genehmigt haben wollen, dann sollten Sie
Peer -to-Peer reinschreiben.
Ob das jetzt Sinn macht oder nicht, ist egal.
Okay, wenn Sie so ein System haben, haben Sie natürlich ein bisschen
andere Aufgaben noch für das Betriebssystem.
Sie müssen solche entfernten Prozeduraufrufe gut abwickeln können, das
heißt diese Übertragung von diesen Remote Procedure Calls und da gibt
es auch wieder so eine Schichtenhierarchie.
Heutige Systeme haben eben üblicherweise zwei Schichten, viele sogar
drei Schichten, sogenannte Multi-Tier-Architektur.
Wir haben hier oben die Kommunikationsschicht, die also Empfangen und
Versenden von Daten übernimmt.
Dann haben wir die Maklerschicht, die dann die Aufträge an das
entsprechende Programm weiterreicht, zum Beispiel über Corbar.
Und dann haben wir unten die Service-Schicht, wie Datenbank, Server
oder Ähnliches, wo dann tatsächlich die entsprechenden Dienste
ausgeführt werden.
Dieser Teil Kommunikationsschicht und Maklerschicht ist auch unter dem
Namen Middleware bekannt, wenn Sie das vielleicht schon mal gehört
haben.
Hier wäre so ein Beispiel.
Also hier haben wir einmal den Monolith, so wie es der Standard ist.
Standard, wenn Sie eben keinen Server-Client haben, sondern alles auf
einem Rechner, haben Sie das User-Interface hier, die eigentliche
Programmlogik und die Datenbank, alles auf Ihrem einzelnen Rechner.
Diese Zwei-Tier-Architektur, da würden Sie hier eine Trennung
einführen.
Also die Datenbank würde abgespeichert und würde auf einen anderen
Server verlagert.
Und in dieser Drei-Tier-Architektur haben Sie eben zwei solche
Grenzen.
Sie haben hier im Prinzip so die Frontends, mit denen Sie gewisse
Anfragen stellen.
Diese Anfragen stellen Sie an ein ganzes Netzwerk von Application
-Servers und die gucken dann, wer kann jetzt diesen Dienst am besten
bereitstellen und holen sich die entsprechenden Daten zum Beispiel aus
der Datenbank.
Also hat man so eine Dreischicht-Architektur.
Okay, damit hätten wir wieder Viertel vor.
Ich lasse all diejenigen, die Hunger haben, in die Mensa gehen.
Ja, ich sagte Ihnen schon, dass diese Einteilung in diese
verschiedenen Betriebsarten mehr zur Illustration da ist.
Was für verschiedene Ziele kann man verfolgen und auch zum Teil eben
historisch gewachsen ist, weil man eben unterschiedliche Rechner
hatte, unterschiedliche Prioritäten hatte.
Heutzutage kann man das nicht mehr so ganz klar trennen.
Unter Umständen haben Sie verschiedene Betriebsarten nacheinander,
also tagsüber etwa Dialogbetrieb und nachts am Wochenende oder am
Wochenende, wenn eben kein direkter Dialog stattfindet, könnten Sie
Stapelbetrieb haben.
Oder Sie wechseln einfach verschiedene Ziele.
Das heißt, Sie haben verschiedene Betriebsarten im Prinzip
gleichzeitig vorhanden.
Sie haben konkurrierende Anforderungen.
Sie haben Leute, die einfach Badges abschicken, die eigentlich im
Hintergrund laufen sollen, also große Rechentops, wo es auch nicht
genau darauf ankommt, wann die jetzt fertig werden.
Sie haben andere interaktive Sessions laufen und das alles
gleichzeitig.
Und das Betriebssystem muss sich jetzt überlegen, wie bringt es diese
konkurrierenden Anforderungen unter einen Hut.
Dazu schauen wir uns nochmal genau an, was ist eigentlich ein Prozess?
Wir hatten ja Kapitel 8 glaube ich schon mal Prozess definiert.
Also eine zeitliche Folge von Aktionen, die zu einer funktionellen
Einheit zusammengefasst sind.
Charakterisiert durch, wie hier aufgeführt, das durchzuführende
Programmstück, die Daten, die dieser Prozess braucht und der
Ausführungskontext.
Also so Dinge wie eben Adressraum und Kontrollfluss, also an welcher
Stelle im Programmtext bin ich denn jetzt gerade.
Zusätzlich haben wir diese Threads, die sogenannten leichtgewichtigen
Prozesse, die zwar auch jeweils einen eigenen Kontrollfluss haben,
aber eben einen gemeinsamen Adressraum.
Der Vorteil bei diesen Threads war, dass man schneller zwischen denen
hin und her schalten kann.
Und Sie erinnern sich auch, dass man, wenn man eben solche Threads
hat, eine bessere Prozessorauslastung durch symmetrisches
Multithreading erreichen konnte, bin ich in Kapitel 8 eingegangen.
Der Nachteil ist eben, oder gleichzeitig Vor- und Nachteil ist der
gemeinsame Speicherbereich.
Vorteil, weil Sie eine schnellere Kommunikation haben, wenn Sie auf
die gleichen Variablen zugreifen können.
Nachteil, weil eben es zu Konflikten kommen kann.
Okay, jetzt sagen wir mal, wir haben so verschiedene Prozesse.
Das heißt, wir haben eigentlich eine Warteschlange von Prozessen, die
abgearbeitet werden können.
Jetzt gibt es verschiedene Zustände, in die ich so einen Prozess
bringen kann.
Zunächst mal werde ich den Prozess initiieren, das heißt, ich mache
den Betriebssystem bekannt und ich lege ihn in den Zwischenspeicher,
aber er darf noch nicht abgearbeitet werden.
Zum Beispiel deswegen noch nicht abgearbeitet werden, weil er noch gar
nicht alle Betriebsmittel hat.
Wenn ein Prozess alle Betriebsmittel hat, also zum Beispiel Zugriff
auf den Drucker oder auf die Tastatur oder solche Dinge, mit Ausnahme
des Prozessors, weil der Prozessor eben normalerweise die kritische
Komponente ist, dann bezeichnet man den Prozess als bereit.
Kriegt er den Prozessor auch noch, dann ist er aktiv, da tut er
tatsächlich was und wird ausgeführt und es kann eben immer nur maximal
ein Prozess in diesem Zustand sein.
Dann gibt es noch die Möglichkeit, dass der Prozess nicht alle
Betriebsmittel zur Verfügung hat, zum Beispiel, oder dass er auf eine
Eingabe wartet oder ähnliches, dann ist er blockiert.
Kann eben im Augenblick, selbst wenn er den Prozessor bekommen würde,
nicht ausgeführt werden.
Und letztendlich, wenn er dann fertig ist, dann terminiert er eben.
Und die Frage ist jetzt, wie kommt man von einem Zustand in den
anderen?
Das wären die möglichen Zustände.
Im Prinzip habe ich hier jeweils Warteschlangen.
Das deute ich mal an durch so eine Schlange hier.
Und hier kann eben nur ein Prozess drin sein.
Also ich habe hier eine Schlange von Prozessen, die initiiert sind.
Die können bereit werden, genau dann, wenn die Auftragssteuerung, also
der Jobscheduler hier entscheidet, okay, aus diesen initiierten
Prozessen, da nehme ich jetzt diesen neu raus, der passt gut zu den
anderen.
Also er versucht da eine gute Auslastung oder einen guten Mix zu
erreichen, zwischen Prozessor-lastigen und Eingabe-Ausgabe-intensiven
Prozessen, so dass man eben diese Verzahnung machen kann.
Und dass der eine eben eine Ausgabe machen kann, während der andere
rechnet.
Also das entscheidet der Jobscheduler, welchen er von den Initiierten
dann in die Warteschlange der bereiten Prozesse einreiht.
Okay, wenn dann der Prozessor frei wird, dann kann ein neuer Prozessor
aktiv werden, kann aus der Menge der Bereiten zum aktiven Prozessor
werden.
Er bekommt den Prozessor zugeteilt, die Komponente, die das hier
macht, ist der CPU-Scheduler.
Und der verwendet als Werkzeug eben den Prozess-Umschalter, der dann
zwischen den verschiedenen Prozessen umschaltet, den Dispatcher.
Und dieser Dispatcher muss natürlich jetzt alle aktuelle
Informationen, also an welcher Stelle im Programmablauf ist eigentlich
der jetzt gerade stehen geblieben und wie ist die Variablenbelegung
und so weiter, das muss er alles irgendwie abspeichern.
In einem sogenannten Prozess-Kontrollblock, der dann in einem
bestimmten Hauptsprecher-Bereich abgelegt wird.
Okay, es kann natürlich jetzt auch sein, dass Sie einen aktiven
Prozess haben, der nicht zu Ende laufen darf, sondern der unterbrochen
wird, einfach weil er eine gewisse Zeitschranke erreicht hat oder weil
ein dringenderer Prozess gekommen ist, der jetzt den Prozessor
braucht.
Das heißt, es gibt die Möglichkeit, dass der Prozess von aktiv nach
bereit wandert.
Und dann gibt es hier noch dieses Blockiert.
Es sagt ja schon, dass der Prozess dann blockiert wird, wenn er
beispielsweise eine langsame Ausgabeoperation angestoßen hat oder
zusätzliche Betriebsmittel braucht, die gerade nicht verfügbar sind.
Dann kann ja der Prozessor gerade sowieso nicht daran weiterarbeiten.
Das heißt, dieser Prozess wird aus dem aktiven Status rausgeschmissen
in den blockierten Status und ein bereiter Prozess kann dann
bearbeitet werden und wird aktiv.
Der Prozess wird natürlich wieder bereit, wenn das entsprechende
Ereignis eingetreten ist, also wenn der Benutzer seine Eingaben
gemacht hat oder wenn das Betriebsmittel, das er braucht, frei
geworden ist.
Dann könnte er wieder bearbeitet werden, kommt also wieder in die
Schlange der bereiten Prozesse.
Und ganz am Schluss natürlich, oder wenn ein Fehler aufgetreten ist,
dann endet dieser Prozess und wandert von aktiv nach terminiert.
Entsprechend werden natürlich die entsprechenden Prozesskontrollblocks
gelöscht, weil man die ja nicht mehr braucht.
Okay, das sind also so die verschiedenen Zustände, in denen ein
Prozess sein kann.
Und die große Frage ist eigentlich immer, jetzt habe ich hier mehrere
Prozesse, die bereit sein können.
Welcher darf als nächster aktiv werden und für wie lange darf dieser
aktiv werden?
Und das schauen wir uns jetzt im nächsten noch an.
Also die Frage der Zuteilung von Rechenzeit.
Wir haben eine Menge von Prozessen, die alle bereit sind und darauf
warten, dass der Prozessor frei wird.
Da gibt es jetzt verschiedene Ziele, die man verfolgen kann.
Man könnte sagen, der Prozess soll möglichst nicht lange warten.
Oder die CPU soll maximal ausgelastet werden.
Oder die Antwortzeit soll minimiert werden.
Oder ich will möglichst gerecht, wobei man eben gerecht definieren
muss, zuteilen.
Und dabei muss man immer auch beachten, dass natürlich dieses
Zuteilungsverfahren sehr einfach sein muss.
Das Betriebssystem muss entscheiden, welcher Prozess denn jetzt als
nächstes drankommt.
Diese Entscheidung braucht selber Rechenzeit.
Und wenn Sie jetzt das supertolle Zuteilungsverfahren haben, das aber
50 % Ihrer Rechenzeit aufbraucht, dann muss man sich fragen, bringt es
das wirklich?
Ist es nicht besser, ein ganz einfaches Zuteilungsverfahren zu haben,
das nur ein halbes Prozent der Rechenzeit braucht oder noch viel
weniger?
Und Sie sind dann vielleicht nicht unbedingt immer fair oder Sie haben
nicht die absolut optimale Lösung, aber Sie haben einfach sehr viel
mehr Rechenzeit zur Verfügung.
Also das ist zusätzlich zu den Sachen, die man sich beim Scheduling im
Operations Research vielleicht anschaut, eben hier eine Besonderheit,
dass das Zuteilungsverfahren selbst auch Rechenzeit und
Prozessorleistung braucht.
Okay, also das erste Prinzip wäre deswegen, dass man sagen will,
möglichst viel Prozessorleistung für die Benutzerprozesse verwenden
und man will das allereinfachste Zuteilungsverfahren haben, was man
sich denken kann.
Und das wäre First come, first served.
Also man hat eine Warteschlange hier und die Aufträge kommen hier rein
und werden hier der Reihenfolge nach abgearbeitet.
Das ist klar, da habe ich natürlich viele Dinge, die ich brauche, wie
dass ich, wenn ein Auftrag mit hoher Priorität kommt, dass ich den
bevorzugen kann oder sowas, habe ich da einfach nicht.
Die andere Möglichkeit wäre, dass ich eine
Prioritätsgestaltungszuteilung habe, dass jeder Prozess eine Priorität
besitzt und wir immer den Prozess aktivieren, der die höchste
Priorität besitzt.
Das ist auch nicht unbedingt ganz so einfach, weil Sie haben unter
Umständen verschiedene Prozesse mit der gleichen Priorität.
Also ein praxisrelevanteres, zwar etwas komplizierteres Verfahren,
aber praxisrelevanter ist, dass Sie die Prozesse in Klassen einteilen,
unterschiedlicher Priorität und dass Sie eben innerhalb einer Klasse
dann zum Beispiel gemäß First come, first served bedienen und die
Klasse eben nur Rechenzeit bekommt, wenn alle Klassen mit höherer
Priorität schon abgearbeitet wurden.
Also hier wäre so ein Beispiel.
Die höchste Priorität haben natürlich Betriebssystemprozesse, denn
wenn das Betriebssystem irgendwie nicht läuft, dann läuft gar nichts.
Dann haben eine hohe Priorität interaktive Prozesse, weniger hoch zum
Beispiel Übersetzungsprozesse, Editierprozesse und die niedrigste
Priorität haben solche Batch-Prozesse.
Das wären eben so Prozesse, die ich einmal losschicke und wo mir dann
egal ist, wann das passiert.
Die alle Daten haben, wo ich dann nach Hause gehen kann und einfach am
nächsten Morgen gucken will, was ist rausgekommen.
Okay, das nächste...