| Axel Rogat |
| Betriebssysteme und betriebssystemnahes Programmieren |
|   |
1.1: Was ist ein Betriebssystem?
| Kapitel 1 |
1.3: Beispiele 
|
|   |
|   | 1.2 Historische Entwicklung der Betriebssysteme |   |
|   |
Hier haben seit der Entwicklung der ersten Rechnersysteme besonders viele
Veränderungen stattgefunden, mehr als in irgendeinem anderen Gebiet.
Die Hardware wurde mit enormer Geschwindigkeit verbessert, wodurch sich
völlig veränderte Einsatzmöglichkeiten ergeben haben. Dadurch
wiederum wurden allmählich höhere Anforderungen an die Leistung des
Gesamtsystems gestellt, die letztendlich die Entwicklung leistungsfähigerer
Hardware erzwangen, etc.
Nach der Konfiguration wurde der Rechner gestartet. Die Ausgabe der
Ergebnisse erfolgte dann durch Lichtanzeigen oder über Papierband, d.h. die
CPU übernahm diese Art von I/O selbst.
Zum Debuggen interpretierte man dann die gelieferten Ergebnisse, entwarf
Programmteile neu auf Papier und erstellte eine angepaßte
Rechnerkonfiguration. Eine Interaktion mit dem Rechner während des
Programmlaufs war nicht (oder nur sehr schwer) denkbar.
Die Programme mußten zunächst natürlich in der
Maschinensprache des jeweiligen Rechners geschrieben werden. Etwas
später wurden dann die ersten höheren Programmiersprachen
entwickelt, von denen sich FORTRAN am schnellsten und weitesten
verbreitete, später im kommerziellen Bereich auch COBOL. Dadurch
wurde die Programmentwicklung schneller und (etwas) sicherer.
Dadurch daß die Hardware zuverlässiger wurde (Transistoren) und das
Programmieren einfacher, wurden die Rechner allmählich auch
kommerziell einsetzbar, wenn auch zunächst nur in großen
Betrieben und Universitäten.
Der Job des Computer-Bedieners teilte sich nun auf in zwei:
Die Karte ist in 12 Zeilen zu je 80 Spalten aufgeteilt. In jedes so
entstehende Feld kann ein rechteckiges Loch gestanzt werden.
In jeder Spalte wird ein Zeichen oder bei Binärdaten ein binäres
Datum dargestellt.
Lösung 1: Batch-Systeme
Die Compiler werden jeweils von einer bestimmten Bandmaschine geladen. Der
Operator muß das Band jeweils per Hand austauschen und den neu
benötigten Compiler einlesen lassen. Durch die Job-Sammlung kann hier Zeit
gespart werden - der Compiler muß nicht für jeden Job gewechselt
werden.
Lösung 2: Automatic Job Sequencing und Monitore
Bei herkömmlichem Operator-Betrieb war der Kartenstapel, den der Benutzer
dem Operator übergab, aufgeteilt in Karten mit Programmen
(FORTRAN-Quellcode) und numerischen Daten. Was wann einzulesen war,
und was damit zu geschehen hatte, entschied der Operator.
Um nun die Daten in den einzelnen Jobs bei Batch-Betrieb günstig
zu organisieren, wurden spezielle neue Karten-Typen eingeführt.
Die neuen Karten dienten zur Beschreibung des Zwecks der
jeweils nachfolgenden Karten (" Kontroll-Karten"). Als Kennzeichnung
enthielten sie als erstes Zeichen (also in der ersten Spalte) meistens ein
Dollar-Zeichen $ oder ein unbelegter Codewert (wie 7-9). Nur IBM
benutzte zwei Spalten //. Danach folgte jeweils die
Spezifikation der Karte - in der Art eines kurzen Befehlsnamens:
Die Interpretation der Kontroll-Befehle geschah im Großrechner. Ein
entsprechendes kleines Programm mußte dafür immer
ausführbereit im Speicher liegen. Dieses Programm wurde
"Monitor" (oder "resident monitor") genannt. Es stellt damit
also das erste Betriebssystem der Geschichte dar (genauer einen
Betriebssystem-Kern).
Der Monitor wird direkt nach dem Start in den Speicher geladen und
bleibt von da an unverändert dort. Er besteht im wesentlichen aus
folgenden Teilen:
Die Kontroll-Karten bzw. -Befehle wurden oft auch zu einer (sehr kleinen)
Batch-Sprache ausgebaut. Beispielsweise bot JCL (Job Control Language)
von IBM die Ausführung von Befehlen in Abhängigkeit von Bedingungen,
etc. Die heutigen Skript-Sprachen sind Abkömmlinge dieser einfachen
Batch-Sprachen.
Lösung 3: Offline-Betrieb
Eine wesentliche Effizienzsteigerung ergab sich später durch
den sogenannten "Offline-Betrieb". Zusammenpassende Jobs (mit
sich überschneidenden System-Ressourcen wie Compiler) werden
zunächst auf einem gesonderten kleinen Rechner (im "Eingaberaum") von
Karten auf Magnetband übertragen (" satellite processing"). Sie
können danach direkt hintereinander auf dem eigentlichen Großrechner
ausgeführt werden.
Die IBM 1401 wurde auch alleine genutzt für einfache Datenspeicherung in
Banken und Versicherungen.
Im günstigsten Fall gibt es mehrere Vor- und Nachrechner, so daß der
teure Großrechner möglichst lückenlos ausgelastet sein kann.
Eine zusätzliche Verbesserung des Durchsatzes kann im Zusammenhang mit
Ein-/Ausgabegeräten bereits durch einfaches Puffern erreicht werden:
Die Software für diesen Pufferungs-Mechanismus wird im Monitor oder im
entsprechenden Geräte-Treiber untergebracht. Es liegt also eine weitere
Zwischenstufe an Virtualisierung vor -- es wird nicht unbedingt direkt die
wirkliche Treiber-Routine angesprochen, sondern die zwischengeschaltete
Pufferungs-Routine.
Es gibt eine wichtige Hardware-Voraussetzung für das Puffern, nämlich
einen Interrupt-Mechanismus in der CPU:
Die CPU muß hardwaremäßig vom Peripherie-Gerät
unterbrochen werden können. Sie nimmt dann das nächste Datum (oder
Datenpaket) vom Eingabegerät an und schreibt es in den Puffer, bzw.
liefert dem Ausgabegerät das nächste Datum (Datenpaket) aus dem
Puffer. Wenn das geschehen ist, kehrt die CPU zu ihrer ursprünglichen
Tätigkeit zurück.
Das Unterbrechen geschieht direkt durch ein Signal ("Interrupt") an
einem CPU-Anschluß. Es gibt im allgemeinen mehrere Signale oder eine
zusätzliche Möglichkeit, Signale durchzunumerieren. Die CPU schaut
dann in einer Tabelle nach, an welcher Stelle im Hauptspeicher die zum
empfangenen Signal gehörige Behandlungsroutine steht und führt sie
aus.
Auf diese Weise können Schwankungen in der Lese-/Schreib- bzw.
Berechnungsgeschwindigkeit ausgeglichen werden. Bei den meisten Programmen
wird allerdings die Ein-/Ausgabe der langsamere Teil sein, so daß Puffern
nur einen (vergleichsweise) geringen Effekt auf die CPU-Ausnutzung hat.
Insgesamt läßt sich über die Rechnersysteme dieser Zeit sagen,
daß sie vergleichsweise gut ausgenutzt werden konnten bei rechenintensiven
Aufgaben, also in Universitäten, Rechenzentren, etc. Im kommerziellen
Betrieb, wie bei der Datenverwaltung in Banken und Versicherungen,
überwiegt meist der I/O-Anteil an der Gesamtzeit, und das System wird
nicht gut ausgenutzt.
Ein wichtiger Nachteil des Batchings muß erwähnt werden: die Benutzung
des Rechners ist nicht mehr interaktiv:
In den 60er Jahren gab es viele Entwicklungen im Hardware-Bereich, die
direkte Auswirkungen auf den Rechnerbetrieb hatten:
1. Spooling
Spooling wäre sicher schon eher möglich gewesen, wurde aber erst durch
die Einführung der Plattenspeicher sinnvoll.
Bei Spooling liegt meist beim Beendigung eines Jobs nicht nur ein Nachfolgejob,
sondern mehrere auf Platte vor (" job pool"). Der Monitor kann also
einen Nachfolgejob auswählen.
Beispielsweise kann abgeschätzt werden, ob ein Job rechenintensiv ist oder
nicht. Wenn ein Job vermutlich längere Zeit keine Ausgabe tätigt, ist
es günstig, ihn bereits laufen zu lassen, während immer noch die
Ausgabe des vorigen Jobs läuft.
Ein-/Ausgabe und Berechnungszeiten können sich noch besser überlappen,
d.h. die CPU kann noch besser ausgelastet werden.
IBM "erfand" mit dem System/360 die "Kompatibilität". Dabei
handelte es sich nicht um einen Rechner, sondern um eine ganze Familie von
Rechnern, die ein großes Leistungsspektrum abdeckte:
OS/360 wurde gigantisch kompliziert und entsprechend fehleranfällig.
Als Reaktion auf Beschwerden von Kunden wurden Fehler in der nächsten
Version möglichst schnell "herausgehackt" - wobei mindestens genauso
viele neue Fehler hineingehackt wurden. Bereits die erste Version wurde
ausgeliefert, obwohl bereits Hunderte von Fehlern bekannt waren!
3. Multiprogramming
Die wichtigste Neuerung, die zuerst in OS/360 implementiert war, war aber
das "Multiprogramming", später (nachdem der Begriff "Task"
entwickelt worden war) auch "Multitasking".
Die Neuerungen in den Vorgänger-Systemen zielten alleine darauf, den
Durchsatz bei der CPU zu maximieren. Durch die fehlende Interaktivität
verlängerte sich dagegen die Programm-Entwicklung (lange Antwortzeit
auf einen Job).
In der Anfangszeit der IC-Technik wurde die Hardware aber sehr schnell
wesentlich billiger - und irgendwann gewannen die Löhne der
menschlichen Bediener an Bedeutung.
Die Idee des Job Pools (vom Spooling) wurde ausgeweitet, und der Pool von
der Platte in den Hauptspeicher verlegt. Der Hauptspeicher, der nicht
fest zum Betriebssystem gehörte, wurde in mehrere Teile aufgeteilt, und
in jeden Teil wurde ein Job geladen.
Um die Aufteilung durchführen zu können, mußte Hardware zur
Beschränkung des erlaubten Adreßbereichs vorhanden sein.
Außerdem war
eine automatische Adreß-Umsetzung sinnvoll, damit ein Programm in
jedem beliebigen physischen Speicherbereich unverändert lauffähig war.
Das System/360 gehörte zu den ersten Systemen, die diese
Hardware-Voraussetzungen erfüllten.
Nachdem ein Job vom Monitor die CPU-Kontrolle übernommen hatte, behielt
er sie so lange, bis er wegen I/O-Operationen gezwungen war, zu warten.
Für diese Operationen mußte er ja ohnehin den Monitor aufrufen - und
dieser hatte nun die Möglichkeit, zu entscheiden, lieber einem
rechenintensiven Job den Vorrang zu geben.
Die Umschaltung zwischen den Jobs erfolgte also nicht kontinuierlich
(per Zeitscheiben-Verfahren), sondern nur bei Wartezeiten des jeweils
aktiven Prozesses. Diese einfachere Art von Multitasking nennt man auch
" non-preemptive" (das Zeitscheiben-Verfahren heißt
"preemptive").
Beispiel: Um die mögliche verbesserte CPU-Ausnutzung zu
demonstrieren, betrachten wir als einfache Situation zwei Prozesse, die
zwischendurch immer wieder auf Eingaben warten müssen.
In dieser Zeit sind sie "idle" (untätig). Unten sind die
Arbeitszeiten mit durchgezogenen Linien, die Idle-Zeiten mit Punkten
dargestellt.
In einem System ohne Multitasking sind die Prozesse nur Programme, die
nacheinander ausgeführt werden. Die Gesamt-Laufzeit ist die Summe der
Einzel-Laufzeiten der Prozesse, inklusive ihrer Idle-Zeiten.
Auch bei Multitasking ohne Zeitscheiben ergeben sich Verbesserungen. Wenn ein
Prozeß warten muß, wird der andere vorgelassen.
Die Pfeile deuten den Wechsel der CPU-Kontrolle an.
4. Timesharing
Timesharing ist im wesentlichen Multiprogramming mit mehreren Benutzern,
die gleichzeitig an mehreren Terminals arbeiten können.
Die meisten Jobs werden "fast immer" auf Benutzer-Eingaben warten
müssen. In dieser Zeit können dann die Jobs laufen, die sich gerade
in einer rechenintensiveren Phase befinden.
Im Zusammenhang mit Timesharing wurden wichtige Konzepte entwickelt, die
bis heute eher noch an Bedeutung gewonnen haben:
Eine echte Verzeichnis- Hierarchie, also beliebig tief verschachtelte
Unterverzeichnisse für jeden Benutzer, wurde erstaunlicherweise bei
vielen Systemen nicht oder erst nachträglich viel später
implementiert.
Die entsprechenden Betriebssysteme mußten sich jetzt nicht an Operatoren,
sondern an reine Bediener ohne tiefe Rechner-Kenntnisse wenden. Dadurch
wurden sie zwangsweise benutzerfreundlicher.
Durch das Wegfallen der Mehrbenutzer-Struktur wurde die Hardware zunächst
wieder vereinfacht (und dadurch verbilligt) - beispielsweise wurden Memory
Protection und privilegierte Befehle wieder fallengelassen. Entsprechend wurden
auch die Betriebssysteme vereinfacht, wobei leider auch die
Mehrprozeß-Elemente eliminiert wurden.
Mit zunehmender Integration und Verbilligung der Hardware - und durch
den Ruf nach Benutzer-Komfort - fanden diese Elemente aber nach und nach
wieder Eingang in Hardware und Betriebssysteme.
1.2.1 Zu Beginn: nackte Rechner
Die Rechner ganz zu Beginn des Computer-Zeitalters waren sehr groß und
extrem teuer. Sie wurden per Hand aus einer Unzahl von Röhren
zusammengebaut und waren entsprechend anfällig. Alle paar Stunden
mußte eine defekte Röhre durch spezielles Personal ausgetauscht
werden. Diese Rechner waren natürlich völlig experimentell und
konnten noch nicht kommerziell eingesetzt werden. Die Hauptaufgaben waren rein
numerische komplexe Berechnungen.
1.2.2 Röhren --> Transistoren
In der Zeit, als Röhren allmählich durch Transistoren ersetzt wurden,
entwickelten sich die Rechner auch zu "universellen Maschinen". Sie
wurden also nicht speziell für eine Aufgabe gebaut oder konfiguriert,
sondern erhielten ihre Aufgabe in Form eines Programms beschrieben.
Die Software wurde also aus der Hardware herausgelöst.
Die Eingabe erfolgte üblicherweise über Lochkarten, die Ausgabe
auf Papier oder (zur weiteren Verwendung) wieder auf Lochkarten. Häufig
benutzte (unveränderliche) Daten wurden auf Magnetband gespeichert,
beispielsweise Assembler, Compiler, Linker, Bibliotheken.
Kurzer Einschub: Format von Lochkarten
Eine Lochkarte stellt üblicherweise eine Zeile Programmtext (80 Zeichen)
oder entsprechend viele binäre Daten dar. Sie ist wie folgt aufgebaut:
Der übliche Ablauf bei der Enstehung eines Programms war folgender:
So wurde einiges an Zeit verschwendet. Der Operator lief zwischen
Kartenleser, -stanzer und Magnetbandmaschine hin und her. Die Kartenstapel
mußten letzendlich durch die CPU eingelesen werden; in dieser Zeit konnte
nicht gerechnet werden. Bei der Preislage der damaligen Rechner (und Operatoren)
kostete jede verschwendete Minute Tausende.
sobald der Rechner "frei" wird (vorheriger Job beendet):
Debuggen:
batch = Schub, Stoß, also hier: Zusammenfassung mehrerer
Befehle
Als erste Verbesserung wurden zusammenpassende Jobs gesammelt, beispielsweise
alle, die den FORTRAN-Compiler benötigen, alle, die den
COBOL-Compiler benötigen, etc.
Ein Job bestand nun also aus einem einzigen Kartenstapel, der intern durch
Kontroll-Karten strukturiert war. Die Zugehörigkeit der Daten zum
Auftraggeber ist durch die ID des Jobs gegeben. Die CPU kann nun
beliebig viele Jobs direkt hintereinander ausführen -- Kartenstapel
können miteinander verschmolzen werden. Die CPU startet so lange
automatisch neue Programme, wie sie entsprechende Karten erhält
("automatic job sequencing").
$JOB oben auf dem Stapel, Beginn des Jobs, ID, Benutzername, etc.
$END unter dem Stapel, Ende des Jobs, ggf. Wiederholung der ID
$FTN (oder $FORTRAN) -- Laden und Starten des
FORTRAN-Compilers (vom Band), das Programm steht auf den
nachfolgenden Karten bis zur nächsten Kontroll-Karte. Das übersetzte
Programm landet auf einem speziellen System-Band.
$COBOL Laden und Starten des COBOL-Compilers
$ASM Laden und Starten des Assemblers
$LOAD Zurückspulen des Systembands, Laden der erzeugten Daten
als Programm
$RUN Starten des geladenen Programms. Die Eingabe-Daten für das
Programm stehen auf den nachfolgenden Karten bis zur nächsten
Kontroll-Karte.
$LGO load-and-go, Kombination aus $LOAD und $RUN
$DATA Eventuell zusätzliche Markierung eines Bereichs als
(Eingabe-)Daten
Als sich diese System-Betriebsart mit Monitor mehr und mehr durchsetzte
und die Monitoren mehr Aufgaben übernahmen, bauten die Hersteller eine
spezielle Hardware-Unterstützung in die CPUs ein. Der Satz von
Maschinenbefehlen wurde zweigeteilt (" dual-mode instructions") in:
Typische Monitorsysteme der damaligen Zeit waren
FMS (FORTRAN Monitor System) und IBSYS (für die
IBM 7094). Erst später, als die Systeme ausgebaut wurden und der Name
Monitor ihnen nicht mehr ganz gerecht wurde, entwickelte sich allmählich
der Begriff Betriebsystem (Operating System wie in IBM OS/360, s.u.).
privilegierte Befehle: nur vom Monitor verwendbar
("Supervisor Mode")
Benutzer-Befehle: auch von Anwenderprogrammen verwendbar
("User Mode")
Voraussetzung für diese Aufteilung ist entsprechende Hardware, nämlich
kleine Rechner, die (im Vergleich mit dem Großrechner) rechnenschwach
sein dürfen, dafür aber auch wesentlich billiger sein müssen
("reader-to-tape"- und "tape-to-printer"-Maschinen).
Ein typischer Fall war:
Lösung 4: Puffern und Interrupts
1.2.3 Platten und integrierte Schaltungen
2. Rechner-Familien und Kompatibilität
Alle Mitglieder der Familie hatten aber dieselbe Architektur und sogar
denselben Befehlssatz. Programme liefen also (theoretisch) unverändert
auf all diesen Rechnern. Die parallele Entwicklung solch vieler Rechner
war erst durch die IC-Technik möglich geworden.
Da man noch keine wirkliche Erfahrung mit Betriebssystemen hatte, gab es
wenig echte Planung im voraus. Viele Fähigkeiten wurden erst spät
während der Entwicklungszeit hinzugefügt.
Timesharing wurde zuerst 1962 (als CTSS) auf einer IBM-7094 entwickelt, also
auf einer Hardware ohne Möglichkeit zur Memory Protection. Es wurde also
erst später wirklich einsetzbar.
1.2.4 Mikroprozessoren
|   |
1.1: Was ist ein Betriebssystem?
| Startseite |
1.3: Beispiele 
|
|   |