0% fanden dieses Dokument nützlich (0 Abstimmungen)
73 Ansichten284 Seiten

Skript Betriebssysteme

Das Dokument enthält eine Einführung in Betriebssysteme und Systemsoftware. Es werden die Ziele und Themen der Vorlesung vorgestellt sowie die Struktur von Rechnersystemen erläutert. Zusätzlich werden wichtige Konzepte wie Prozessverwaltung, Speicherverwaltung und parallele Systeme beschrieben.

Hochgeladen von

xcntffpbmz
Copyright
© © All Rights Reserved
Wir nehmen die Rechte an Inhalten ernst. Wenn Sie vermuten, dass dies Ihr Inhalt ist, beanspruchen Sie ihn hier.
Verfügbare Formate
Als PDF, TXT herunterladen oder online auf Scribd lesen
0% fanden dieses Dokument nützlich (0 Abstimmungen)
73 Ansichten284 Seiten

Skript Betriebssysteme

Das Dokument enthält eine Einführung in Betriebssysteme und Systemsoftware. Es werden die Ziele und Themen der Vorlesung vorgestellt sowie die Struktur von Rechnersystemen erläutert. Zusätzlich werden wichtige Konzepte wie Prozessverwaltung, Speicherverwaltung und parallele Systeme beschrieben.

Hochgeladen von

xcntffpbmz
Copyright
© © All Rights Reserved
Wir nehmen die Rechte an Inhalten ernst. Wenn Sie vermuten, dass dies Ihr Inhalt ist, beanspruchen Sie ihn hier.
Verfügbare Formate
Als PDF, TXT herunterladen oder online auf Scribd lesen

Grundlagen: Betriebssysteme und

Systemsoftware (GBS)

Johann Schlichter
Institut für Informatik
TU München, Munich, Germany

September 2015
Vorlesungsunterlagen
(Teacher Script1 )

1 Script generated by Targeteam. Not for Distribution


Inhaltsverzeichnis

1 Übersicht 2
1.1 Ziele der Vorlesung . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.1 Anforderungen an Rechensysteme . . . . . . . . . . . . . 4
1.2.2 Struktur eines Rechensystems . . . . . . . . . . . . . . . 7
1.3 Themen der Vorlesung . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.1 Laufzeitmodell . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.2 Inhaltsübersicht . . . . . . . . . . . . . . . . . . . . . . . 10
1.4 Literaturübersicht . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4.1 Begleitend zur Vorlesung . . . . . . . . . . . . . . . . . . 12
1.4.2 Weiterführende Literatur . . . . . . . . . . . . . . . . . . 12

2 Einführung 14
2.1 Betriebssystem - Überblick . . . . . . . . . . . . . . . . . . . . . 14
2.1.1 BS-Hauptaufgaben . . . . . . . . . . . . . . . . . . . . . 15
2.1.2 Systemprogrammierung . . . . . . . . . . . . . . . . . . 19
2.1.3 Hardwarekomponenten . . . . . . . . . . . . . . . . . . . 20
2.1.4 Betriebsarten . . . . . . . . . . . . . . . . . . . . . . . . 21
2.1.5 Historie . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.2 Betriebssystem-Architektur . . . . . . . . . . . . . . . . . . . . . 23
2.2.1 Monolithischer Ansatz . . . . . . . . . . . . . . . . . . . 23
2.2.2 Mikrokern-Ansatz . . . . . . . . . . . . . . . . . . . . . 26
2.2.3 Beispiel: BS-Architekturen . . . . . . . . . . . . . . . . . 27
2.2.4 Systemaufrufe . . . . . . . . . . . . . . . . . . . . . . . 30

i
Schlichter, TU München INHALTSVERZEICHNIS

2.2.5 Virtuelle Maschine . . . . . . . . . . . . . . . . . . . . . 32


2.3 Hardwarenahe Programme . . . . . . . . . . . . . . . . . . . . . 33
2.3.1 Definitionen . . . . . . . . . . . . . . . . . . . . . . . . 33
2.3.2 Programmaufbereitung . . . . . . . . . . . . . . . . . . . 34
2.3.3 Binder und Lader . . . . . . . . . . . . . . . . . . . . . . 36

3 Parallele Systeme - Modellierung, Strukturen 42


3.1 Fragestellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.2 Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.2.1 Begriffsdefinitionen . . . . . . . . . . . . . . . . . . . . 44
3.2.2 Beschreibungskonzepte . . . . . . . . . . . . . . . . . . . 46
3.3 Modellierung paralleler Systeme . . . . . . . . . . . . . . . . . . 47
3.3.1 Modellierungsziele . . . . . . . . . . . . . . . . . . . . . 47
3.3.2 Verhaltensbeschreibung . . . . . . . . . . . . . . . . . . 48
3.3.3 Ereignisse und Aktionsstrukturen . . . . . . . . . . . . . 50
3.3.4 Aktionen als Zustandsübergänge . . . . . . . . . . . . . . 56
3.3.5 Petri-Netze . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.4 Thread-Konzept . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.4.1 Charakterisierung von Threads . . . . . . . . . . . . . . . 75
3.4.2 Threads in Java . . . . . . . . . . . . . . . . . . . . . . . 78
3.5 Synchronisation . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.5.1 Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.5.2 Definition: Wechselseitiger Ausschluss . . . . . . . . . . 84
3.5.3 Modellierung . . . . . . . . . . . . . . . . . . . . . . . . 85
3.5.4 Synchronisierungskonzepte . . . . . . . . . . . . . . . . 87
3.5.5 Semaphore . . . . . . . . . . . . . . . . . . . . . . . . . 92
3.5.6 Synchronisierung von Java Threads . . . . . . . . . . . . 98
3.6 Verklemmungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
3.6.1 Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . 100
3.6.2 Belegungs-Anforderungsgraph . . . . . . . . . . . . . . . 101
3.6.3 Verklemmungs-Ignorierung . . . . . . . . . . . . . . . . 101
3.6.4 Verklemmungs-Erkennung . . . . . . . . . . . . . . . . . 102
3.6.5 Verklemmungs-Verhinderung . . . . . . . . . . . . . . . 103

ii
Schlichter, TU München INHALTSVERZEICHNIS

3.6.6 Verklemmungs-Vermeidung . . . . . . . . . . . . . . . . 104


3.6.7 Vergleich der Ansätze . . . . . . . . . . . . . . . . . . . 106

4 Prozess- und Prozessorverwaltung 107


4.1 Fragestellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
4.2 Prozessverwaltung . . . . . . . . . . . . . . . . . . . . . . . . . 107
4.2.1 Prozesskonzept . . . . . . . . . . . . . . . . . . . . . . . 108
4.2.2 Dispatcher . . . . . . . . . . . . . . . . . . . . . . . . . 115
4.2.3 Arbeitsmodi . . . . . . . . . . . . . . . . . . . . . . . . 117
4.2.4 Systemaufrufe . . . . . . . . . . . . . . . . . . . . . . . 117
4.2.5 Realisierung von Threads . . . . . . . . . . . . . . . . . 118
4.3 Prozessorverwaltung . . . . . . . . . . . . . . . . . . . . . . . . 121
4.3.1 Kriterien . . . . . . . . . . . . . . . . . . . . . . . . . . 122
4.3.2 Scheduling-Strategien . . . . . . . . . . . . . . . . . . . 124
4.3.3 Beispiel Unix Scheduling . . . . . . . . . . . . . . . . . 129
4.3.4 Thread Scheduling . . . . . . . . . . . . . . . . . . . . . 130
4.3.5 Mehrschichtiges Scheduling . . . . . . . . . . . . . . . . 131
4.3.6 Echtzeit Scheduling . . . . . . . . . . . . . . . . . . . . 132
4.4 Unterbrechungskonzept . . . . . . . . . . . . . . . . . . . . . . . 134
4.4.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . 134
4.4.2 Unterbrechungsarten . . . . . . . . . . . . . . . . . . . . 135
4.4.3 Behandlung externer Unterbrechungen . . . . . . . . . . 137
4.4.4 Konflikte . . . . . . . . . . . . . . . . . . . . . . . . . . 138

5 Speicherverwaltung 141
5.1 Fragestellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
5.2 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
5.2.1 Adressräume . . . . . . . . . . . . . . . . . . . . . . . . 142
5.2.2 Organisation von Adressräumen . . . . . . . . . . . . . . 143
5.2.3 Fragmentierung . . . . . . . . . . . . . . . . . . . . . . . 150
5.2.4 Forderungen an Adressraumrealisierung . . . . . . . . . . 151
5.3 Speicherabbildungen . . . . . . . . . . . . . . . . . . . . . . . . 152
5.3.1 Direkte Adressierung . . . . . . . . . . . . . . . . . . . . 152

iii
Schlichter, TU München INHALTSVERZEICHNIS

5.3.2 Basisadressierung . . . . . . . . . . . . . . . . . . . . . . 154


5.4 Seitenadressierung . . . . . . . . . . . . . . . . . . . . . . . . . 156
5.4.1 Ansatz . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
5.4.2 Adressabbildung . . . . . . . . . . . . . . . . . . . . . . 159
5.4.3 Seiten-Kacheltabelle . . . . . . . . . . . . . . . . . . . . 163
5.4.4 Seitenfehlerbehandlung . . . . . . . . . . . . . . . . . . . 166
5.4.5 Seitenverwaltungsstrategien . . . . . . . . . . . . . . . . 167
5.4.6 Linux - Virtuelle Adressierung . . . . . . . . . . . . . . . 172
5.5 Segment-Seitenadressierung . . . . . . . . . . . . . . . . . . . . 174
5.6 Speicherhierarchie / Caches . . . . . . . . . . . . . . . . . . . . . 175
5.6.1 Speicherhierarchie - Beispiel . . . . . . . . . . . . . . . . 175
5.6.2 Cache Speicher . . . . . . . . . . . . . . . . . . . . . . . 176
5.6.3 Caching in der Speicherhierarchie . . . . . . . . . . . . . 176
5.6.4 Realisierung von Caches . . . . . . . . . . . . . . . . . . 178
5.6.5 Cache freundlicher Code . . . . . . . . . . . . . . . . . . 182

6 Prozesskommunikation 184
6.1 Fragestellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
6.2 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
6.2.1 Kommunikationsarten . . . . . . . . . . . . . . . . . . . 185
6.2.2 Verteilte Systeme . . . . . . . . . . . . . . . . . . . . . . 189
6.3 Nachrichtenbasierte Kommunikation . . . . . . . . . . . . . . . . 190
6.3.1 Elementare Kommunikationsmodelle . . . . . . . . . . . 190
6.3.2 Erzeuger-Verbraucher Problem . . . . . . . . . . . . . . . 196
6.3.3 Modellierung durch ein Petrinetz . . . . . . . . . . . . . . 196
6.3.4 Ports . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
6.3.5 Kanäle . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
6.3.6 Ströme . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
6.3.7 Pipes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
6.4 Client-Server-Modell . . . . . . . . . . . . . . . . . . . . . . . . 204
6.5 Netzwerkprogrammierung . . . . . . . . . . . . . . . . . . . . . 207
6.5.1 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . 207
6.5.2 Server Protokoll . . . . . . . . . . . . . . . . . . . . . . 208

iv
Schlichter, TU München INHALTSVERZEICHNIS

6.5.3 Client Protokoll . . . . . . . . . . . . . . . . . . . . . . . 210


6.5.4 Bidirektionale Stromverbindung . . . . . . . . . . . . . . 210
6.5.5 Java Socket Class . . . . . . . . . . . . . . . . . . . . . . 211
6.5.6 Beispiel - Generische Client/Server Klassen . . . . . . . . 213

7 Dateisysteme 218
7.1 Fragestellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
7.2 Charakteristika von Dateisystemen . . . . . . . . . . . . . . . . . 219
7.3 Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
7.4 Memory-Mapped Dateien . . . . . . . . . . . . . . . . . . . . . . 223
7.5 Verzeichnisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
7.6 Schichtenmodell . . . . . . . . . . . . . . . . . . . . . . . . . . 225
7.6.1 Datenträgerorganisation . . . . . . . . . . . . . . . . . . 225
7.6.2 Blockorientiertes Dateisystem . . . . . . . . . . . . . . . 226
7.6.3 Dateiverwaltung . . . . . . . . . . . . . . . . . . . . . . 227
7.6.4 Virtuelles Dateisystem . . . . . . . . . . . . . . . . . . . 228

8 Ein-/Ausgabe 229
8.1 Klassifikation von E/A-Geräten . . . . . . . . . . . . . . . . . . . 229
8.2 Schichten eines E/A-Systems . . . . . . . . . . . . . . . . . . . . 230
8.3 Geräteverwaltung . . . . . . . . . . . . . . . . . . . . . . . . . . 232
8.3.1 Gerätetreiber . . . . . . . . . . . . . . . . . . . . . . . . 232
8.3.2 Geräteunabhängige E/A . . . . . . . . . . . . . . . . . . 234
8.4 RAID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
8.5 Disk Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
8.6 Multimedia Systems . . . . . . . . . . . . . . . . . . . . . . . . 243
8.6.1 Zustellung von Mediendaten . . . . . . . . . . . . . . . . 243
8.6.2 Eigenschaften von Multimedia Systemen . . . . . . . . . 244

9 Sicherheit in Rechensystemen 246


9.1 Fragestellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
9.2 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
9.3 Schutzmechanismen . . . . . . . . . . . . . . . . . . . . . . . . 252

v
Schlichter, TU München INHALTSVERZEICHNIS

9.3.1 Anforderungen . . . . . . . . . . . . . . . . . . . . . . . 253


9.3.2 Ebenen des Zugriffschutzes . . . . . . . . . . . . . . . . 253
9.3.3 Schutzmatrix . . . . . . . . . . . . . . . . . . . . . . . . 254
9.3.4 Authentifizierung . . . . . . . . . . . . . . . . . . . . . . 259
9.4 Mobiler Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
9.4.1 Sandboxing . . . . . . . . . . . . . . . . . . . . . . . . . 260
9.4.2 Interpretation . . . . . . . . . . . . . . . . . . . . . . . . 261
9.4.3 Signed Code . . . . . . . . . . . . . . . . . . . . . . . . 261

10 Entwurf von Betriebssystemen 262


10.1 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
10.1.1 Hauptaspekte . . . . . . . . . . . . . . . . . . . . . . . . 262
10.1.2 Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . 263
10.2 Schnittstellenentwurf . . . . . . . . . . . . . . . . . . . . . . . . 264
10.2.1 Leitlinien für den Entwurf . . . . . . . . . . . . . . . . . 264
10.2.2 Paradigmen der Systemaufrufschnittstelle . . . . . . . . . 265
10.3 Weitere Implementierungsaspekte . . . . . . . . . . . . . . . . . 268
10.3.1 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . 268
10.3.2 Mechanismen vs. Policies . . . . . . . . . . . . . . . . . 268
10.3.3 Namensräume . . . . . . . . . . . . . . . . . . . . . . . 269
10.3.4 Statische - Dynamische Datenstrukturen . . . . . . . . . . 270
10.3.5 Verbergen der Hardware . . . . . . . . . . . . . . . . . . 270
10.3.6 Speicherplatz vs. Laufzeit . . . . . . . . . . . . . . . . . 271
10.4 Trends beim Entwurf von Betriebssystemen . . . . . . . . . . . . 272

11 Zusammenfassung 276

vi
Schlichter, TU München INHALTSVERZEICHNIS

• Prof. J. Schlichter

– Lehrstuhl für Angewandte Informatik / Kooperative Systeme, Fakultät für


Informatik, TU München
– Boltzmannstr. 3, 85748 Garching
Email: schlichter@[Link] (URL: [Link]
Tel.: 089-289 18654
URL: [Link]

1
Kapitel 1

Übersicht

Grundlagen der
Programmierung

Systemnahe Programmierung;
Betriebsysteme, verteilte Systeme

Technische Grundlagen der


Informatik

1.1 Ziele der Vorlesung


Diese Vorlesung beschäftigt sich mit den technischen Aspekten von Rechensyste-
men und der Informationsverarbeitung, nämlich der systemnahen Programmie-
rung im Zusammenhang mit Betriebssystemen. Dabei werden vor allem nicht
verteilte Systeme betrachtet. Aspekte verteilter Systeme und Rechnernetze wer-
den im Grundstudium einführend in der Vorlesung: "Grundlagen: Rechnernetze
und verteilte Systeme" (GRV) behandelt.

• Zunächst werden informell die Aufgaben und Eigenschaften eines Betriebssy-


stem dargestellt. Daraus lassen sich die für die Vorlesung relevanten Begriffe
ableiten. Weiterhin wird kurz auf Hardware-nahe Programme eingegangen.

2
Schlichter, TU München 1.2. MOTIVATION

• Im nächsten Teil der Vorlesung erfolgt der Übergang von sequentiellen zu


parallelen Systemen. Zu den Themen, die behandelt hier werden, gehören die
Grundlagenprobleme paralleler Systeme und die Verfahren, mit denen diese
gelöst werden können: Modellierung des Systemverhaltens, Synchronisation,
Verklemmungen.

• Im Anschluss daran werden Konzepte und Verfahren von Betriebssystemen,


die der wesentliche Teil der Konkretisierung paralleler Systeme sind, behandelt.
Insbesondere geht es um die Arbeitsspeicherverwaltung (Hauptspeicherverwal-
tung, "main memory management"), die Prozessverwaltung und die Prozessor-
zuteilung sowie Mechanismen zur Kontrolle der Nebenläufigkeit. Beispiele für
letztere sind Threads und Semaphore.

• Prozesse existieren nicht in Isolation, sondern die Kommunikation zwischen den


Prozessen ist von zentraler Bedeutung für Lösung vieler Problemstellungen.
Der Austausch von Information zwischen Prozessen kann entweder speicher-
basiert oder über Nachrichten erfolgen. Die nachrichtenbasierte Prozesskom-
munikation ist gerade für verteilte Rechensysteme, wo Prozesse über ein Rech-
nernetz miteinander kommunizieren, von großer Bedeutung. Wichtige Aspekte
sind hierbei das Client-Server Modell und die Netzwerkprogrammierung.

• Im Abschnitt Ein-/Ausgabe wird die Anbindung von peripheren Geräten durch


das Betriebssystem behandelt.

• Mit der rasanten Verbreitung des Internet und dessen Nutzung für private und
geschäftliche Transaktionen (E-Commerce und E-Business) steigt der Bedarf
an sicheren IT-Systemen. Der Abschnitt behandelt nach einigen verbreiteten Si-
cherheitslücken verschiedene Schutzmechanismen, wie Schutzmatrizen, Kryp-
tosysteme und Authentifizierungsmechanismen. Eine vertiefte Behandlung die-
ser Thematik erfolgt in verschiedenen Spezialvorlesungen zur IT-Sicherheit.

1.2 Motivation
Aufgabe der Informatik ist es, Rechensysteme zu entwickeln und diese Anwen-
dern als leistungsfähige Hilfsmittel für Lösungen ihrer Informationsverarbei-
tungsprobleme zur Verfügung zu stellen. Diese Aufgabe ist vielgestaltig, weit-
reichend, kompliziert und komplex; sie führt im Zuge der Weiterentwicklung von
Rechensystemen und im Zuge der wachsenden Nachfrage der Gesellschaft nach
Information fortwährend auf neue Fragestellungen, für die nach Antworten ge-
sucht werden muss. Sie hat zudem dazu geführt, dass sich große Bereiche der
Industrie und der Wirtschaft mit dieser Aufgabe befassen. Im folgenden werden

3
Schlichter, TU München 1.2. MOTIVATION

zunächst die wichtigsten Anforderungen, die mit der Entwicklung von Rechensy-
stemen erfüllt werden sollen, in Kürze genauer erklärt.

1.2.1 Anforderungen an Rechensysteme


Rechensysteme sind

offene, dynamische, technische Systeme


mit Fähigkeiten zur Speicherung und zur

Verarbeitung von Information, die für Anwendungen und Anwender nutzbar


zur Verfügung gestellt werden sollen.

Offenes System

Ein Rechensystem R ist ein offenes System sagt zweierlei aus:

• R ist als System eine durch Zusammenfassung gebildete, abgegrenzte Einheit,


wo zwischen innen (R) und außen (U(R)) unterschieden wird. Innen ist das,
was zu R gehört, und außen ist das, was nicht zu R und damit zur Umgebung
U(R) gehört.

• R hat eine (offene) Schnittstelle, mit der Einwirkungen von U(R) auf R und
Einwirkungen von R auf U(R) möglich sind.

• Schnittstelle eines Rechensystems

4
Schlichter, TU München 1.2. MOTIVATION

Umgebung
U(R)

Schnittstelle R - U(R)

Rechensystem R

Zur Schnittstelle R - U(R) gehören z.B. die Benutzerinteraktionsschnittstelle,


die Netzschnittstelle, die Schnittstelle zu externen Geräten (Sensoren).

• Sichten eines Rechensystems


Es existieren verschiedene Sichten auf das Rechensystems R

– Außensicht vs. Innensicht. Die Außensicht, die von außen die Eigenschaften
der R-U(R) Schnittstelle zeigt, und die Innensicht, welche die inneren
Eigenschaften von R präsentiert.
– Black-box Sicht vs. White-box Sicht. 1
Das System ist ein schwarzer Kasten (black box): Das System wird als
einzelner Gegenstand aufgefasst. Das System ist ein weißer Kasten (white
box oder auch glass box): Für das Verständnis des Systems ist dessen
Zusammensetzung aus Komponenten wichtig.
– Sichten sind methodische Hilfsmittel für Systemanalysen:
∗ Komponenten haben Eigenschaften, die denen von Systemen entsprechen.
Dies bedeutet, Komponenten können für sich als Systeme betrachtet
werden.
∗ Verbindungen zwischen Komponenten beschreiben Abhängigkeiten zwi-
schen Komponenten.
∗ Rekursive Aufteilungen in Komponenten bzw. Sub-Komponenten liefern
verfeinerte White-box Sichten.
1
(siehe Informatik I, Brügge)

5
Schlichter, TU München 1.2. MOTIVATION

∗ Zusammenfassungen und Abgrenzungen liefern Einheiten, für die Black-


box Sichten möglich sind.
∗ ⇒ Rekursion bei der Entwicklung und Analyse von Rechensystemen.
Die umrissene Vorgehensweise unter Anwendung der erklärten Systembe-
griffe ist für Analysen großer Systeme geeignet, wenn sie iterativ (rekursiv)
angewandt wird; sie ist insbesondere dann geeignet, wenn sie induktiv ange-
wandt werden kann. Die Möglichkeiten hierfür ergeben sich aus den Eigen-
schaften, die ein gegebenes System hat. Für ein Rechensystem R wird über
diese Möglichkeiten bei der Entwicklung von R entschieden. Die Vorgehens-
weise bei der Entwicklung von R und die Vorgehensweise bei Analysen von
R stehen also in engem Zusammenhang.

Dynamisches System

Eigenschaften des Rechensystems R ändern sich mit der Zeit


⇒ Beschreibung des Verhaltens von R.
In diesem Zusammenhang werden wir Beschreibungsmöglichkeiten kennenler-
nen, insbesondere Petrinetze. Diese dienen dazu das Verhalten von Prozessen
und deren Interaktion zu spezifizieren. Ein Rechensystem erhält seine Fähigkeiten
zu selbsttätigen Veränderungen seiner Eigenschaften mit entsprechenden Kompo-
nenten; demnach sind für R aktive und passive Komponenten zu unterscheiden:
Mit seinen aktiven Komponenten (z.B. CPU) führt R Aktionen aus, die Verän-
derungen der Eigenschaften von R bewirken; die passiven Komponenten (z.B.
Arbeitsspeicher) sind Hilfsmittel für diese Aktionen.

Technisches System

Das Rechensystem ist mit hardware- und softwaretechnischen Mitteln realisiert.


R ist entweder ein mit technischen Mitteln realisiertes, reales System oder ein
künstliches, artifizielles System, das die Eigenschaften hat, die es mit seiner
Entwicklung und mit seinen Weiterentwicklungen erhält.

Informationsspeicherung und -verarbeitung

6
Schlichter, TU München 1.2. MOTIVATION

Wissen

Information Information

Repräsentation Interpretation

Daten Daten

Nachricht

Daten sind elementare Fakten, Aussagen und Sachverhalte. Sie sind leicht
zu strukturieren, leicht maschinell zu erfassen und leicht zu übertragen. Im
Zusammenhang mit der Übertragung spricht man auch gerne von Nachrichten.
Information sind Daten mit einer Bedeutung und einem Zweck; sie erfordert
Analyse, Konsens bzgl. Semantik und Interpretation. Die Semantic Web
(URL: [Link] Initiative versucht, die syntaktische Web-
Information um semantische Information zu ergänzen. Wissen ist Information
in einem bestimmten, für den Menschen relevanten Kontext; es ist schwierig,
Wissen zu strukturieren, schwierig maschinell zu erfassen und zu verarbeiten.
Weiterhin ist es schwierig Wissen zu übertragen, da es oft nur implizit existiert
(siehe auch das neue Forschungsgebiet Wissensmanagement bzw. "Knowledge
Management").
2

1.2.2 Struktur eines Rechensystems

2
Unterscheidung zwischen implizites und explizites Wissen.

7
Schlichter, TU München 1.2. MOTIVATION

Anwendungs-
Datenbank World Wide Web Email programme

Shell Übersetzer Dateisystem


Systemprogramme

Betriebssystem

Maschinensprache

Mikroprogramme / festverdrahtete Programme Hardware

physische Komponenten und Geräte

In dieser Vorlesung werden wir uns besonders mit Aspekten der technischen
Informatik beschäftigen, und zwar mit den Systemprogrammen (Betriebssysteme,
Assembler, Kommunikation in verteilten Systemen) sowie der Schnittstelle zu
der darunter liegenden Hardware. Die Vorlesung ist als eine Einführung in
diesen Bereich zu interpretieren; eine detailliertere Behandlung von Hardware,
Systemprogramme und verteilte Systeme erfolgt in weiterführenden Vorlesungen.
Mikroprogramme dienen zur Realisierung der Maschinensprache; bei RISC-
Rechnern (z.B. Sun Workstation) sind die Mikroprogramme oft festverdrahtet.

• Darstellung von Programmen in maschinennaher Form für bestimmte Anwen-


dungen auch heute noch unerläßlich, beispielsweise für den Übersetzerbau, ein-
gebettete Systeme oder für systemnahe Programmierung in Teilen des Betriebs-
systems. Beispiele dafür sind Echtzeitanwendungen, aber auch Teile des Be-
triebssystems wie Nachrichtenaustausch, low-level Speicherverwaltung. Ein-
gebettete Systeme sind in Autos oder Handies zu finden. Beispielsweise ist in
modernen Autos bereits eine zweistelligen Anzahl von Prozessoren zu finden,
die über einen internen Bus miteinander verbunden sind.
• Thema der Vorlesung ist systemnahe Programmentwicklung; darunter maschi-
nennahe Programmierung und nebenläufige ("concurrent") Ausführung von
mehreren Teilabläufen ⇒ Nichtdeterminismus. Dabei ergibt sich von selbst ei-
ne neue Qualität der Programmierung: Nebenläufigkeit, d.h. zwei oder mehrere
Teilabläufe finden gleichzeitig statt, beispielsweise CPU und Drucker. Neue

8
Schlichter, TU München 1.3. THEMEN DER VORLESUNG

Qualität insofern, als Nebenläufigkeit auch Nichtdeterminismus enthält. Unter


Nichtdeterminismus verstehen wir das willkürliche Auftreten von Abläufen und
Ereignissen (bedingt durch Einflüsse wie Last, Interaktion mit Benutzer).

1.3 Themen der Vorlesung


Diese Vorlesung beschäftigt sich
mit den technischen Aspekten von Rechensystemen und der Informationsver-
arbeitung, insbesondere der Systemsoftware.

Dabei werden vor allem Strukturen, Abläufe und Dienste von Betriebssyste-
men betrachtet. Der Fokus liegt auf nicht verteilte Systeme. Im Zusammen-
hang mit der Prozesskommunikation wird auch ein Ausblick auf verteilte Sy-
steme gegeben. Dienste sind Softwareeinheiten, die bestimmte Funktionali-
täten bereitstellen. Ablauf ist eine Abfolge von Aktivitäten/Operationen. Als
Teil eines Ablaufs können die Operationen eines Dienstes aufgerufen werden.
Ablauf hat einen Zeitbezug.

1.3.1 Laufzeitmodell
Bereitstellung eines indirekten Zugangs zur Rechnerhardware über eine Dienst-
schicht. 3 Ziel dieser Schicht ist die Realisierung einer virtuellen Maschine.
Virtualisierung kann sowohl zur Fehlervermeidung als auch zur Reduktion der
Komplexität eingesetzt werden.

• Die in den Diensten bereitgestellten Abstraktionen stellen einen Rahmen für


die Organisation von Anwendungen zur Laufzeit dar, d.h. ein Laufzeitmodell.

• Dienste des Laufzeitmodells: Systembedienung, Prozessmanagement, Prozes-


sinteraktion, Datenhaltung, Gerätemanagement. Wichtige Fragestellungen der
systemnahen Programmierung sind:
a) welche Dienste gehören zu einem Laufzeitmodell?
b) gibt es einen inneren Zusammenhang unter den Diensten?
c) welche Dienstmenge ist unverzichtbar?
d) wo werden die Dienste realisiert?
Beispielsweise werden die Dienste im Betriebssystemkern oder als Systempro-
zesse realisiert, die im Benutzermodus ("user mode") ablaufen.
3
[nehmer2001 S27]

9
Schlichter, TU München 1.3. THEMEN DER VORLESUNG

• elementare Abstraktionen eines Laufzeitmodells. Prozesse sind beispielsweise


dynamische Objekte, die Aktivitäten in einem Rechensystem repräsentieren.
Jeder Prozess ist definiert durch einen Adressraum A, eine darin gespeicherte
Handlungsvorschrift H in Form eines sequentiellen Programms und einen
Aktivitätsträger T, der mit der Handlungsvorschrift verknüpft ist und sie
ausführt. Der Aktivitätsträger T wird oft auch als "Thread" bezeichnet. Das
Tripel (A, H, T) repräsentiert einen sequentiellen Prozess.

Elemente des Laufzeitmodells

– Adressräume = Abstraktion eines physischen Speichers. Unter einem


Adressraum versteht man einen von der Speichertechnologie und den be-
schränkten Ausbaumöglichkeiten physischer Speicher unabhängigen virtuel-
len Speicher. Adressräume verschiedener Prozesse sind gegeneinander ab-
geschottet. Innerhalb eines Adressraums können ein oder mehrere Threads
ablaufen.
– Threads = Abstraktion eines physischen Prozessors. Ein Thread ist der Träger
einer sequentiellen Aktivität, die durch die Ausführung eines dem Thread
zugeordneten Programms (Handlungsvorschrift) bestimmt ist. Parallelität
wird durch die Ausführung mehrerer Threads erreicht.
– Prozessinteraktion. Prozessinteraktion kann entweder speicherbasiert, d.h. es
gibt gemeinsame Speicherbereiche, auf die die Prozesse (Threads) zugreifen,
oder nachrichtenbasiert ablaufen. Im ersten Fall sind Mechanismen zur Syn-
chronisation der Zugriffe auf den gemeinsamen Speicherbereich notwendig,
um Inkonsistenzen zu vermeiden. Im letzten Fall haben die Prozesse getrenn-
te Adressräume. Sie tauschen Informationen über Nachrichten aus. Dieser
Ansatz wird vor allem in verteilten Rechensystemen verwendet, wo Prozesse
über ein Rechnernetz miteinander kommunizieren.

1.3.2 Inhaltsübersicht
Im einzelnen werden in der Vorlesung die folgenden Themen behandelt:

1. Übergang von sequentiellen Systemen zu parallelen Systemen: Verhaltensbe-


schreibungen mit Hilfe von Spuren und Petrinetzen, Synchronisationskonzepte.
Hier steht vor allem die Interaktion zwischen den Komponenten des Rechensy-
stems im Vordergrund. Daneben wird auch die speicherbasierte Prozessinterak-
tion behandelt, d.h. das gemeinsame Nutzen von Daten. Hier kommen Sema-
phore und Monitore zum Einsatz. Ein wichtiger Aspekt ist die Behandlung von
Verklemmungen, d.h. Prozesse blockieren sich gegenseitig.

10
Schlichter, TU München 1.4. LITERATURÜBERSICHT

2. grundlegende Betriebssystemkonzepte: Prozessverwaltung, Prozessorzutei-


lung, Arbeitsspeicherverwaltung, Dateisysteme. Bei der Arbeitsspeicherver-
waltung steht vor allem der virtuelle Speicher in Form der Seitenadressierung
im Vordergrund. Bei Dateisystemen wird neben allgemeinen Anforderungen
auch ein Schichtenmodell kurz vorgestellt.

3. Prozesskommunikation - speicherbasiert und nachrichtenbasiert. Zunächst


werden die verschiedenen Kommunikationsarten vorgestellt, wobei wir uns vor
allem auf die nachrichtenbasierte Kommunikation konzentrieren, z.B. Ports und
Sockets.

4. Sicherheit in Rechensystemen: Schutzmechanismen, Zugriffskontrolllisten,


Capability-Listen, Kryptographie, Authentifizierung. In diesem Abschnitt steht
die Sicherheit in Rechensystemen im Vordergrund, und zwar sowohl in lokalen
als auch in verteilten Systemen.

Programmiersprachen

In der Vorlesung wird vor allem die Programmiersprache Java verwendet.


Daneben, wenn notwendig, Verwendung von

• C Programmiersprache: zur Spezifikation von systemnahen Programmstücken.

– entwickelt zwischen 1969 und 1973 von Dennis Ritchie bei Bell Labs
– C und Unix sind eng miteinander verbunden
– C ist eine einfache, kleine Sprache
– C war und ist noch eine wichtige Sprache für systemnahe Programmierung
– C bedingt jedoch einige Fehleranfälligkeiten, z.B.
dynamische Speicherbelegung und -freigabe. (malloc, free)
Pointerarithmetik. (Addieren einer ganzen Zahl zu einem Pointer)

1.4 Literaturübersicht
Literatur, die als Basis für die Vorlesung verwendet wird.

11
Schlichter, TU München 1.4. LITERATURÜBERSICHT

1.4.1 Begleitend zur Vorlesung


• Andrew S. Tanenbaum, "Modern Operating Systems", Prentice Hall, 2014; es
gibt eine ältere deutsche Übersetzung
Andrew S. Tanenbaum, "Moderne Betriebssysteme", Pearson Studium,
2009
• Abraham Silberschatz, Peter Galvin, Greg Gagne, " Operating System
Concepts. Operating System Concepts", Wiley & Sons, 2012 4

1.4.2 Weiterführende Literatur


• Albrecht Achilles, "Betriebssysteme - Eine kompakte Einführung mit Linux",
Springer, 2006

• Uwe Baumgarten, Hans-Jürgen Siegert, "Betriebssysteme", Oldenbourg, 2006

• Rüdiger Brause, "Betriebssysteme - Grundlagen und Konzepte", Springer, 2013

• Eduard Glatz, "Betriebssysteme - Grundlagen, Konzepte, Systemprogrammie-


rung", [Link], 2015

• Jürgen Nehmer, Peter Sturm, "Systemsoftware - Grundlagen moderner


Betriebssysteme", [Link], 2001

• Randal E. Bryant, David R. O’Hallaron, "Computer Systems - A Programmer’s


Perspective", Pearson Education, 2015 (detaillierte Diskussion von Cache
Speicher und deren Verwaltung)

• William Stallings, "Operating Systems - Internals and Design Principals",


Pearson International Edition, 2011

• George Coulouris, Jean Dollimore, Tim Kindberg, "Distributed Systems -


Concepts and Design", Addison-Wesley, 2012 (Neuausgabe 5. Edition)

• Andrew S. Tanenbaum, Marten van Steen, "Verteilte Systeme - Grundlagen und


Paradigmen", Pearson Studium, 2007 (2. Auflage)

• Elliote Rusty Harold, "Java Network Programming", O’Reilly, 2013 (seit 2009
auch als eBook Kindle erhältlich)
4
2010 ist eine Variante erschienen als " Operating System Concepts with Java Operating
System Concepts with Java" (8. Edition).

12
Schlichter, TU München 1.4. LITERATURÜBERSICHT

• Ralph Morelli, Ralph Walde, "Java, Java, Java - Object-Oriented Problem


Solving", Prentice Hall, 2005 (Aspekte von Java Netzwerkprogrammierung)

• Claudia Eckert, "IT-Sicherheit: Konzepte - Verfahren - Protokolle", Oldenbourg


Verlag, 2014

13
Kapitel 2

Einführung

Definition eines Betriebssystems nach DIN 44300:


Das Betriebssystem wird gebildet durch die Programme eines digitalen
Rechensystems, die zusammen mit den Eigenschaften der Rechenanlage die
Grundlage der möglichen Betriebsarten des digitalen Rechensystems bilden
und insbesondere die Ausführung von Programmen steuern und überwachen.
Diese Definition geht also von der Beschreibung seiner Aufgabe und seiner
Stellung in einer Programmhierarchie aus.

2.1 Betriebssystem - Überblick


Ein Betriebssystem realisiert die Schnittstelle zwischen dem Benutzer und der
physischen Rechenanlage. Aus der Sicht des Benutzers entsteht durch ein Be-
triebssystem eine virtuelle Maschine. Für einen Benutzer ist es nicht wichtig, ob in
einem Rechensystem Systemfunktionen durch Hardware oder Software realisiert
sind. Ein Betriebssystem realisiert insbesondere eine Benutzerschnittstelle. Der
Entwurf und die Implementierung von Betriebssystemen gehören zu den klassi-
schen Aufgabenstellungen der Systemprogrammierung. Je nach Art der Hardware
gibt es sehr unterschiedliche Typen von Betriebssystemen. Sie reichen von Be-
triebssystemen für Großrechner, über Server-BS bis hin zu PC-Betriebsystemen
und eingebetteten Betriebssystemen (z.B. in einem Android Smartphone). Andro-
id ist fuer den Nutzer weitgehend unsichtbar. Im Vordergrund steehn die Apps,
mit denen er interagiert.

14
Schlichter, TU München 2.1. BETRIEBSSYSTEM - ÜBERBLICK

2.1.1 BS-Hauptaufgaben
Ein Betriebssystem (engl. operating system) erfüllt folgende Hauptaufgaben:

• Veredeln der Hardware (Virtualisierung).

• Steuerung und Kontrolle der Programmausführung. Dazu werden die beiden


Betriebsmittel CPU und Arbeitsspeicher geeignet den Programmen zugeteilt.
Zur Durchführung dieser Aufgabe ist eine Prozessverwaltung (die im
System momentan auszuführenden Programme) und eine Benutzerverwaltung
notwendig.

• Interprozesskommunikation. Prozesse können mit anderen Prozessen Informa-


tionen austauschen. Die Prozesse können entweder auf dem gleichen Rechner
(lokal) oder auf anderen Rechner im Rechnernetz (verteilt) ausgeführt werden.

• Verwaltung der Ressourcen (Speicher, CPU, Platten, Netz etc.) ⇒ Betriebssy-


stem kann als Ressourcenverwalter gesehen werden. 1
Damit stellt sich die Frage: Sind Ressourcen überhaupt knapp, oder können aus-
reichend viele bereitgestellt werden? Phasen der Ressourcenverwaltung: Anfor-
derung, Zuteilung, Nutzung, Freigabe/Entzug/Aufräumen. Die Benutzung der
Ein-/ Ausgabegeräte sowie des Netzanschlusses erfolgt stets über das Betriebs-
system.

– Ressourcenklassen
Ein Rechensystem kann als strukturierte Sammlung von Ressourcenklassen
betrachtet werden, wobei jede Klasse durch Dienste des Betriebsystems
kontrolliert wird. 2

Zentral Ressourcen Periphere Ressour-


cen
Aktive Ressourcen Prozessoren (CPUs) Kommunikationseinheiten
wie Endgeräte ( Tasta-
tur, Drucker, Monitor,
Maus) und Netzwerk
(lokal, entfernt)
Passive Ressourcen Arbeitsspeicher Speichereinheiten wie
Festplatten, CD, DVD
1
Man spricht oft auch von Betriebsmittelverwalter.
2
Glatz S3

15
Schlichter, TU München 2.1. BETRIEBSSYSTEM - ÜBERBLICK

• Anbieten von Diensten in Form von Schnittstellen, so dass die Ressourcen


genutzt werden können ⇒ Hardwareunabhängige Programmierschnittstelle,
z.B. geräteunabhängige Ein-/Ausgabefunktionen. Programme können auf
diese Weise unverändert auf verschiedenen Rechensystemen mit Geräten
unterschiedlicher Hersteller ablaufen.

• Sicherheitsmechanismen. Darunter fallen Funktionen wie fehlerfreie Datenver-


arbeitung und Datenschutzkonzepte, z.B. Zugangskontrolle zum Rechner oder
Zugriffskontrolle auf Dienste oder Dateien. Unterscheidung zwischen
Authentifizierung: wer ist er?
Autorisierung: was darf er?

• Arbeitsmodi des Betriebssystems


Operationen des Betriebssystems und der Hardware müssen vor Programmier-
fehlern in Anwendungsprogrammen geschützt werden ⇒ Einführung eines Pri-
vilegiensystems.
Benutzermodus (user mode): Ausführung von Benutzerprogrammen,
kein direkter Hardware-Zugriff, keine privilegierten Befehl, nur virtuelle
Adressen.
Systemmodus (kernel mode): Ausführungsmodus der Dienste des BS-
Kerns, privilegierte Befehle erlaubt. Beispiele von privilegierten Befehlen
sind das Anhalten des Rechners, Zugriff auf Prozesskontrollblock (Pro-
zessbeschreibung), direkter Zugriff auf Hardware, insbesondere Geräte.
Benutzermodus Systemmodus
begrenzte Auswahl von Maschinen- alle ausführbaren Maschinenbefehle
befehlen
Hardwarezugriff nur über BS Vollzugriff auf Hardware
kein bzw. nur lesender Zugriff auf exklusiver Zugriff auf Systemcode
Systemcode oder Daten und Daten
Schreibzugriffe auf Systemcode sind nur im Systemmodus möglich. Wenn
im Systemmodus auf Systemcode/Systemdaten zugegriffen wird, kann parallel
kein anderer Zugriff darauf (auch kein lesender) erfolgen.

16
Schlichter, TU München 2.1. BETRIEBSSYSTEM - ÜBERBLICK

Benutzerprozess
Ausführung System Rückkehr von
Benutzermodus
Benutzerprozess Aufruf System Aufruf

Betriebssystemkern
Ausführung
Systemmodus
Systemdienst

Bei Ausführung des Benutzerprozesses befindet sich das System im Benutzer-


modus. Falls ein Dienst des Betriebssystemkerns notwendig ist, z.B. Zugriff auf
ein Gerät, muss vorher in den Systemmodus gewechselt werden. Beim Rech-
nerboot wird zunächst im Systemmodus gestartet. Das Betriebssystem wird ge-
laden; anschliessend werden die Benutzerprogramme im Benutzermodus gest-
artet.

• Struktureller Aufbau

17
Schlichter, TU München 2.1. BETRIEBSSYSTEM - ÜBERBLICK

berechtigte berechtigte zu überprüf.


Benutzer Benutzer Benutzer

Schnittstelle zur Systemumgebung login

System- Benutzer-
Prozesse Z
Prozesse
u
g
Betriebssystem-Schnittstelle a
n
g
Prozess
s
verwaltung
k
o
Speicher Datei
n
verwaltung system
t
r
o
Scheduler & EA- l
Dispatcher System l
e
Unterbrechungs-
System

Hardware
Konfiguration

Aus dem strukturellen Aufbau sind auch die wichtigsten Aufgaben und Funk-
tionen eines Betriebssystems ersichtlich. Dabei ist auch festzulegen, welche
Dienste im Betriebssystemkern und welche Dienste über Systemprozesse reali-
siert werden.

• Ein anderer Blickwinkel


NY Times, Sept, 3, 1997: A decade ago, an "operating system" was just the
basic piece of software that ruled the machine and allowed it to manipulate
files, converse with any peripherals, and start up programs. That was when a
computer was just a nerd toy, not the foundation for the most vital part of of
our economy. But today, an "operating system" is much more a vote over who
gets to be the richest men in the world. Windows means Microsoft, Java means
Sun, while MacOs means That Steve Jobs won’t go broke saving Apple. Linux
means no one gets rich because the OS is free, thanks to the help of many

18
Schlichter, TU München 2.1. BETRIEBSSYSTEM - ÜBERBLICK

3
volunteers.

2.1.2 Systemprogrammierung
Die Programmierung eines Betriebssystems gehört zu dem Bereich der System-
programmierung.

• Definition
Die Systemprogrammierung befasst sich mit der Darstellung, der Realisierung,
den Eigenschaften und der Konstruktion derjenigen Algorithmen für ein
Rechensystem, die die Bearbeitung und Ausführung von Benutzerprogrammen
unter vorgegebenen Qualitätsgesichtspunkten organisieren, d.h. steuern und
kontrollieren, und zum Teil selbst durchführen.
direkte Nutzung der generischen Systemprogrammierschnittstelle des BS.
meist in Programmiersprache C.
generischen Systemprogrammierschnittstelle bedeutet eine allgemeine Schnitt-
stelle, d.h. alle Applikationen haben die gleiche Schnittstelle; im Gegensatz zu
anwendungsspezifischen Schnittstellen.

• Qualitätskriterien können z.B. sein:

– Zuverlässigkeit der durchgeführten Berechnung (Behandlung von System-


crashs, Netzausfällen, fehlerhafter Nachrichtenübermittlung etc.).
– Effizienz und Performanz einerseits systemglobal, d.h. es wird versucht,
das System optimal auszulasten, andererseits Auftrags-lokal, z.B. es wird
versucht, zu garantieren, dass eine Auftragsbearbeitung nicht übergebührlich
lange verzögert wird. Dabei soll auch die unfaire Behandlung von Prozessen
vermieden werden, d.h. jeder Prozess soll nach einer gewissen Wartezeit
rechnen können.
– Einhaltung von Realzeitanforderungen: zeitkritische Aufträge besitzen z.B.
eine Deadline bis zu der sie ausgeführt sein müssen. Ein Beispiel sind
Videoströme, die die Frameraten für die Anzeige von Bildern einhalten
müssen.
– Durchsetzung von Sicherheitsanforderungen: Schutz der Daten und Informa-
tionen vor unberechtigten Zugriffen und Einsichtnahme.
3
Welche Perspektive ist zukünftig relevant? Am mächtigsten ist derjenige, der die
Informationen verwaltet - Google? Oder am mächtigsten ist derjenige, der die sozialen
Beziehungen verwaltet - Facebook?

19
Schlichter, TU München 2.1. BETRIEBSSYSTEM - ÜBERBLICK

– Benutzerfreundlichkeit: bequeme Formulierungsmöglichkeit von Benutzer-


aufträgen.

2.1.3 Hardwarekomponenten
Das Betriebssystem ist sehr eng mit der Hardware des Rechensystems verknüpft,
auf dem es ausgeführt wird. Es erweitert den Befehlssatz des Rechners und
verwaltet seine Ressourcen.
Deshalb an dieser Stelle einen kurzen Überblick über den Aufbau eines
Rechensystems. (Detaillierte Erklärungen zum Aufbau von Rechensystemen
wurden in der Vorlesung Einführung in die Technischen Grundlagen behandelt.)
Als Beispiel wird hier kurz der Aufbau eines Intel PC’s präsentiert. Daraus erkennt
man, dass ein Rechner unterschiedlicher Bussysteme mit unterschiedlichen
Geschwindigkeiten integriert. Daneben gibt es noch weitere Busse wie SCSI für
den Anschluss Festplatten und anderen Geräten, sowie IEEE 1394 - Firewire für
den Anschluss von Multimedia Geräten z.B. digitale Kamera.

Systembus Speicherbus

CPU Northbridge Arbeitsspeicher

USB (Maus,
Tastatur)
AGP
EA-Karte
Grafik
PCI Bus
EA-Karte
Sound
IDE
Festplatte
Southbridge

ISA Bus

EA-Karte
LAN Drucker

20
Schlichter, TU München 2.1. BETRIEBSSYSTEM - ÜBERBLICK

PCI = Peripheral Component Interconnect


ISA = Industry Standard Architecture
USB = Universal Serial Bus
AGP = Accelerated Graphics Port (Anschluss von schnellen Grafikkarten).
Der AGP Bus soll den Zugriff schneller Grafikkarten auf den Arbeitsspeicher
beschleunigen. Alternativ existiert PCI-Express.
Der Systembus unterteilt sich weiterhin in den Adressbus, Datenbus und
Steuerbus. Die Anzahl der parallelen Leitungen des Adressbusses (32bit oder
64bit) bestimmen auch die maximale Größe des Programmadressraums. Intel
bezeichnet die Southbridge auch als I/O Controller Hub, die Northbridge als
Memory Controller Hub.

2.1.4 Betriebsarten
Beim Betrieb von Rechenanlagen können bzgl. des Zusammenwirkens von Be-
nutzer und Rechensystem die Betriebsweisen Stapelverarbeitung, Dialogbetrieb,
Transaktionsbetrieb und Echtzeitbetrieb unterschieden werden.

• Stapelbetrieb
Das Rechensystem verarbeitet Ströme von Auftragspaketen (engl. batch pro-
cessing). Ein Benutzer deklariert vollständig alle Teile eines Auftragspaketes,
bevor es in das System eingegeben wird. Anschließend wird das Auftragspa-
ket durch das Rechensystem abgearbeitet, ohne dass der Benutzer noch Ein-
flussmöglichkeiten hat. Bei Auftreten eines Fehlers muss i.a. nach der Korrektur
das gesamte Auftragspaket nochmals gestartet werden. Auftragspakete können
in Unterabschnitte zerfallen, z.B. Teilprogrammabläufe. Diese Betriebsart war
in den Anfängen von Rechenanlage sehr verbreitet (Nutzung von Lochkarten
und Lochstreifen).

• Dialogbetrieb
Im Dialogbetrieb (engl. Timesharing) erteilt der Benutzer dem Betriebssystem
einen Auftrag nach dem anderen im Dialog. Innerhalb eines Benutzerauftrags
findet eine Interaktion zwischen dem Benutzer und der Systemumgebung
statt (z.B. Eingabe weiterer Daten, Ausgabe von Zwischenergebnissen). Der
Dialogbetrieb erfordert eine besondere Gestaltung der Benutzerschnittstelle.
Oft wird Betriebssystem und Benutzerschnittstelle (engl. user interface) in
einem Atemzug genannt und auch oft gleichgesetzt. Beide sind jedoch getrennt
voneinander zusehen. Beispielsweise existierten mit dem X11-Windowsystem
und Sun Windowsystem (auf der Basis von Postscript) zwei unterschiedliche
Benutzerschnittstellen auf demselben Betriebssystem.

21
Schlichter, TU München 2.1. BETRIEBSSYSTEM - ÜBERBLICK

• Transaktionsbetrieb
Bewältigung einer Vielzahl von kleinen Aufgaben in kürzester Zeit, z.B.
Banküberweisungen oder Buchungen. Dabei muss die Bearbeitung folgende
Kriterien, wie sie auch von Datenbanken bekannt sind, erfüllen: Atomarität,
Konsistenz, Isolation, Dauerhaftigkeit (engl. ACID), d.h. die Bearbeitung muss
entweder vollständig ablaufen oder keinerlei Änderung verursachen (Alles-
oder-nichts Prinzip).
• Echtzeitbetrieb
In der Prozesssteuerung (automatische Fertigungssysteme, Roboter) und im
Multimediabereich sind die Reaktionszeiten des Betriebssystems von großer
Bedeutung. Dies erfordert spezielle Mechanismen bei der Behandlung von
Ereignissen und Unterbrechungen sowie der CPU-Zuteilung an rechenbereite
Prozesse / Threads. Beispielsweise ein Videoserver (bei Nutzung des Streaming
Ansatzes) benötigt ein Betriebssystem, das gewisse Echtzeitfähigkeiten hat.
Videos müssen mit einer bestimmten Geschwindigkeit abgespielt werden. Die
Bilder dürfen an das Abspielprogramm nicht zu langsam (ansonsten ruckelt
das Videobild) und nicht zu schnell ausgeliefert werden (sonst gehen bei
Pufferüberlauf Videobilder verloren). Unterscheidung zwischen
harte Echtzeitsysteme: Reaktionszeit darf nicht überschritten werden. Eine
zu späte Reaktion kann zu ernsthaften Problemen führen, z.B. bei der
Steuerung eines Atomreaktors.
weiche Echtzeitsysteme: gewisse Toleranzen bzgl. der Abweichung
sind erlaubt. Bei Audio und Multimedia-Systemen werden gewisse
Abweichungen von der Reaktionszeit toleriert.

2.1.5 Historie
Betriebssysteme haben sich über die Jahre hinweg ständig weiterentwickelt.
Faktoren für die Entwicklung von Betriebssystemen:
Fortschritte der Hardwaretechnologie.
Preis - Leistungs - Verhältnis.
Übergang von numerischer Berechnung zur allgemeinen
Informationsverarbeitung.
neue Anwendungsbereiche und Öffnung für Nichspezialisten. Ein Beispiel
ist die Nutzung von Rechnern als eingebettete Systeme im Auto sowie ihre
Nutzung in Mobiltelefonen oder Smartphones.

• 1. Generation 1945 - 55: Arbeiten an leerer Rechenanlage. Es war praktisch


kein Betriebssystem vorhanden. Es gab ein sehr rudimentäres Betriebssystem

22
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

(nur Steuerung der Ein-/Ausgabe, es wird deshalb auch nicht als Betriebssystem
bezeichnet). Ein Benutzer hatte den Rechner für sich. Die Programmierung
erfolgte in Maschinensprache. Lochkarten und Lochstreifen brachten eine
gewisse Verbesserung. Beispielrechner sind die Zuse Z3, ENIAC, oder die
PERM an der TUM.

• 2. Generation 1955 - 65: Stapelbetrieb ohne parallele Verarbeitung von


Programmen. Programme wurden als Lochkartenstapel eingelesen; auf diese
Weise wurden Jobs sequentiell abgearbeitet. Damals gab es auch noch den
Beruf des Operateurs. Beispiel: Betriebssystem der Telefunken TR4.

• 3. Generation 1965 - 80: Mehrprogrammbetrieb, Spooling auf Platten, Nutzung


von Dateisystemen, Dialogbetrieb. Unterstützung von Unterbrechungen und
ASP-Organisation für Mehrprogrammbetrieb. Beispiele: Multics (Vorläufer
von Unix), Unix V6, DEC VMS.

• 4. Generation ab 1980: Integration des Personal Computing, graphische Be-


nutzeroberflächen, Netzwerkunterstützung, Multimedia. Beispiele: Windows,
MacOS, Linux.

• 5. Generation ab 2000: eingebettete Systeme und Chipkarten, Unterstützung


mobiler Plattformen für ubiquitäre Nutzung, BS-Unterstützung gemäß dem
Schlagwort: Das Netz ist der Computer. Beispiele: ChromeOS, Android, iOS.

Neben den Betriebssystemen für Großrechner, Server und Arbeitsplatzrechner


haben sich auch Betriebsysteme für eingebettete Systeme und Chipkarten ent-
wickelt. Diese Systeme besitzen meist die Eigenschaften von Echtzeitbetriebssy-
stemen, sind aber zusätzlich noch auf geringe Größe, einen kleinen Arbeitspeicher
und geringen Stromverbrauch ausgelegt.

2.2 Betriebssystem-Architektur
In der Praxis findet man einige verschiedene BS-Architekturkonzepte, wobei der
monolithische Ansatz und zunehmend auch der Mikrokern-Ansatz am weitesten
verbreitet sind.

2.2.1 Monolithischer Ansatz


Das Betriebssystem besteht aus einer umfangreichen Menge an Funktionen,
die sich bei Bedarf gegenseitig aufrufen können. Die Funktionen werden in

23
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

einem großen BS-Kern zusammengefasst. Der BS-Kern wird durch Aufruf


von Systemdiensten betreten. Der BS-Kern hat i.a. nur wenig Struktur. Als
Grundstruktur kann man von 3 Schichten ausgehen: a) die Hauptprozedur, b)
den Systemfunktionen, die von der Hauptprozedur aufgerufen werden, sowie c)
den Hilfsfunktionen. Unix kann als BS mit einer monolithischen Architektur
betrachtet werden.
BS-Kern arbeitet im Systemmodus.
Er hat hohe Ablaufpriorität. Oft läuft er unter kompletter Unterbrechungssper-
re.
Er ist permanent im Arbeitsspeicher.

Anwendung Anwendung
Benutzerprozess Benutzerprozess
Benutzer-Modus
(User Mode)

System-Modus
Systemdienste (Kernel Mode)
(Hauptprozedur)

Hilfs
funktionen

Hardware

• komplexe, monolithische Betriebssystem sind sehr schwierig zu warten und


zu erweitern. Es ist oft schwierig nachzuvollziehen, welche Konsequenzen
Änderungen von Systemdiensten bzw. Hilfsfunktionen im Betriebssystem
nach sich ziehen. Dies bezieht sich vor allem auf die Synchronisation von
nebenläufigen Zugriffen und die Nutzung von Ressourcen. Es sind oft viele
Detailkenntnisse des gesamten Betriebssystems notwendig.

• Geschichtete Systeme

24
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

Einen Ausweg aus der Problematik monolithischer Systeme bieten geschichtete


Systeme;
das Betriebssystem besteht aus einer Hierarchie abstrakter Maschinen.
Jede Schicht hat wohldefinierte Schnittstellen und eine wohldefinierte
Aufgabe
⇒ Reduktion der Systemkomplexität.
Geschichtete Systeme ermöglichen die Realisierung von Systemfamilien, d.h.
ein neues Familienmitglied (und damit eine neue Plattform für Anwendungen)
kann mit vergleichsweise geringem Aufwand auf irgendeiner abstrakten
Maschine aufgesetzt werden. Unter der Voraussetzung, dass die Schnittstellen
präzis und in sich konsistent festgelegt wurden, kann jede abstrakte Maschine
unabhängig von anderen erstellt werden. Dies bietet auch die Möglichkeit,
einzelne Schichten durch neue Implementierungen zu ersetzen, solange
Schnittstelle und Aufgabe eingehalten werden. Gerade im Bereich der
Rechnernetze spielt das Schichtenkonzept eine sehr wichtige Rolle (siehe
ISO/OSI Referenzmodell oder TCP/IP Referenzmodell).

Anwendungen

Funktionsschnittstelle
Schicht N
abstrakte Maschine N

Funktionsschnittstelle
Schicht N-1
abstrakte Maschine N - 1

Funktionsschnittstelle
Schicht 0
abstrakte Maschine 0

Rechnerhardware

25
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

2.2.2 Mikrokern-Ansatz
Der Trend moderner Betriebssystem geht hin zu einem Mikrokern-Ansatz.
Im Mikrokern sind nur mehr Basismechanismen, z.B. Prozesskommunikation
(Austausch von Nachrichten), CPU-Zuteilung. Möglichst viele Subsysteme
sind als Systemprozesse außerhalb des Mikrokerns realisiert. Sie laufen im
Benutzermodus ab, z.B. Dateisystem, Speicherverwaltung. Verwaltungsdienste,
z.B. Strategien zur Speicherverwaltung oder Prozessverwaltung (z.B. Zuteilung
von Prioritäten) laufen im Benutzermodus. Man spricht im Zusammenhang
mit diesem Ansatz auch von einer Client/Server-Struktur. Systemfunktionen
werden als Serverprozesse im Benutzermodus ausgeführt. Benötigt ein Prozess
(Client) eine Dienstleistung schickt er eine Anforderung an einen anderen
Prozess (Server), der die Dienstleistung erfüllt und die Antwort an den Client
zurückgibt. Die Kommunikation zwischen den beteiligten Prozessen erfolgt über
den Mikrokern. Durch die Ausgliederung in Serverprozesse ist eine Trennung von
Mechanismus und Strategie möglich. Die Strategien werden in Serverprozessen
im Benutzermodus realisiert, während der Mikrokern wenige Basismechanismen
umfasst. Ziel ist, das der BS-Kern nur für kurze Zeit blockiert sein soll.
Einfaches Austauschen von Subsysteme ⇒ ermöglicht die einfache Anpas-
sung von Systemanforderungen.

Benutzer Memory Netzwerk


Programm Server Server

Prozess File Display Benutzer-Modus


Server Server Server (User Mode)

Anforderung System-Modus
(Kernel Mode)

Mikrokern

Antwort

Hardware

Vorteile des Mikrokernansatzes sind


Bereitstellung einer einheitlichen Schnittstelle für alle Requests,
Flexibilität, Erweiterbarkeit, Portabilität (Prozessor-spezifischen Codeanteile
sind im Mikrokern),
leichte Unterstützung verteilter Systeme.

26
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

Nachteil ist der zusätzliche Zeitaufwand, da die Systemkomponenten über


Nachrichten miteinander kommunizieren, die über den Mikrokern propagiert
werden.

2.2.3 Beispiel: BS-Architekturen


Unix Betriebssystem

Die nachfolgende Abbildung skizziert die wesentlichen Komponenten des


Unix Betriebssystems. Der Unix-BS-Kern enthält die Datei-, Prozess- und
Prozessorverwaltung, die Speicherverwaltung und die Geräte-Treiber. Zur
Nutzung beispielsweise der Systemdienste des Dateisystems bietet das BS u.a.
die Dienste open, read, write, close an. Bibliotheken enthalten u.a. die
Routinen für Standard-Ein/Ausgabe sowie malloc-Funktion zur dynamischen
Speicherverwaltung.

Bibliotheken Benutzungs-
Programme Shells
(z.B. lib.a) schnittstelle

Systemschnittstelle Programmier-
u.a. open,close, read, write; fork, exec, kill, ... schnittstelle

Datei Prozess Prozessor


System verwaltung verwaltung
Betriebs-
systemkern
Unterbrechungs Arbeitsspeicher
Geräte Treiber
behandlung verwaltung

Hardware

Windows NT Betriebssystem

Mit Hilfe von HAL wird versucht, die meisten Maschinenabhängigkeiten zu


verbergen. HAL präsentiert dem restlichen BS abstrakte Hardwaregeräte (z.B.
Systembus, Arbeitsspeicher etc). Der Kernel ist kein Mikrokern. Zielsetzung des
Kernels ist die vollständige Hardware-Unabhängigkeit, und damit sehr portable

27
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

BS-Komponenten höherer Ebene. Der Kernel besteht aus Control-Objects (z.B.


primitive Prozessobjekte, Unterbrechungsobjekte) und Dispatcher-Objects (z.B.
Semaphore, Ereignisse, Timer). Der Kernel ist auch zuständig für das Scheduling
von Threads. Der Objektmanager verwaltet alle Systemobjekte (z.B. Prozesse,
Threads, Dateien, Semaphore). Der Prozessmanager ist für die Erzeugung,
Verwaltung und Löschung von Prozessen und Threads verantwortlich. Die Local
Procedure Call Facility realisiert eine effiziente Interprozess-Kommunikation
zwischen den Subsystemen. Die System Services stellt die Schnittstelle zum
Executive bereit. Daneben gibt es noch einige weitere Manager wie Power
Manager, Cache Manager und Plug-and-play Manager. 4

Logon
OS/2 Client Win32 Client Posix Client Applications
Process

Protected
OS/2 Posix Subsysteme
Subsystem Subsystem (Servers)
Security Win32
Subsystem Subsystem
Systemaufrufe

System Interface (DLL)


User Mode

Kernel Mode
System Services
I/O Manager
Local Virtual
Object Security Process NT Executive
Procedure Memory File
Manager Manager Manager
Call Facility Manager Systems
Cache Mgr
Device
Kernel Drivers
Network
Drivers
Hardware Abstraction Layer (HAL)

Hardware Manipulation

Hardware

Nachfolgende Betriebssystem Versionen wie Windows XP, Windows Vista, Win-


dows 7 und Windows 8 haben auf dieser Abstraktionsebene eine ähnliche Struk-
tur. Windows 10 besitzt eine Architekturmischform: Elemente der Mikrokernidee
als auch der geschichteten Strukturierung. Windows 10 ist in C und z.T in C++
programmiert.
4
Eine ausführliche Behandlung von Windows 2000 ist in [Tanenbaum2001, S763] zu finden.

28
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

Linux Betriebssystem

Linux begann Anfang der 1990er Jahre als eine Unix Variante für den IBM PC;
erste Version durch Linus Torvalds (1991).
Linux ist frei und Quellcode ist verfügbar.
kollaborative Weiterentwicklung durch Open Source Community.

• kein Mikrokern-Ansatz, jedoch modulare Struktur.


dynamic linking. Linux besteht aus einer Sammlung von Moduln, die
dynamisch geladen und ausgeladen werden können (je nach Bedarf). Ein
Modul des BS-Kerns kann bei Bedarf in den Kern geladen und verlinkt
werden. Auf diese Weise bleiben die Vorteile des Mikrokern-Ansatzes
erhalten. Jederzeit kann ein Modul wieder ausgeladen, und damit vom
aktuellen BS-Kern entfernt werden.
Module sind hierarchisch organisiert. Zwischen Moduln auf unterschiedli-
chen Schichten bestehen Dienstaufrufbeziehungen, d.h. ein Client Modul
referenziert eine Bibliothek der unteren Schicht.
• jeder Modul ist durch 2 Datenstrukturen beschrieben.
Modulbeschreibung, u.a Modulname, Größe, Zahl der exportierten Symbo-
le und referenzierte Module. Die Modulbeschreibungen sind untereinander
zu einer Liste verbunden.
Symbol-Tabelle. Liste der Symbole, die im Modul definiert sind und durch
andere Komponenten verwendet werden.

29
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

Prozesse user mode

System kernel mode


Signals
calls

Processes & Network


File system
scheduler protocols

Virtual device driver Device driver Network


memory (Char) (Block) driver

Traps Physical
Interrupt
faults memory

Network interface
CPU Main memory terminal disk
controller

Jeder Prozess kann aus ein oder mehreren Threads (Aktivitätssequenzen)


bestehen. Der Kernel besteht aus einer Sammlung von Komponenten, wobei
die Pfeile die Hauptinteraktionen zwischen den Komponenten darstellen. Jede
Komponente wird natürlich auf der CPU ausgeführt.

Signals: Aufruf eines Prozesses durch den Kernel (z.B. um Prozess von einem
Fehler zu unterrichten (Division durch 0).

Traps: Unterbrechungen und Fehler, die durch CPU erzeugt werden.

2.2.4 Systemaufrufe
Die Schnittstelle zwischen dem Betriebssystem und den Benutzerprogrammen
wird durch eine Menge von Systemaufrufen (engl. system calls) gebildet. Sie
stellen für Benutzerprogramme die einzige Schicht zum Zugriff auf Dienste des
Betriebssystems and damit zur Nutzung der Hardware dar.

• in Benutzerprogrammen werden Systemaufrufe nicht direkt verwendet, sondern


dies erfolgt über die Einbindung von Systembibliotheken, z.B. C-Library. Nach
dem Übersetzen des Benutzerprogramms wird dieses i.a. mit einer C-Library

30
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

(z.B. glibc bei Linux) gelinkt, bevor es ausgeführt wird. Die Aufgabe dieser
Bibliothek ist es, Standard-C-Aufrufe in Systemaufrufe umzusetzen.

main ( ) {
--------------
printf ("hello“); Anwendung
--------------
}
Benutzermodus
-------------
printf erledigt Formatierung
-------------- Bibliotheksfunktion
Systemaufruf

-------------
write (1, "hello“, 5); Betriebssystemkern
Systemmodus
--------------

Hardware
Z.B. Zugriff auf Festplatte

Im write-Befehl wird als 1. Parameter das Standard-Ausgabemedium und als


3. Parameter die Stringlänge angegeben.
• Systemaufruf führt zum Übergang vom Benutzermodus in den Systemmodus.
• Beispiele von Systemaufrufen
Prozessmanagement: fork, waitpid, exit. fork (Erzeugen eines neuen
Kindprozesses), waitpid (Warten auf Beendigung des Kindes), exit (Prozess
beenden).
Dateimanagement: open, close, read, write.
Verzeichnismanagement: mkdir, rmdir, link, mount.
Gerätemanagement: request/release device, get/set device attributes.
Kommunikationsmanagement: send/receive messages, create/delete
connection.
Ein Systemaufruf wird realisiert mittels eines TRAP-Befehls (SysCall), der
als Parameter die gewünschte Systemfunktion hat. Der TRAP-Befehl führt
zu einer Unterbrechung des aktuellen Ablaufes und zu einem Sprung in den
BS-Kern, wo die Unterbrechungsbehandlung nach dem Retten des aktuellen
Ausführungskontexts zum gewünschten Dienst springt.

31
Schlichter, TU München 2.2. BETRIEBSSYSTEM-ARCHITEKTUR

2.2.5 Virtuelle Maschine


Das Konzept der Virtualisierung erlaubt die Abstraktion der Hardware eines
einzelnen Rechners (CPU, Festplatte, Netzschnittstelle) auf unterschiedliche
Ausführungsumgebungen. Eine wichtige Anwendung dieses Konzepts ist die
gleichzeitige Bereitstellung mehrerer Betriebssysteme auf einem Rechner.
Isolierung der virtuellen Maschinen. Es gibt keine direkte gemeinsame Nut-
zung von Ressourcen; deshalb gibt es keine Probleme bzgl. konkurrierender
Zugriffe verschiedener virtueller Maschinen.
gemeinsame Nutzung von Dateien möglich. Teile einer Festplatte können für
die gemeinsame Nutzung eingerichtet werden.
Beispiel VMware (URL: [Link]

Applikation Applikation Applikation

Gast-Betriebssystem Gast-Betriebssystem
(free BSD) (Windows XP)

virtuelle CPU virtuelle CPU


virtueller Speicher virtueller Speicher
virtuelle Geräte virtuelle Geräte

Virtualisierungsschicht

Host Betriebssystem
(Linux)

Hardware
CPU Arbeitsspeicher E/A-Geräte

In diesem Fall ist Linux ist das native Host-Betriebssystem. Die Virtualisierungs-
schicht abstrahiert die physikalische Hardware zu isolierten virtuellen Maschinen,
auf denen jeweils Gast-Betriebssysteme laufen.
Die Java Virtual Machine (JVM) spezifiziert einen abstrakten Computer, auf dem
Java Programme ausgeführt werden. JVM ist ein Softwaresystem, das auf dem
Host-Betriebssystem ausgeführt wird.

32
Schlichter, TU München 2.3. HARDWARENAHE PROGRAMME

2.3 Hardwarenahe Programme


Zur Erleichterung werden hardwarenahe Programme für ein Rechensystem nicht
als ausführbare Maschinenprogramme (Folge von Befehlswörtern) realisiert,
sondern mit Hilfe von Assemblerprogrammen.

2.3.1 Definitionen
Maschinenschnittstelle

Als Maschinenschnittstelle 5 bezeichnet man die Gesamtheit aller Datenobjekte


und Operationen der reinen Hardwarearchitektur (auch Programmierschnittstellen
der Maschine).

• Folge von Maschinenbefehlen ist auf dieser Ebene eine Folge von Binärzeichen.
Auf dieser Ebene müsste man insbesondere die Befehle der Maschine als reine
Folge von Binärzeichen (Befehlswörter) schreiben; diese Schnittstelle ist sehr
programmier-unfreundlich.

Assemblerschnittstelle

Die Assemblerschnittstelle ist die eigentliche maschinennahe (konkrete) Program-


mierschnittstelle. Sie erlaubt, alle Befehle, Adressen und Datenobjekte der reinen
Hardware darzustellen.

• Verwendung von Namen für Adressen und Operationen. Assemblersprachen


sind eine geringfügige Erweiterung von reinen Maschinensprachen. Zur
bequemeren Nutzung werden u.a. symbolische Adressen (z.B. Identifikatoren)
und symbolische Namen für Operationen (z.B. ADD für Addition) verwendet.

Assembler

Ein Assembler ist ein Programm, das die Aufgabe hat,

1. Assemblerbefehle in Maschinencode zu transformieren,

2. symbolischen Namen Maschinenadressen zu zuweisen, sowie

3. ein Objektprogramm zu erzeugen.


5
siehe die Vorlesung "Einführung Technische Grundlagen"

33
Schlichter, TU München 2.3. HARDWARENAHE PROGRAMME

2.3.2 Programmaufbereitung
Wir wollen eine grobe Vorstellung der Funktion eines Assemblers, Binders und
Laders vermitteln. Binder/Lader sind i.d.R. Bestandteil des Betriebssystems. Hier
steht nicht die Konstruktion solcher Komponenten (Systemprogrammierung),
sondern deren Aufgaben und Funktionen im Vordergrund.

Programm

z.B. Java Programm


Compiler

Assembler
Programm

Assembler

Bindemodul Bindemodul

Binder symbolische Bezüge


nach außen
Lademodul offene Referenzen

Maschinenbefehle mit
relativen Adressen Lader

Maschinenprogramm im
Arbeitsspeicher

Beispiel Unix Compilersystem

Aufruf:
unix> gcc -o hello hello.c

34
Schlichter, TU München 2.3. HARDWARENAHE PROGRAMME

hello.c preprocessor hello.i compiler hello.s assembler


Source (cpp) Modified Source (ccl) Assembly (as)
Program Program Program
(Text) (Text) (Text)
hello.o

relocatable object
program (Binary)
printf.o

hello linker
(ld)
executable
object program
(Binary)

Transformation in 4 Phasen

• Preprocessor: Aufbereitung. Der Preprocessor (cpp) modifiziert das ursprüngli-


che C Programm gemäß den Anweisungen, die mit einem # Zeichen beginnen,
z.B. die Anweisung #include <studio.h> führt zur Einfügung der header Datei
studio.h. In C können sie am Anfang mittels "#def" Makros definieren, z.B. an-
stelle eines Zahlenwerts definieren sie einen Namen, der überall im Programm
dann verwendet wird. Möchten sie dann den Zahlenwert ändern, muss dies nur
an einer Stelle erfolgen. Der Preprocessor ersetzt vor dem Übersetzen dann den
definierten Name durch den zugeordneten Zahlenwert.
• Compiler: Übersetzer von C nach Assembler. Der Compiler (ccl) übersetzt
hello.i in die Text Datei hello.s. Jede Anweisung in Assembler beschreibt
eine maschinen-sprachliche Instruktion im Textformat. Die Assemblersprache
ist gemeinsam für die verschiedenen Compiler unterschiedlicher höherer
Programmiersprachen.
• Assembler: Übersetzer von Assembler nach Maschinensprache; Generierung
des Objektprogramms. 6
Der Assembler (as) übersetzt hello.s in Maschineninstruktionen und paketiert
sie in verschiebbare Objektprogramme.
• Linker (Binder): Nachbearbeitung und Kombinationen verschiedener Module.
In der Linker Phase werden notwendige Standardfunktionen wie printf
integriert. Der Linker ld führt die Kombination der einzelnen Module durch.
Ergebnis ist die ausführbare Datei hello, die nun in den Arbeitsspeicher geladen
und ausgeführt werden kann.
6
Dieser Teil und der Aufbau von Objektprogramms ist Teil der Vorlesung "Einführung in die
Technische Informatik".

35
Schlichter, TU München 2.3. HARDWARENAHE PROGRAMME

2.3.3 Binder und Lader


Ein Assembler-Programm kann aus mehreren logischen Einheiten bestehen, die
vom Assembler als einzelne, unabhängige Einheiten (Bindemoduln) transformiert
werden. In Informatik I wurde bereits Modularisierung als wichtiges Konstrukti-
onsprinzip behandelt. Aspekte sind: Problem wird in Teilprobleme zerlegt, Bau-
steine als Lösung von Teilproblemen, Wiederverwendung von Bausteinen, Biblio-
theken (engl. library). Modularisierung ist besonders bei der Entwicklung großer
Programme sehr wichtig.

Binder

Der Binder (engl. linker) hat die Aufgabe, aus einer Menge von einzelnen
Bindemoduln ein ausführfähiges Ladeprogramm zu erzeugen, indem die noch
offenen externen Referenzen aufgelöst werden.

• Binde-Module
Der Assembler erzeugt Code, der jeweils relativ zum Modul-Anfang adressiert.

Segment 1 Segment 2 Segment n


Assemblermodule
JUMP start start:

assemblieren

Lade Lade Lade


objekt 1 objekt 2 objekt n Bindemodule

Das Zusammenfügen der einzelnen Ladeobjekte zu einem ausführfähigen


Programm ist die Aufgabe des Binders (Linker).

– Externe Referenzen
In einem Modul Mi können Referenzen auf Daten/Symbole auftreten, wobei
die Daten/Symbole in einem anderen Modul Mj definiert werden. Beispiel:
Symbol start wird in Segment 1 verwendet, und erst in Segment n definiert.

36
Schlichter, TU München 2.3. HARDWARENAHE PROGRAMME

Solche Referenzen heißen externe Referenzen. Assembler kann Referenzen


nicht auflösen, Assembler besitzt keine Informationen darüber, wo sich die
einzelnen Segmente zur Ausführungszeit im Arbeitsspeicher befinden.
– Behandlung externer Referenzen
Für jede externe Referenz erzeugt der Assembler Informationen, die
es dem Binder ermöglicht, aus den Einzelmoduln ein ausführfähiges
Gesamtprogramm zu erzeugen, d.h. die → Referenzen (siehe Seite 39)
aufzulösen. Module können unabhängig assembliert werden: keine Vorgabe
über zeitliche Reihenfolge.
∗ Der Programmierer gibt durch spezielle Assembler-Direktiven für jeden
Modul an, welche Symbole und Namen des Moduls von außen verwendet
werden können, d.h. exportiert werden.
∗ Extern referenzierte Symbole in einem Modul, sogenannte importierte
Symbole, müssen durch Assembler-Steuerungsanweisungen im Modul
markiert werden.
∗ Assembler erzeugt ausgehend von diesen Steuerinformationen spezielle
Einträge im Objekt-Programm.
◦ Für exportierte Symbole: ein Eintrag (gekennzeichnet z.B. durch ein
D (=define)), der den Namen und die relative Adresse des Symbols
umfasst. Aufbau des Define-Eintrag:
"Kennung D, Name des exportierten Symbols, relative Adresse des
Symbols im definierenden Segment".
◦ Für importierte Symbole: ein Eintrag (gekennzeichnet z.B. durch ein R
(=refer)), der den Namen des importierten Symbols umfasst. Adressen
können hierfür noch nicht eingetragen werden. Aufbau des Refer-
Eintrag:
"Kennung R, Name des importierten Symbols".
∗ Findet der Assembler eine externe Referenz, so trägt er in dem
erzeugten Code die Adresse 0 ein. Gleichzeitig erzeugt er einen
Modifikations-Eintrag (gekennzeichnet z.B. durch ein M (=modify)) im
Objektprogramm, der für den Binder die benötigte Information enthält:
Angabe, welches Auftreten der Referenz zu modifizieren ist und
Name des externen Symbols.
Auftreten bezieht sich hier auf die Angabe, wo im Maschinenbefehl die
externe Referenz als Operand auftritt. Aufbau Modifikations-Eintrag:
"Kennung M, Startadresse des zu modif. Adressfeldes, importiertes
Symbol".

37
Schlichter, TU München 2.3. HARDWARENAHE PROGRAMME

Lader

Ein Lader (engl. loader) ist ein Systemprogramm, das die Aufgabe hat,
Objektprogramme in den Speicher zu laden und deren Ausführung anzustoßen.

• Eigenschaften
In einem System ist i.d.R. nur ein Lader vorhanden, so dass Programme
unterschiedlicher Quellsprachen in ein einheitliches Objektprogramm-Format
transformiert werden müssen.

– Viele Lader beinhalten gleichzeitig Binde-Funktion. Binde/Lader sind


heutzutage typische Komponenten in Rechensystemen. Binde/Lader sind
Bestandteil der Dienste, die ein Betriebssystem anbietet.
∗ Binde/Lader: Programmmodule werden zur Ladezeit gebunden.
∗ Lauf 1: Zuweisung von Adressen zu externen Referenzen (Auflösen von
Referenzen).
∗ Lauf 2: Binden, Verschieben, Laden. Hierbei werden die Modify-Einträge
aufgelöst, d.h. die Adressen der extern referenzierten Symbole werden
eingetragen.
– Absoluter Lader
Aufgaben eines absoluten Laders; ein Lauf genügt.
∗ Prüfe, ob der für das Programm vorgesehene Speicher groß genug
ist. Jedes Objektprogramm hat einen Header, in dem u.a. auch die
Programmgröße verzeichnet ist.
∗ Die Text-Einträge im Objekt-Programm werden gelesen und der Code
wird an die dort angegebenen, absoluten Adressen des Speichers geladen.
∗ Beim Lesen des END-Eintrags springt der Lader zur angegebenen Start-
Adresse des Programms, um die Programmausführung zu starten. Ein ab-
soluter Lader hat jedoch eine Reihe von Problemen: a) Programmierer
muss Lade-Adressen explizit angeben, b) Probleme bei Multiprogram-
ming: Ladeadresse nicht vorab bekannt, c) Verschiebbarkeitsforderungen
können nicht erfüllt werden, und d) Probleme bei Wiederverwendbar-
keit von z.B. Bibliotheksfunktionen, wenn diese vorab vergebene absolute
Adressen besitzen.
– Relativer Lader
Laden verschiebbarer Objekt-Programme, wobei die Information, welche
Adressen neu zu berechnen sind, vom Assembler zur Verfügung ge-
stellt werden, z.B. durch Modifikations-Einträge im Objekt-Programm.

38
Schlichter, TU München 2.3. HARDWARENAHE PROGRAMME

Modifikations-Einträge sind jedoch nicht für jede Maschinen-Architektur ge-


eignet. Maschinen, die z.B. keine relative Adressierung kennen, erfordern,
dass u.U. fast alle Adressen neu berechnet werden müssen durch den Lader.
Entsprechend umfangreich sind dann die benötigten Modifikations-Einträge
und entsprechend groß wird dann das Objekt-Programm. Die Verschiebbar-
keit wird in Zusammenhang mit der Seitenadressierung detaillierter behan-
delt.

Datenstrukturen eines Binde/Laders

Der Binder benötigt eine Tabelle ESTAB ("external symbol table") für die
aufzulösenden externen Referenzen, wenn im Programm externe Referenzen
auftreten. Der Tabelleneintrag besteht aus [Symbol, Adresse]. ESTAB hat analoge
Aufgaben wie die Symboltabelle des Assemblers. Der Tabelleneintrag beinhaltet
u.U. auch den Modul, in dem das Symbol definiert ist.

• Hilfsvariable

– PADR: Startadresse im Speicher, wohin das gebundene Programm geladen


werden soll. Der Wert wird i.d.R. durch das Betriebssystem ermittelt und
dem Lader mitgeteilt.
– CSADR: Startadresse des jeweils bearbeiteten Moduls; dieser Wert wird zu
den Relativ-Adressen des jeweiligen Moduls hinzu addiert. CSADR steht für
control section adr.

• Algorithmus zum Lauf 1


Festlegen der Startadresse PADR des zu ladenden Programms (also wohin es in
den Speicher geladen werden soll). Jedes Modul wie folgt bearbeiten:

– Header-Eintrag lesen und Eintrag in Symboltabelle ESTAB:


[Name des Moduls, Startadr. (=CSADR) des Moduls].
Beim ersten Modul gilt: CSADR=PADR.
– Lesen von Export-Einträgen (Symbol-Definitionen) im Objekt-Programm;
alle auftretenden Symbole in ESTAB eintragen, wobei gilt:
[symbolischer-Name, Adresse = Relativadr + CSADR].
Lesen der Assemblerbefehle; bei externen Referenzen werden jeweils
Modifikationseinträge hinzugefügt.
– Lesen des END-Eintrags: CSADR = CSADR_alt + Länge des Segments
(steht als Info im Header); Bearbeiten des nächsten Moduls mit der neuen
Anfangsadresse CSADR.

39
Schlichter, TU München 2.3. HARDWARENAHE PROGRAMME

• Algorithmus zum Lauf 2


Nach Lauf 1 enthält ESTAB alle externen Symbole, die in Modulen definiert
wurden zusammen mit deren Adresse. Der 2. Lauf erledigt die Funktionen
Laden, Verschieben, Binden.

– Sukzessives Lesen der Text-Einträge aus Objektprogramm; Abspeichern des


Codes an "Startadresse des Segments + Relativadresse" im Eintrag. Die
Startadresse des Segments ist CSADR und ist jeweils im Eintrag zum Modul
in ESTAB enthalten. Die Adressen im Maschinenbefehl werden angepasst.
– Wird ein Modifikations-Eintrag gelesen, so wird das extern referenzierte
Symbol bzw. dessen Adresse, in ESTAB nachgeschlagen.
– Ist das letzte Modul bearbeitet und dessen END-Eintrag gelesen, so wird
zum dort angegebenen Beginn des Programms gesprungen und die Kontrolle
zur Ausführung des Programms wird an das Programm abgegeben. Bei
mehreren Objektprogrammmodulen enthält meist nur das Hauptprogramm
eine Angabe einer Startadresse. Falls kein Modul eine Startadresse definiert,
wird vom Lader per default die Anfangsadresse PADR genommen. Damit
gilt folgendes: Reihenfolge, in der Module geladen werden spielt keine
Rolle. Andere Möglichkeit: Startadresse des geladenen Programms wird an
das Betriebssystem zurückgeliefert und Benutzer muss mit einem Execute-
Befehle (exec) explizit die Ausführung starten.

Dynamisches Binden

Binden von Unterprogrammen erst zur Laufzeit, d.h. erst wenn sie das erste Mal
aufgerufen werden. Als Vorteile ergeben sich folgende:

• Nach Bedarf laden


Unterprogramme werden also nur dann, wenn sie tatsächlich gebraucht werden,
zum in Ausführung befindlichen Programm hinzu gebunden. Bei großen
Unterprogrammen oder bei Unterprogrammen mit vielen externen Referenzen
kann man mit dynamischen Binden viel Speicherplatz und Zeit einsparen.
Z.B. Nutzung einer großen Statistik-Bibliothek abhängig von Eingabewerten,
die erst zur Laufzeit bekannt sind: kein Binden einer vollständigen Kopie der
Bibliothek nötig.
Beispiel Windows: Routinen in Dynamic Link Libraries (DLL) zusammen-
gefasst; erst wenn sie benötigt wird, Laden der gesamten DLL.
• Code-Sharing

40
Schlichter, TU München 2.3. HARDWARENAHE PROGRAMME

Dynamisches Binden wird oft verwendet, wenn mehrere ausführfähige


Programme eine einzige Kopie eines Unterprogramms oder einer Bibliothek
gemeinsam nutzen sollen. Z.B. werden für die Programmiersprache C
die Routinen für die Laufzeit-Unterstützung in der dynamic link library
zusammengefasst. Es wird dann nur eine Kopie der Routinen der Bibliothek
in den Arbeitsspeicher geladen und alle ausführenden Programme können
dann dynamisch diese Kopie zu ihrem Programm hinzu binden, anstatt jeweils
eine eigene Kopie in ihr Objektprogramm zu binden. Dabei ist es notwendig
zwischen dem statischen Teil (gleich für alle) und dem dynamischen Teil
(spezifisch für jedes aufrufende Programm) zu unterscheiden. Bibliothek ist
eine Sammlung von Funktionalitäten, die in ein Programm eingebunden werden
können. Die dort verfügbaren Funktionen werden dann als Unterprogramm im
eigenen Programm aufgerufen. Bibliotheken werden typischerweise von vielen
Anwendungsprogrammen verwendet.

41
Kapitel 3

Parallele Systeme - Modellierung,


Strukturen

Historisch gesehen war der Ausgangspunkt eine Ein-Benutzer, Ein-Programm


Rechenanlage und zwar ohne ein Betriebssystem, das die Ausführung von
Programmen koordiniert. Für die Ausführung von mehreren Programmen,
insbesondere wenn sie parallel ausgeführt werden sollen, sind eine Reihe von
organisatorischen Maßnahmen notwendig. Die angesprochenen organisatorischen
Aufgaben sind wesentlicher Bestandteil der Aufgaben eines Betriebssystems
und die Programmierung eines Betriebssystems gehört zu dem Bereich der
systemnahen Programmierung. Typischerweise finden in einem allgemeinen
Rechensystem eine Vielzahl paralleler Abläufe statt, die miteinander koordiniert
werden müssen.
Bevor wir auf die Aufgaben eines Betriebssystems und insbesondere auf
die Bereiche Prozess- und Prozessorverwaltung, Speicherverwaltung sowie
Ein/Ausgabe eingehen, werden wir uns zunächst mit den Problemen beschäftigen,
die sich daraus ergeben, dass in einem Rechensystem eine Vielzahl von parallelen
Abläufen/Prozessen, existieren kann, die sich beeinflussen können, miteinander
kommunizieren oder auch in Konkurrenz zueinander stehen können.

3.1 Fragestellungen
• Sequentielle Aspekte von systemnaher Programmierung:

– Programm als Repräsentation eines Algorithmus; ein Algorithmus ist ein


schrittweise effektiv durchführbares Verfahren, in endlichen Schritten; er hat
eine endliche eindeutige Beschreibung.

42
Schlichter, TU München 3.1. FRAGESTELLUNGEN

– Programm als sequentielle Folge von Aktionen/Anweisungen (alle Schritte


nacheinander);
– determinierte Programme: unter gleichen Bedingungen und Eingaben
produziert das Programm stets das gleiche Ergebnis; dies erlaubt eine
einfaches Testen bzw. Debuggen der Programme und der Prozessabläufe.
– deterministische Abläufe: eindeutig vorbestimmter Ablauf, keine willkürli-
che Auswahl von alternativen Schritten.

• Übergang von sequen-


tiellen Systemen hin zu parallelen Systemen/Programmen. Dabei werden die
folgenden Aspekte näher betrachtet.

– gleichzeitige Aktivität von Komponenten, die möglicherweise miteinander


kommunizieren oder aufeinander einwirken.
– Beispiele für Parallelität
∗ HW-Komponenten eines Rechensystems, z.B. Prozessor und E/A-
Controller.
∗ SW-Komponenten eines Rechensystems, z.B. parallel ablaufende Pro-
gramme; u.U. Zugriff auf gemeinsame Ressourcen, z.B. Daten im Arbeits-
speicher. In einem Multiprozessorsystem können Programme echt gleich-
zeitig ausgeführt werden.
∗ SW-Komponenten in einem verteilten System, d.h. Rechensysteme, die
über ein Rechnernetz miteinander verbunden sind.
– Aspekte des Abschnitts
∗ Modellierungstechniken zur Analyse und Beschreibung der Eigenschaften
paralleler Systeme (Spuren, Petrinetze).
∗ Threads als Mittel zur Realisierung von Parallelität innerhalb eines
Prozesses.
∗ Synchronisation in parallelen Systemen. Hier geht es darum, dass
Konkurrenz in parallelen Systemen koordiniert werden muss, um
Inkonsistenzen in Rechensystemen zu vermeiden. Erhaltung der kausalen
Beziehungen zwischen Aktionen; Synchronisation des Zugriffs auf
gemeinsame Ressourcen.
∗ Mechanismen zur Behandlung von Verklemmungen. Im Rechensystem
gibt es keinen Fortschritt, da sich die einzelnen Prozesse gegenseitig
blockieren. Prozesse warten gegenseitig auf frei-werdende Ressourcen.
Im Gegensatz zum vorhergehenden Aspekt ist bereits eine Blockierung
eingetreten, die nun aufgelöst werden muss.

43
Schlichter, TU München 3.2. GRUNDLAGEN

3.2 Grundlagen
In diesem Teilabschnitt werden kurz die wichtigsten Begriffe definiert sowie
Konzepte zur Formulierung paralleler Aktivitäten aufgelistet. Einige dieser
Konzepte werden in nachfolgenden Teilabschnitten ausführlicher diskutiert.

3.2.1 Begriffsdefinitionen
Nebenläufigkeit

Nebenläufigkeit (engl. concurrency) bezieht sich auf die zeitliche Beziehung


zwischen den Aktivitäten von Komponenten, die gleichzeitig oder zeitlich
verzahnt (engl. interleaving) ablaufen können.

• z.B. gleichzeitig: Drucken eines Dokuments und Berechnen einer Formel in


einer Tabellenkalkulation (CPU-Nutzung).

• z.B. zeitlich verzahnt: Benutzerauftrag muss CPU abgeben und wartet; ein
anderer Auftrag wird (teilweise) ausgeführt und gibt CPU wieder zurück, bevor
das Ende erreicht ist. Hier spricht man auch von Pseudoparallalität. Für einen
Benutzer sieht es so aus, als ob Dinge gleichzeitig passieren.

Parallelität

Parallelität wird häufig synonym zu Nebenläufigkeit verwendet;

• spezielle Form der Nebenläufigkeit: mehrere Prozessoren stehen zur Ausfüh-


rung zur Verfügung. Ein Beispiel dafür sind Multiprozessoren mit mehreren
Prozessoren. Auch bei einem Ein-Prozessor gibt es echte Parallelität zwischen
E/A-Controller (z.B. mit angeschlossenem Drucker) und CPU.

Verteiltheit

Verteilheit (engl. distribution) ist die räumliche oder auch nur konzeptionelle
Aufteilung der Komponenten eines Systems, z.B. vernetzte PCs. Die Verteilung
kann sich sowohl auf der Ebene der HW-Komponenten als auch auf der Daten-
und Anwendungsebene abspielen.

44
Schlichter, TU München 3.2. GRUNDLAGEN

Interaktion

Kommunikation, Synchronisation, Konkurrenz betrifft die kausalen Beziehungen


zwischen räumlich verteilten und nebenläufig ausgeführten Aktivitäten.

• kausale Abhängigkeit zwischen Ampel und Fußgänger:


Ereignis von Fußgänger:
er drückt Knopf
Ereignis beeinflusst Ampel: sie schaltet auf Rot für Auto
• Kommunikation: Prozesse auf dem gleichen oder unterschiedlichen Rechensy-
stemen tauschen Nachrichten untereinander aus.

• Koordinierung: Beziehung zwischen Auftraggeber und Auftragnehmer ⇒


Erstellen eines Auftrages durch Client und anschließendes Bearbeiten des
Auftrags durch Server. Ein Beispiel ist auch der koordinierte Zugriff auf
gemeinsame Daten (Erzeuger - Verbraucher Problematik).

• Konkurrenz: Aktivitäten eines Prozesses behindern die eines anderen Prozesses


z.B. Warten, wenn CPU von anderem Prozess belegt.

Nichtdeterminismus

System zeigt bei gleichen Ausgangsbedingungen und gleichen Eingaben unter-


schiedliches Verhalten (Reihenfolge der Prozesse spielt eine Rolle!). Problem:
Nichtreproduzierbarkeit von Ergebnissen, Testen von parallelen Programmen bei
Nichtdeterminismus ist schwierig. Beispiel:
x = 2 Prozess 1: x = x+5 Prozess 2: x = x*2
Ausführungsreihenfolge
P1 vor P2: x == 14
P2 vor P1: x == 9
Andere Ursachen für Nichtdeterminismus sind unterschiedliche Last bzgl
Rechner, Netz. Es geht nur um die Ausgangsbedingungen, die für die Ausführung
im Rechner relevant sind, und nicht darum, ob in New York gerade ein Taxi die 5th
Av. herunterfährt. Zu Ausgangsbedingungen zählen u.a., welche anderen Prozesse
laufen im Rechner gerade, wie ist der Speicher belegt, findet ein Netzwerk-
kommunikation statt, etc.

45
Schlichter, TU München 3.2. GRUNDLAGEN

3.2.2 Beschreibungskonzepte
Es gibt eine Vielzahl von Konzepten zur Formulierung paralleler Aktivitäten.
In der Vorlesung werden wir uns vor allem mit den beiden modell-basierten
Ansätzen, Ereignisse und Petrinetze befassen. Es gibt auch noch andere
Modellansätze (z.B. bei Rechnernetzen), z.B. formale Beschreibungssprachen
(Estelle, LOTOS), die z.T. auf Prozessalgebren basieren. Eine andere Möglichkeit
sind parallele Programmiersprachen.

modell-basierte Konzepte

• ereignis-orientiert: es wird der Ablauf von Prozessen betrachtet; jeder Ablauf


wird durch eine Menge von Ereignissen charakterisiert. Jeder Ablauf repräsen-
tiert eine Ereignisspur. Einzelne Ereignisse können in kausalem Zusammen-
hang stehen. Es werden nun eine Menge von Prozessen und deren Zusammen-
wirken betrachtet, insbesondere auch wie deren Ereignismengen im Zusam-
menhang zueinanderstehen. Ein Prozess wird anhand von Ereignismengen cha-
rakterisiert.
• graphisch-orientiert: der Prozessablauf wird graphisch dargestellt. Petrinetze
sind ein Beispiel dafür. Petrinetze sind Graphen mit 2 Arten von Knoten,
den Stellen und Transitionen. Abläufe werden durch das Schalten von
Transitionen und der Propagierung von Marken charakterisiert. Dabei können
Aussagen bzgl. der kausalen Abhängigkeit, aber auch der Unabhängigkeit von
Teilabläufen getroffen werden.

Sprachkonstrukte in Programmiersprachen

• parallele Komposition von Teilabläufen innerhalb eines Prozesses, z.B. Java


Threads. Andere Beispiele sind Tasks in Ada, oder auch parbegin, parend.
• Prozesshierarchien in Betriebssystemen: u.a. fork, join
• Kommunikationskonzepte: u.a. send, receive
• Synchronisationskonzepte: u.a. lock, unlock

Konzepte in Betriebssystemen

• Prozesskonzept = Programm in Ausführung; Prozesse haben einen eigenen


Adressraum während Threads eines Prozesses den Adressraum des Prozesses
gemeinsam nutzen.

46
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

• Threadkonzept = leichtgewichtiger Prozess;

• Kommunikation: Shared memory, Dateien, Nachrichten etc.

• Synchronisation: Unterbrechungen (Interrupts), Sperren etc. Das Auftreten von


Unterbrechungen sowie deren Behandlung wird im Verlaufe der Vorlesung
noch näher behandelt.

3.3 Modellierung paralleler Systeme


In diesem Abschnitt behandeln wir grundlegende Mechanismen zur Modellierung
und Beschreibung parallel ablaufender Systeme. Siehe auch das Buch M. Broy
"Informatik", Springer-Verlag. Insbesondere geht es in diesem Abschnitt um
folgendes:
das Verhalten von parallelen Systemen klären,
sich auf wesentliche Aktionen, Ereignisse konzentrieren (Abstraktion),
die Abhängigkeiten zwischen Aktionen ermitteln/klären,
Fehler oder Konflikte aufgrund paralleler Tätigkeiten vermeiden und
maximale Parallelität erzielen.

3.3.1 Modellierungsziele
Ziel ist die einfache Analyse und Beschreibung von parallelen Systemen.

• Spezifikation eines Modells im Sinne von Abstraktion: Vereinfachung,


Weglassen von Details, Beschränken auf interessierende Eigenschaften.

• Beispiele interessanter Eigenschaften sind:

– Determiniertheit. Unter gleichen Bedingungen entstehen die gleichen


Ergebnisse.
– Störungsfreiheit. Für störungsfreie Systeme gilt, dass unter Einhaltung der
durch eine Ordnung (später wird hierzu die Kausalitätsordnung zwischen Er-
eignissen verwendet) festgelegten Reihenfolge, die Ausführungsreihenfolge
der parallelen Ereignisse und deren Aktionen keinen Einfluss auf die berech-
neten Ergebnisse hat.

47
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

– wechselseitiger Ausschluss. Hier geht es darum, dass bei konkurrierenden


Zugriffen auf gemeinsame Ressourcen, die exklusiv benutzt werden, immer
nur ein Prozess zu einem Zeitpunkt darauf zugreift. Damit soll die Konsistenz
sichergestellt werden.
– Endloses Blockieren (engl. Deadlock).
– Verhungern (engl. Starvation). Beispielsweise erzielt ein Prozess keinen
Fortschritt, da er nie rechnend gesetzt wird, obwohl er rechenbereit wäre.
In Rechnerkernvergabe gibt es jedoch immer einen anderen rechenbereiten
Prozess, der eine höhere Priorität hat.

• Die Eigenschaften können in zwei Klassen eingeteilt werden.

– Sicherheitseigenschaften (engl. safety): Sicherstellen, dass gewisse uner-


wünschte Zustände und unerwünschte Aktionsverläufe nicht auftreten; For-
mulierung durch Invarianten (z.B. wechselseitig ausgeschlossene Nutzung
der CPU). Hier geht es nicht um Datensicherheit, d.h. persistente Speiche-
rung von Daten, damit sie auch nach einem Systemcrash noch zur Verfügung
stehen. Es geht auch nicht um Datenschutz, d.h. dass Daten nicht für andere
Prozesse lesbar sind.
– Lebendigkeitseigenschaften (engl. liveness): Garantieren, dass gewisse
erwünschte Zustände bzw. Aktionsmuster in den Abläufen irgendwann
auch auftreten (z.B. erwünschter Ablauf: rechenbereiter Prozess macht
irgendwann auch Fortschritte). Möglicherweise ist dafür die dynamische
Anpassung der Priorität notwendig.

3.3.2 Verhaltensbeschreibung
Verhaltensbeschreibungen eines dynamischen Systems sind Beschreibungen der
Eigenschaften des Systems und deren Veränderungen über der Zeit. Das Verhalten
eines Systems kann mit Spuren in einem 2-dimensionalen Raum beschrieben
werden:
Die 1. Dimension ist die Zeit, mit der das Fortschreiten der Ausführung der
Berechnungen erfasst wird, d.h. hier geht es um die Folge von Ausführungen
von elementaren Aktionen, die jeweils Ereignisse auslösen.
Die 2. Dimension ist der Raum der Eigenschaften des Systems, mit dem die
Systemzustände in Zeitpunkten erfasst werden. Zu Zeitpunkten wird jeweils
ein Schnappschuss des Systemzustands genommen. Über die Zeitachse wird
eine Folge von Zuständen angegeben, die sich mit der Ausführung der
Aktionen (Berechnungen) ergibt.

48
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

Die Verhaltensbeschreibung setzt sich aus den Basiseinheiten Aktionen und


Zustände zusammen.

• Eigenschaftenveränderungen sind Ausführungen von elementaren Aktionen.


Ausführungen von komplexen Berechnungen können mit Kombinationen von
Ausführungen dieser elementaren Aktionen beschrieben werden. Es sind zwei
Sichten möglich.

– Die Sicht auf die Tätigkeiten, die auszuführen sind; in dieser Sicht
sind die Basiseinheiten die atomaren Aktionen. Eine Aktion kann ein
Maschinenbefehl oder eine Java Anweisung sein.
– Die Sicht auf die Veränderungen, die erfolgen und beobachtet werden
können; in dieser Sicht sind die Basiseinheiten die atomaren Ereignisse,
die eintreten. Die Ausführung einer Aktion führt zu einem Ereignis im
Rechensystem. Aktionen und Ereignisse sind dual zueinander und können
nach Bedarf genutzt werden; hier wird überwiegend die Ereignissicht
benutzt. Aktionen können mehrfach ausgeführt werden; sie resultieren in
mehrfachen Ereignissen.
Beispiel: Aktion - Knopf drücken; Ereignis - die Ampel ist rot.

• Aktionen bzw. Ereignisse sind zeitlich geordnet. In einem sequentiellen


System werden die elementaren Aktionen sequentiell ausgeführt, d.h. es
existiert eine lineare Ordnung bzgl. der Zeitachse. Diese Zeitachse für
Verhaltensbeschreibungen hat mit der gewohnten, physikalischen Zeit die
lineare Ordnung gemeinsam; sie abstrahiert jedoch als diskrete Zeit von der
Dauer der Ausführung von Aktionen. In einem parallelen System müssen
zusätzlich auch nebenläufige Aktionen betrachtet werden, d.h. für sie kann keine
zeitliche Reihenfolge bestimmt werden.

• Zustände des Systems anhand der Werte der Datenobjekte. Folge von
Zuständen gemäß der Zeitachse. Jedem Zeitpunkt wird der Zustand der
Datenobjekte, der mit dem Zeitpunkt erreicht ist, zugeordnet. Für jeden
Zeitpunkt wird damit ein Schnappschuss vom System angegeben; über der
Zeitachse wird die Folge der Zustände angegeben, die sich mit der Ausführung
der Berechnungen ergibt.

• Spuren
Es sind zwei Varianten von Verhaltensbeschreibungen zweckmässig.

1. Ereignisspuren: Sie beschreiben den zeitlichen Ablauf der Berechnungen


eines Systems mit Ereignissen, die linear geordnet sind.

49
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

2. Zustandsspuren: Sie beschreiben den zeitlichen Ablauf der Berechnungen


eines Systems anhand der auftretenden Zustände der Datenobjekte. Ereignis-
spur und Zustandsspur sind eng miteinander verknüpft. Bei Auftreten eines
Ereignisses wird jeweils ein Schnappschuss des Systems genommen. Dieser
Schnappschuss stellt ein Element der Zustandsspur dar.

3.3.3 Ereignisse und Aktionsstrukturen


In diesem Abschnitt wird der Begriff Prozess anhand von Aktionsstrukturen ma-
thematisch gefasst. Dies ermöglicht die mathematische Modellierung beliebiger,
nichtkontinuierlicher ("diskreter") Abläufe verteilter Systeme, insbesondere von
Prozessen in Rechenanlagen. Durch diese Modellierung können jedoch auch an-
dersartige, technische oder betriebliche Vorgänge, die sich aus Einzelaktionen zu-
sammensetzen und zwischen denen kausale Beziehungen bestehen, erfasst wer-
den.

Prozess

Gegeben seien eine Menge (das "Universum") E* von Ereignissen (engl. events)
und eine Menge A von Aktionen (engl. actions).

• Definition
Ein Triple p = (E, ≤, α) nennen wir einen Prozess oder auch eine
Aktionsstruktur, falls folgende Aussagen gelten:

– E ⊆ E*, E heißt die Ereignismenge.


– ≤ ist eine partielle Ordnung über E, ≤ ist die Kausalitätsrelation.
Die partielle Ordnung ist eine reflexive, transitive und antisymmetrische
Relation.
– α: E → A ist die Aktionsmarkierung des Prozesses p.
– Die Abbildung α ordnet jedem Ereignis eine Aktion zu. In dieser Definition
von Aktionsstrukturen ist auch der leere Prozess eingeschlossen. Er wird
durch die Aktionsstruktur dargestellt, die aus der leeren Ereignismenge
besteht.

• Beispiel: Fußgängerübergang
Wir betrachten einen Prozess mit 14 Ereignissen. Jedem Ereignis werden
Aktionen zugeordnet.

50
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

Ereignis Aktion
e1 Knopf wird gedrückt
e2 Ampel für Autofahrer schaltet auf Gelb
e3 Ampel für Autofahrer schaltet auf Rot
e4 Auto hält auf Spur 1
e5 Ampel für Fußgänger schaltet auf Grün
e6 Auto hält auf Spur 2
e7 Fußgänger benutzt Fußgängerübergang
e8 Auto hält auf Spur 3
e9 Ampel für Fußgänger schaltet auf Rot
e10 Ampel für Autofahrer schaltet auf Rot und Gelb
e11 Ampel für Autofahrer schaltet auf Grün
e12 Auto fährt an auf Spur 1
e13 Auto fährt an auf Spur 2
e14 Auto fährt an auf Spur 3
e15 Knopf wird gedrückt
Die Ausführung einer Aktion löst ein Ereignis aus. Wird dieselbe Aktion
mehrmals ausgeführt, so wird jeweils ein neues Ereignis ausgelöst (siehe e1
und e15).

– Die Relation der kausalen Abhängigkeiten sei gegeben durch:


e1 ≤ e2, e2 ≤ e3, e3 ≤ e4, e3 ≤ e5, e3 ≤ e6, e5 ≤ e7,
e3 ≤ e8, e5 ≤ e9, e9 ≤ e10, e10 ≤ e11, e11 ≤ e12,
e11 ≤ e13, e11 ≤ e14, e4 ≤ e12, e6 ≤ e13, e8 ≤ e14, e9 ≤ e15.
Die kausalen Abhängigkeiten ergeben keine vollständige Ordnung.
– Diese Beziehungen erzeugen (durch die Bildung der reflexiv transitiven
Hülle) eine partielle Ordnung, die die Kausalität zwischen den Ereignissen
beschreibt. Man beachte, dass hier beispielsweise das Ereignis e12 nur
stattfindet, nachdem die Ereignisse e4 und e11 stattgefunden haben.
– Graphische Darstellung
Endliche Prozesse lassen sich anschaulich durch knotenmarkierte, gerichtete,
zyklenfreie Graphen darstellen, Die Knoten repräsentieren die Ereignisse
und sind durch die zugeordneten Aktionen markiert. Ereignisse werden
nicht wiederholt, nur die Aktionen werden wiederholt, d.h. jede wiederholte
Ausführung der gleichen Aktion führt zu einem neuen Ereignis; deshalb
zyklenfrei,

51
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

e6 e13

e1 e2 e3 e4 e12

e8 e14

e9 e10 e11

e5 e7 e15

• Charakterisierung von Prozessen


In einem Prozess hat jedes Ereignis eine eindeutige Identität ("X betritt am
19.1.2001 um 11:15 h den Hörsaal"), eine Aktion kann jedoch mehrfach
stattfinden (die Aktion "X betritt den Hörsaal" kann mehrfach stattfinden).
Dementsprechend kann in einem Prozess verschiedenen Ereignissen die gleiche
Aktion zugeordnet sein. Ereignisse haben einen eindeutigen Bezeichner;
Prädikate sind eine andere Möglichkeit, Ereignisse zu identifizieren, z.B.
Ermordung Kennedy’s oder die Kreuzigung Christi.

– Parallel, nebenläufig
Für einen Prozess p = (E, ≤, α) nennen wir zwei Ereignisse e1, e2 ∈ E
parallel oder nebenläufig (engl. concurrent), falls sie im Prozess p nicht in
einer kausalen Relation stehen, d.h. wenn gilt:
¬(e1 ≤ e2 oder e2 ≤ e1)
∗ Parallele Ereignisse sind kausal unabhängig, sie können zeitlich nebenein-
ander oder in beliebiger Reihenfolge stattfinden.
– Sequentiell
Ein Prozess p = (E, ≤, α) heißt sequentiell, wenn in ihm kein Paar von
parallelen Ereignissen auftritt, d.h. die Kausalitätsrelation ≤ eine lineare
Ordnung ist. Damit gilt für zwei beliebige Ereignisse e1 und e2 stets
entweder e1 ≤ e2 oder e2 ≤ e1.
– Der Ablauf eines Programmes kann auch als Prozess im Sinne der
Aktionsstrukturen gedeutet werden. Sequentielle Programme erzeugen
sequentielle Prozesse.
– Endlich
Ein Prozess p = (E, ≤, α) heißt endlich, falls seine Ereignismenge
eine endliche Menge ist. Beispielsweise ist das Abspielen einer CD ein
endlicher Prozess, während ein Betriebssystem einen unendlichen Prozess

52
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

repräsentiert. Unendliche Prozesse besitzen unendliche Ereignismengen.


Unendliche Prozesse können jedoch endlich beschreibbar sein.
main () { while true {} }

Kausale Abhängigkeiten

Häufig finden wir in Prozessen unterschiedliche Ursachen für die kausale


Beziehung e ≤ d zwischen Ereignissen e und d. Im einzelnen können drei
verschiedene Arten unterschieden werden.

• Echt kausale Beziehungen


das Ereignis e ist kausal für das Ereignis d in dem Sinn, dass d ohne e niemals
auftreten kann.

– Beispiel
e = Geldeinwurf, d = Kartenausgabe; e ≤ d, d.h. der Fahrkartenautomat gibt
erst dann eine Fahrkarte aus, wenn der passende Geldbetrag eingeworfen
wurde.

• zeitliche Beziehungen
das Ereignis e endet, bevor das Ereignis d beginnt.

– Beispiel: Nachricht muss gesendet sein, bevor sie empfangen werden kann.
Zeitliche Beziehungen können, aber müssen nicht echt kausal sein. Auto 1
fährt auf Spur 1, Auto 2 fährt eine Minute später auf Spur 2; es gibt eine
zeitliche Beziehung, jedoch keine kausale Beziehung.
– Happend-before
Die kausale Beziehung impliziert also eine zeitliche Relation; das ist die
bekannte happened before-Beziehung von L. Lamport. Die Umkehrung
gilt nicht. Die zeitliche Relation zwischen Ereignissen sagt nichts über die
Kausalität aus.
∗ Wichtig: Ereignisse wurden als atomare Ereignisse modelliert. D.h.
Beginn und Ende fallen auf einen Zeitpunkt zusammen. Ein alternativer
Ansatz wäre die Spezifikation eines Zeitintervalls für ein Ereignis mit
Anfangs- und Endzeitpunkt. Damit könnten auch Überlappungen von
Ereignissen modelliert werden.
∗ Die Happend-before Relation spielt im Kontext von Verteilten Anwendun-
gen eine wichtige Rolle (siehe Vorlesung Verteilte Anwendungen (URL:
[Link] Insbesondere in der

53
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

Gruppenkommunikation wird sie eingesetzt, um die an alle Gruppenmit-


glieder gesandten Nachrichten zu sequentialisieren. Auf diese Weise soll
erreicht werden, dass alle Gruppenmitglieder in einen für die Gruppe kon-
sistenten Zustand versetzt werden.

• Systembeschränkungen
Systembeschränkungen, z.B. wechselseitiger Ausschluss. Das Ereignis e darf
nicht parallel zum Ereignis d auftreten.

– Beispiel
e = Fußgänger überquert die Fahrbahn beim Übergang, und
d = Auto überfährt den Übergang.
e und d dürfen nicht parallel ausgeführt werden, aber es besteht keine ech-
te kausale Abhängigkeit zwischen e und d. Ereignisse, welche mit Aktionen
markiert sind, die aufgrund von Systembeschränkungen nicht parallel statt-
finden können, sind nicht unbedingt in einem "echt" kausalen Zusammen-
hang. Trotzdem sollten sie nicht als parallele Ereignisse auftreten. Um diese
Systembeschränkungen mit den eingeführten Modellierungskonzepten (un-
interpretierte Aktionen) zu erfassen, müssten sie in eine (künstliche) kausale
Abhängigkeit gebracht werden; das ist aber meist nicht sehr sinnvoll. Wir
werden später sinnvollere Möglichkeiten kennen lernen.

Sequentialisierung

Idee: vereinfachte Darstellung paralleler Abläufe, aus der Sicht eines Beobachters.
Ein sequentieller Prozess hat genau eine vollständige Sequentialisierung, nämlich
die vorgegebene Reihenfolge der Ereignisse. Durch α ergibt sich aus der
Ereignisreihenfolge eine Folge von Aktionen. Vollständige Sequentialisierung:
partielle Kausalitätsordnung zu linearer Ordnung ergänzen.

• Definition
Ein Prozess p1 = (E1, ≤1, α1) heißt eine Sequentialisierung eines Prozesses p2
= (E2, ≤2, α2), falls gilt:
E1 = E2
∀ e, d ∈ E1: e ≤2 d ⇒ e ≤1 d
α1 = α2

– Ist p1 sequentiell, so heißt die Sequentialisierung vollständig. Die Vervoll-


ständigung einer partiellen Ordnung zu einer linearen Ordnung heißt topolo-
gisches Sortieren.

54
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

• Ein sequentieller Beobachter eines Prozesses ist ein Beobachter, der die
Ereignisse eines Prozesses und die entsprechenden Aktionen in einem
sequentiellen Ablaufprotokoll festhält. Parallele Aktionen werden dabei in
eine zufällige Reihenfolge gebracht. Das Ergebnis der Beobachtung ist
ein sequentieller Prozess, der einer zufällig gewählten Sequentialisierung
entspricht. Gehen wir von sequentiellen Beobachtern aus, so erhalten wir
sequentielle Prozesse als Beobachtungen.

• Existiert für einen nichtsequentiellen Prozess eine Reihe von Beobachtungen,


die alle vollständige Sequentialisierungen des Prozesses darstellen, so lässt sich
aus diesen Beobachtungen der Prozess teilweise rekonstruieren. Kennen wir die
Gesamtmenge aller Sequentialisierungen, so lässt sich der Prozess eindeutig
rekonstruieren. Für den Beweis siehe Broy, Band II, S 12.

• Die Ausführung eines Programms auf einer Rechenanlage kann ebenfalls


als Prozess dargestellt werden. Gewisse Anweisungen ("Aktionen") eines
Programms zerfallen bei der Ausführung auf einer Rechenanlage in eine Reihe
von Einzelaktionen.

• Beispiel
Für das Beispiel des Fußgängerübergangs ist folgendes eine vollständige
Sequentialisierung.

e1 e2 e3 e4 e6 e5 e7 e8 e9

e10 e11 e14 e12 e13 e15

• Spuren
Darstellung sequentieller Prozesse mittels Spuren. Sequentielle Prozesse sind
Spezialfälle paralleler Prozesse. Für die Darstellung sequentieller Prozesse
bietet sich eine wesentlich einfachere Darstellungsform als Aktionsstrukturen.
Wir können ganz auf die explizite Angabe von Ereignismengen verzichten und
stattdessen endliche oder unendliche Sequenzen von Aktionen verwenden.

– Sei A eine Menge von Aktionen, dann bezeichnen wir mit A+ die Menge
der endlichen Folgen von Aktionen aus A und mit A∞ die Menge der
unendlichen Folgen von Aktionen.

55
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

– Jedem sequentiellen Prozess können wir eindeutig eine Folge von Aktionen
zuordnen, wie sprechen von der Spur (engl. trace). Sei p = (E, ≤, α) ein
sequentieller Prozess. Wir definieren:
∗ spur : {p | p ist sequentieller Prozess } → A+ ∪ A∞
∗ spur(p) = empty, falls E = Ø
∗ spur(p) = <a> · spur(p | E \ {e}), falls E 6= Ø, wobei e das gemäß der
Kausalitätsordnung kleinste Ereignis in p ist und α(e) = a gilt.
p | E \ {e} bezeichnet den Teilprozess, der durch die Einschränkung
auf die Ereignismenge E \ {e} entsteht.
"·" ist hier die Konkatenation von Aktionen, die sich durch die Ereignisse
ergeben. spur ist eine Abbildung auf die Menge der Aktionen. Als Ergebnis
liefert spur einen Strom (engl. stream) von Aktionen.
– Für einen nichtsequentiellen Prozess p gilt:
Spuren(p) = {spur(q) : Prozess q ist eine vollständige Sequentialisierung
von p}
Spuren sind ein einfacheres Modell für sequentielle Abläufe eines Systems
als Aktionsstrukturen. Da bei nichtsequentiellen Systemen in vielen Anwen-
dungen die Frage, welche Aktionen parallel zueinander auftreten können,
von untergeordneter Bedeutung ist, ist es naheliegend für solche Systeme
vereinfachend statt ihrer nebenläufigen Prozesse deren Sequentialisierungen
als Abläufe zu betrachten. In vielen Ansätzen zur Modellierung verteilter Sy-
steme werden nicht Prozesse mit ihrer expliziten Darstellung von Parallelität,
sondern die technisch etwas einfacher zu handhabenden Mengen von Akti-
onsströmen verwendet.

3.3.4 Aktionen als Zustandsübergänge


Neben der Beschreibung von Systemen durch die Prozesse, die deren Abläufe
bilden, ist es naheliegend, Systeme durch Zustände und ihr Verhalten durch Zu-
standsänderungen zu modellieren. ⇒ Zustandsraum = Menge aller Systemzu-
stände. Dazu geben wir für ein System einen Zustandsraum an. Dieser besteht
aus der Menge aller Zustände, die das System einnehmen kann. Auf dieser Basis
beschreiben wir dann alle Zustandsübergänge, die im System auftreten können.

Interpretierte Aktionen

Aktionen werden Zustandsänderungen als Bedeutung zugeordnet. Bisher haben


wir die Mengen der Aktionen nicht weiter interpretiert. Eine Deutung für Ak-
tionen in Prozessen liefern Zustandsänderungen. Dazu weisen wir Aktionen Zu-

56
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

standsänderungen als Bedeutung zu, d.h. Aktionen bewirken Zustandsänderun-


gen. Dabei interessiert uns insbesondere die Frage, ob wir über diese Zuordnung
auch Prozessen eindeutig eine Bedeutung zuordnen können.

Modell

Zu diesem Zweck definieren wir nichtdeterministische Zustandsautomaten mit


Transitionsaktionen.

• Zustandsautomat
Ein nichtdeterministischer Zustandsautomat ist gegeben durch:

– S, eine Menge von Zuständen, genannt Zustandsraum,


– A, eine Menge von Transitionsaktionen,
– R ⊆ S × A × S eine Zustandsübergangsrelation, Zustand ⇒Aktion Zustand’
∗ Seien s0, s1 ∈ S und a ∈ A gegeben. (s0, a, s1) ∈ R bedeutet, dass
im Zustand s0 die Aktion a ausgeführt werden kann und dies zum
Nachfolgezustand s1 ∈ S führen kann.
∗ Diese Art von Automaten heißt nichtdeterministisch, da in einem
Zustand mehrere Transitionsaktionen möglich sein können und eine
Transitionsaktion zu unterschiedlichen Nachfolgezuständen führen kann.
∗ Wir schreiben (für gegebene Relation R) s0 →a s1, um auszudrücken, dass
(s0, a, s1) ∈ R gilt.
– S0 eine Menge von möglichen Anfangszuständen.

• Beispiel Fahrkartenautomat
Akzeptiert werden 1- und 2 DMark Münzen. Mittels zweier Knöpfe kann man
zwischen einer Kurzstrecke für 1 DM oder einer normalen Fahrt für 2 DM
wählen. Der Automat gibt Wechselgeld zurück.

– Menge der Zustände


S ⊆ S1 × S2 mit
S1= {Wahl, kurz, normal} und S2= {-1,0,1,2}
1
mit der folgenden Interpretation eines Zustandes s = (x, y):
1
x und y repräsentieren jeweils Zustandswerte. S1 spezifiert die Streckenwahl, S2 definiert das
Wechselgeld.

57
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

x= Wahl: Automat wartet auf die Wahltaste


x= kurz: eine Kurzstreckenkarte wurde gewählt und ist noch auszugeben
x= normal: eine normale Fahrkarte wurde gewählt und ist noch
auszugeben
y= -1 : es ist noch 1 DM zurückzugeben
y= 0 : es ist kein Geld mehr einzuwerfen oder zurückzugeben
y= 1 : es muss noch 1 DM eingeworfen werden
y= 2 : es muss noch 2 DM eingeworfen werden
– Menge der Transitionsaktionen
A = {Wk, Wn, E1, E2, R1, Ak, An }, mit
Wk: Wahl einer Kurzstreckenkarte
Wn: Wahl einer normalen Fahrkarte
E1: Einwurf eines 1DM Stückes
E2: Einwurf eines 2DM Stückes
R1: Rückgabe eines 1DM Stückes
Ak: Ausgabe einer Fahrkarte für Kurzstrecke
An: Ausgabe einer Normalfahrkarte
– Zustandsübergänge

Wn Wk
(normal, 2) (Wahl, 0)

E2
An Ak
E1

E1 E1
(normal, 1) (normal, 0) (kurz, 0) (kurz, 1)

E2 R1 R1 R1
E2

An Ak
(normal, -1) (Wahl, -1) (kurz, -1)

• Aktionsspur
Jedem Zustandsautomaten lassen sich ausgehend von der gegebenen Menge
von Anfangszuständen Spuren zuordnen.

– Definition
Gegeben sei ein Zustandsautomat Z = (S, A, R, S0). Eine Folge ai, wobei 1
≤ i ≤ k mit k ∈ IN ∪ {∞}, ist eine endliche oder unendliche Aktionsspur
des Zustandsautomaten, falls eine Folge von Zuständen si existiert, mit si ∈
S, s1 ∈ S0 und

58
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

si-1 →a si für alle i mit 1 < i ≤ k


i
– Eine Aktion a heißt deterministisch, wenn für jeden Zustand s ∈ S höchstens
ein Nachfolgezustand sf ∈ S existiert mit
s →a sf
– Beispiel
Auswertung eines Programms mit Zustandsänderung. Das Programm
y = 1;
x = 10;
while (x > 0) {
y = x * y; x = x - 1;
}
berechnet die Fakultätsfunktion. Nach seiner Ausführung gilt 10! = y. Der
Ablauf dieses Programms entspricht der sequentiellen Aktionsstruktur, deren
Ereignisse, Aktionen und Zustände in der folgenden Tabelle angegeben sind.
Ereignis Aktion Zustand x Zustand y
a0 y=1 undefiniert 1
b0 x = 10 10 1
a1 (x > 0) ? 10 1
b1 y=x*y 10 10
c1 x = x -1 9 10
... ... ... ...
a10 (x > 0)? 1 10!
b10 y=x*y 1 10!
c10 x=x-1 0 10!
a11 (x > 0)? 0 10!
Hier bezeichnen Aktionen wie (x > 0)? Abfrageaktionen, die den
Datenzustandsraum nicht ändern. Nehmen wir jedoch Kontrollzustände
(etwa einen Befehlszähler) mit zu den Zuständen des Zustandsraums
hinzu, so ändert auch diese Abfrage den Zustand. Zustände sind für das
obige Programm durch Paare (n, m) von Zahlen gegeben, die die Werte
der Programmvariablen x und y repräsentieren. Mit jeder Zuweisung in
einem prozeduralen Programm wird eine Aktion verbunden, die einer
Zustandsänderungsabbildung entspricht.

Konflikte

Im Zusammenhang mit Programmen und den ihnen zugeordneten Prozessen


stellt sich die Frage, welche Zustandsänderungen ohne Schwierigkeiten zeitlich
parallel durchgeführt werden können. In vielen Fällen lassen sich Aktionen
zeitlich nebeneinander ausführen. Gewisse Zustandsänderungen können aber

59
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

nicht ohne Konflikte nebeneinander ausgeführt werden. Wir sagen, dass diese
Aktionen im Konflikt miteinander sind. Sollen beispielsweise zwei Anweisungen
an die gleiche Programmvariable x parallel ausgeführt werden, so lässt sich dem
entsprechenden Prozess keine Zustandsänderungsabbildung eindeutig zuordnen.
In beiden Aktionen soll die Programmvariable x geändert werden. Die Aktionen
sind im Konflikt.

• Beispiel
Mögliche Konflikte bei parallel durchzuführenden Zuweisungen. Wir betrach-
ten die Aktionen, die den folgenden beiden Zuweisungen entsprechen:
(1) x = x + 1
(2) x = 2 * x
Die Zuweisungen stehen im Konflikt zueinander.

– Werden sie parallel ausgeführt, so kann dem entsprechenden Prozess


keine Zustandsänderung eindeutig zugeordnet werden; wir sagen auch, die
Aktionen stören sich wechselseitig.

• Störungsfreiheit
Frage: Gibt es Kriterien, um auf einfache Weise solche Konflikte zu erkennen,
so dass sie durch eine Reihenfolgeregelung gelöst werden können? Die Frage
kann mit ja beantwortet werden; es gibt Kriterien, und zwar die Bernstein-
Bedingungen.

– Vorbereitung
Für eine Transitionsaktion a gelte:
V(a) ⊆ S ist Vorbereich, d.h. die Menge der gelesenen Zustandsvariablen.

N(a) ⊆ S ist Nachbereich, d.h. die Menge der geschriebenen Zustandsva-


riablen.
– Beispiel
Sei S = {x, y, z}
(1) a1: x = x+3y+z V(a1)={x,y,z}, N(a1)={x}
(2) a2: y = 2*x V(a2)={x}, N(a2)={y}
Zwischen dem Vorbereich von a2 und dem Nachbereich von a1 gibt es eine
Überlappung.
– Definition Störungsfreiheit
Gegeben sei ein Prozess p= (E, ≤, α). Der Prozess p heißt störungsfrei, genau
dann, wenn für jedes Paar von Ereignissen e1, e2 ∈ E gilt:

60
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

1.) e1 ≤ e2 oder e2 ≤ e1 oder


2.) V(α(e1)) ∩ N(α(e2)) = N(α(e1)) ∩ V(α(e2)) = N(α(e1)) ∩ N(α(e2)) = Ø.

e1 und e2 sind parallel. Vorbereich und Nachbereich überschneiden sich


nicht.
Die Bedingung (2) nennt man auch Bernstein-Bedingungen. "Gilt die Bern-
steinbedingung, dann ist die Reihenfolge der Ausführung der beiden Zu-
weisungen ohne Einfluss auf den schließlich erreichten Endzustand. Der
Störungsbegriff umfasst auch unerwünschte Situationen in konventionellen
Rechnern, in denen ein gleichzeitiges Lesen und Schreiben, sowie mehrfa-
ches gleichzeitiges Schreiben auf einer Speicherzelle auch technisch zu ei-
nem Konflikt führt."
– Für störungsfreie Systeme gilt, dass unter Einhaltung der mit ≤ festgelegten
Reihenfolge, die Ausführungsreihenfolge der parallelen Ereignisse und
deren Aktionen keinen Einfluss auf die berechneten Ergebnisse hat. "Die
Bernstein-Bedingungen sind auch im Zusammenhang mit parallelisierenden
Compilern wichtig. Parallelisierende Compiler versuchen, Anweisungen
des zu compilierenden Programms, die keine gemeinsamen Datenobjekte
benutzen, für eine parallele Bearbeitung vorzubereiten (z.B. Ausnutzen vieler
Pipeliningstufen von RISC-Prozessoren). Dazu kann man die sequentiellen
Aktionen (Anweisungen) schrittweise aus der ≤ Relation entfernen, solange
die Bernsteinbedingung nicht verletzt wird."

3.3.5 Petri-Netze
Ein Prozess beschreibt einen möglichen Ablauf eines verteilten Systems. Ver-
teilte Systeme besitzen viele Abläufe, d.h. ein System wird durch die Men-
ge von Abläufen beschrieben. Gesucht wird deshalb ein Modell zur Beschrei-
bung von Systemen und deren möglichen Abläufen. Drei Vertreter solcher For-
malismen sind Petri-Netze (graphische Beschreibungsmethode), Agenten (for-
male Beschreibungssprache, siehe Broy Band II) und prädikatenlogische For-
meln zur Beschreibung von Abläufen. Im folgenden werden Petri-Netze (URL:
[Link] vorgestellt, die eine graphen-orientierte
Beschreibung verteilter Systeme und deren Abläufen ermöglicht.

Allgemeines

Formalismus von C.A. Petri 1962 entwickelt. Ansatz führte zu einer Theorie zur
Analyse und Entwicklung nebenläufiger Systeme.

61
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

• informelle Charakterisierung
Ein Petri-Netz ist gerichteter Graph mit Kanten und zweierlei Knoten.

– Knoten: Stellen (graphisch Kreise) und Transitionen (graphisch Rechtecke)


– Kanten: von Stellen zu Transitionen oder von Transitionen zu Stellen
– Belegung der Stellen mit Marken/Werten (Token);
∗ In einem boolschen Netz sind als Werte nur 0 oder 1 zugelassen.
∗ In einem Stellen/Transitionsnetz sind für die Belegung der Stellen
natürlichzahlige Werte zugelassen; die maximale Belegung definiert die
Stellenkapazität.
– Zustand: definiert durch Belegung der Stellen;
Zustandsübergang durch sogenannte Schaltregeln (engl. firing rule); Bele-
gung ändert sich. Man spricht in diesem Zusammenhang vom Schalten einer
Transition.
Das dynamische Verhalten eines Netzes läßt sich durch Schaltvorgänge
beschreiben. Transitionen schalten, indem sie von allen Eingangsplätzen eine
Marke abziehen (bei 1-wertigen Kanten) und auf allen Ausgangsplätzen eine
Marke hinzufügen. Ein Schaltvorgang kann insbesondere die Gesamtzahl der
Marken in einem Netz ändern. Eine einzelne Transition ist schaltbereit, wenn
alle ihre Eingangsplätze echt positiv belegt sind; bei mehrwertigen Kanten
müssen entsprechend viele Marken bei den Eingangsplätze vorhanden sein.
– Markierung der Kanten, Kantengewichte: Gewichtung gibt an, wieviele
Marken beim Schalten einer Transition von den Eingangsknoten (Stellen)
der Transition abgezogen und den Ausgangsknoten (Stellen) der Transition
hinzugefügt werden.

• Beispiel eines Petri-Netzes


grobe Modellierung einer Materialverwaltung.

62
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

Bestell- Auslieferung
aufnahme
Bestellung Lieferauftrag Waren

Produktions-
Produktion Lager
auftrag

Bestellungen kommen zur Bestellaufnahme, die Lieferaufträge an die Auslie-


ferung erteilt. Diese bedient sich aus einem Lager und liefert Ware aus. Um
das Lager aufzufüllen, müssen Produktionsaufträge an die Produktion erteilt
werden. Aus der graphischen Darstellung ist ersichtlich, dass Transitionen Tä-
tigkeiten repräsentieren, während Stellen eher Zustände darstellen. Marken, die
Stellen zugeordnet sind und einen dynamischen Ablauf ermöglichen, werden
erst weiter unten eingeführt.

Definition: Petri-Netz

Ein Petri-Netz ist ein Tripel (S, T, F) mit


S ist eine endliche Menge von Stellen (engl. place)
T ist eine endliche Menge von Transitionen (engl. transition) und es gilt: S ∩
T = Ø d.h. Stellen und Transitionen sind disjunkt.
F ist die Flussrelation mit F ⊆ (S × T) ∪ (T × S)
Für einen Knoten x ∈ (S ∪ T) gilt:
·x = {y | y F x} den Vorbereich von x
x· = {y | x F y} den Nachbereich von x

x kann dabei eine Stelle oder eine Transition sein.

• Mit obiger Definition ist die statische Struktur eines Netzes formal erfasst. Die
graphische Darstellung wurde bereits anhand des obigen Beispiel gezeigt.
• Für das Beispiel Materialverwaltung gilt beispielsweise:
·Bestellaufnahme = {Bestellung}
Bestellaufnahme· = {Produktionsauftrag, Lieferauftrag}

63
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

• Verfeinerung
Netzstrukturen können schrittweise verfeinert, konkretisiert werden. Wichtig:
Globale Struktur muss bei Verfeinerung erhalten bleiben, d.h. alle Kanten in
eine verfeinerte Transition und alle Kanten aus dieser verfeinerten Transition
bleiben erhalten. Die innere Struktur der Transition kann wiederum in
Stellen, Transitionen und Kanten aufgeschlüsselt werden. Die zu verfeinernde
Transition kann nach außen hin als Blackbox gesehen werden.

– Beispiel
Verfeinerung der Materialverwaltung: z.B. der Komponente Auslieferung.
Anhand des Lieferauftrages wird der Lieferschein geschrieben, der zusam-
men mit dem Produkt verpackt und versandt wird.

Lieferschein-
erstellung Versenden
Lieferauftrag
Lieferschein Waren

Lager verpackte
Verpacken Produkte

Auslieferung

Auslieferung ist nach außen hin eine Transition. Dies bedeutet, dass die
Eingangskanten von Auslieferung jeweils zu einer Transition führen müssen.

Markierung und Schaltregeln

Zur Erfassung des dynamischen Verhaltens erweitern wir die Definition eines
Petri-Netzes zunächst um Markierungen und geben dann die Schaltregeln an.

• Markierung
Gegeben sei ein Petri-Netz (S, T, F).

64
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

– Eine Abbildung c: S → IN ∪ {∞} gibt die Kapazität einer Stelle an. Wenn
in den von uns verwendeten Netzen die Stellen nicht explizit markiert sind,
dann bedeutet dies eine unbeschränkte Kapazität.
– Eine Abbildung w: F → IN ∪ {0} gibt die Gewichtung einer Kante an. Wenn
in den von uns verwendeten Netzen die Kanten nicht explizit markiert sind,
dann bedeutet dies eine implizite Gewichtung mit dem Gewicht 1.
– Eine Abbildung M: S → IN heißt natürlichzahlige Markierung der Stellen.
Die Markierung beschreibt einen Zustand des Netzes.
Es muss gelten: ∀ s ∈ S: M(s) ≤ c(s)
Ein solches Netz heißt Stellen-Transitionsnetz
– Falls gilt M: S→ IB, mit IB = {0, 1}, dann heißt das Netz: Bedin-
gungs/Ereignisnetz oder Boolesches Netz. Demnach entsprechen Boolsche
Petri-Netze natürlichzahligen Petri-Netzen, bei denen jede Stelle die Kapazi-
tät 1 hat (oder einen boolschen Wert mit true (=1) bzw. false (=0) hat). Eine
Transition t kann nur dann schalten, wenn alle Stellen, zu denen Kanten von
t aus führen, mit false markiert sind.

• Schaltregeln
Das Verhalten eines Netzes wird durch Schaltvorgänge beschrieben. Gegeben
sei ein Petri-Netz (S, T, F), die Funktionen c, w und eine Anfangsmarkierung
M0.

– Ein Zustandsübergang erfolgt durch das Schalten von Transitionen, wobei


gilt: Eine Transition t ∈ T kann schalten (ist transitionsbereit), wenn folgende
Bedingungen erfüllt sind:
Für alle s ∈ ·t gilt: M(s) ≥ w((s,t))
Für alle s ∈ t· gilt: M(s) ≤ c(s) - w((t,s))
w(s,t) spezifiziert die für die Kante s → t erforderliche Marken. Der zweite
Fall bedeutet, dass vor Schalten der Transition die aktuelle Markierung der
Stelle kleiner oder gleich als die Kapazität der Stelle minus der zugehörigen
Kantengewichtung ist, d.h. die generierten Marken müssen in der Ziel-Stelle
Platz haben.
– Durch das Schalten von t wird eine Folgemarkierung M’ zu M erzeugt, mit
Für alle s ∈ ·t \ t· gilt: M’(s) = M(s) - w((s,t))
Für alle s’ ∈ t· \ ·t gilt: M’(s’) = M(s’) + w((t,s’))
Für alle s" ∈ (·t ∩ t·) gilt: M’(s") = M(s") - w((s",t)) + w((t,s"))
Sonst: M’(s) = M(s)
– Das Modell trifft keine Festlegungen über die Schaltdauer einer Transition,
man geht davon aus, dass das Schalten keine Zeit erfordert. Die Definition

65
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

besagt, dass eine Transition nur schalten kann, wenn in ihren Eingangsstellen
mindestens soviele Marken liegen, wie die Gewichtung der jeweiligen
Kanten angibt und wenn außerdem gewährleistet ist, dass durch das Schalten
die Kapazität ihrer Ausgangstellen nicht überschritten wird. Durch das
Schalten werden entsprechend der Kantengewichtung Marken von allen
Eingangstellen abgezogen und ebenfalls entsprechend der Gewichtung
Marken den Ausgangstellen hinzugefügt.
– Beispiel: Schalten einer Transition
Gegeben sei eine Kantengewichtungsfunktion w, die jede Kante mit 1
gewichtet, also
w: F → 1

vor dem Schalten nach dem Schalten

– Beispiel: Schalten mit Kantengewicht

3 3

2 2

vor dem Schalten nach dem Schalten

– Beispiel: nichtschaltbare Transition


In der linken Situation enthält die Stelle s2 zu wenige Tokens, da gemäß
der Kantenmarkierung bei jedem Schalten der Transition t1 zwei Marken
von der Stelle s2 konsumiert werden. In der rechten Situation liegt dagegen

66
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

ein Markenüberfluss vor. Die Transition t1 kann nicht schalten, da auf der
Stelle s4 bereits ein Token liegt und damit die Kapazität der Stelle (1)
bereits erschöpft ist. Durch ein Schalten würde ein weiteres Token der Stelle
hinzugefügt werden und die Kapazität überschreiten.

s1 t1 s3 s1 t1 s3

s4 Kapazität 1
s2 s2 s4
2 2

Markenmangel Markenüberfluss bei s4

Animation Petrinetz
siehe online Version

Nebenläufigkeit

Mit Petri-Netzen lassen sich nebenläufige Systeme auf einfache Weise modellie-
ren. Betrachten wir zum Beispiel vier Aktivitäten t1, ... , t4, wobei jede Aktivität
durch eine Transition modelliert wird. Nach Beendigung von t1 (z.B. Einlesen von
Eingabewerten) können t2 (z.B. Berechne ggt) und t3 (z.B. Berechne Fibonacci)
nebenläufig aktiv sein, aber sie müssen beide beendet sein, bevor t4 ausgeführt
wird.

t2

t1 t4

t3

• Nichtdeterminismus

67
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

Bei einer gegebenen Markierung M können Konflikte hinsichtlich der


Schaltbereitschaft von Transitionen auftreten. Zwei Transitionen t1 und t2 sind
im Konflikt, wenn sie gemeinsame Eingangs- und Ausgangsstellen besitzen,
die so markiert sind, dass nur eine von beidem Transitionen schalten kann.
Es erfolgt eine nichtdeterministische Auswahl. Es erfolgt also eine zufällige
Auswahl der schaltbaren Transitionen.

– Beispiel
Erzeuger/Verbraucher mit Konfliktbelegung. Nach dem nebenläufigen
Schalten der Transitionen a und b des Netzes (siehe Situation oben) ergibt
sich eine Konfliktbelegung (siehe Situation unten), in der nur entweder die
Transition c oder die Transition d schalten kann.

nebenläufiges
a c e d b
Schalten

Erzeuger Verbraucher

Konflikt
a c e d b belegung
bzgl c und d

Eigenschaften von Netzen

Für ein gegebenes Petri-Netz, das das Verhalten eines verteilten Systems
modelliert, sind wir daran interessiert, zu klären, ob das System bei gegebener
Anfangsmarkierung bestimmte Eigenschaften besitzt. Eigenschaften sind die
Erreichbarkeit und die Lebendigkeit.

• Erreichbarkeit
Häufig ist man an der Frage interessiert, ob das Netz ausgehend von einer
Markierung M irgendwann eine Folgemarkierung M’ erreicht. Das ist die Frage
der Erreichbarkeit von Zuständen.

68
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

– Erreichbare Markierung
Gegeben sei ein Petri-Netz (S, T, F) mit der Markierung M. Eine endliche
Sequenz ρ = t1, t2, ..., tn mit ti ∈ T heißt von M aktivierte endliche
Schaltfolge, wenn Markierungen M1, M2, ..., Mn existieren mit

t1 t2 tn
M M1 M2 Mn d.h. M Mn

In diesem Fall ist Mn von M aus erreichbar.


M’ ist von M erreichbar, wenn es eine Sequenz ρ gibt, die von M in
den Endzustand M’ führt. Um die erreichbaren Markierungen eines Netzes
zu erfassen, modelliert man das Netz als einen Zustandsautomat, der
üblicherweise als Graph dargestellt wird (Erreichbarkeitsgraph). Die Knoten
des Graphen sind die erreichbaren Markierungen und die Kanten sind mit
Transitionen beschriftet.
– Beispiel: Bahnnetz
Vier Städte sind durch Bahngleise, die nur in einer Richtung befahrbar sind,
im Kreis verbunden. Zwei Züge fahren auf der Strecke.

Aufgabe: Das System ist so zu konstruieren, dass sich niemals beide Züge
auf derselben Strecke befinden.

Lösung: Die Strecken werden mit Stellen s1, ... , s4 modelliert. Eine
Marke auf der Stelle si bedeutet, dass ein Zug auf der i-ten Strecke fährt.
Durch die zusätzlichen Kontrollstellen k1, .. , k4 soll garantiert werden,
dass in keiner erreichbaren Markierung mehr als eine Marke auf einer der
Stellen si liegt. ki kontrolliert den Zugang zur Strecke si (Stelle).

s1
t4 t1

k1
s4 k4 k2 s2 Bahnnetz

k3
t3 t2
s3

Der Graph zeigt jeweils einen Zug auf Strecke s2 und s4.

69
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

k1, s2, k3, s4


t2 t4

k1, k2, s3, s4 s1, s2, k3, k4

t4 t2 Erreichbarkeitsgraph
t3 t1
s1, k2, s3, k4
t1 t3

k1, s2, s3, k4 s1, k2, k3, s4

Die Zustände werden durch die Menge der markierten Stellen in einer
erreichbaren Markierung beschrieben. Der Erreichbarkeitsgraph zeigt, dass
kein Zustand ereichbar ist, in dem mehr als eine Marke, also mehr als ein
Zug, auf einer Stelle si liegt. Damit ist die gewünschte Eigenschaft korrekt
modelliert.
Die Frage, ob es einen Algorithmus gibt, der entscheidet, ob eine Markierung
aus einer gegebenen Anfangsmarkierung aus erreichbar ist oder nicht,
(Entscheidbarkeit des Erreichbarkeitsproblems), war ca. 10 Jahre lang offen.
Prof. E.W. Mayr hat die Entscheidbarkeit 1980 in seiner Dissertation (an der
TUM) bewiesen. Aber: der Algorithmus besitzt sehr hohe Komplexität, er ist
nicht effizient durchführbar.

• Lebendigkeitseigenschaften
Wie zu Beginn des Kapitels bereits erwähnt, verwendet man System-
modelle häufig, um Lebendigkeitseigenschaften zu analysieren. Stellen-
Transitionsnetze werden oft in Bereichen verwendet, in denen es auf die An-
zahl und die Verteilung veränderlicher Objekte ankommt. (z.B. Daten in einem
Rechner, Waren in einem Lager, Werkstücke). Man ist daran interessiert zu er-
kennen, ob es in einem System zu Blockierungen kommen kann, so dass Teile
des Systems blockiert sind oder der gesamte Ablauf zum Stillstand kommt.
Ursachen für solche Situationen sind Mangel oder Stau, der durch die verän-
derlichen Objekte ausgelöst wird.

– Netzdarstellung
aktive Systemelemente als Transitionen (Prozessor, Maschine, etc.)
passive Systemteile als Stellen (Speicher, Lager, etc.)
veränderliche Objekte als Marken
Für Lebendigkeitsuntersuchungen sind Netzteile interessant, die niemals
markiert werden oder die niemals ihre Marken verlieren.

70
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

– Definition
Gegeben sei ein Petri-Netz (S, T, F) mit der Anfangsmarkierung M0.
∗ Das Netz heißt lebendig, wenn für jede erreichbare Markierung M und für
jede Transition t ∈ T eine Markierung M’ existiert, die aus M erreichbar ist
und in der t transitionsbereit ist. Informell: jede Transition t kann immer
wieder irgendwann einmal schalten.
∗ Die von M0 aus erreichbare Markierung M beschreibt eine vollständige
Verklemmung (eng. deadlock), wenn es keine Transition t ∈ T gibt, die
unter M schalten kann.
∗ Die von M0 aus erreichbare Markierung M beschreibt eine lokale
Verklemmung, wenn es eine Transition t ∈ T gibt, so dass ausgehend von
M keine Folgemarkierung M’ erreichbar ist, in der t transitionsbereit ist.
∗ Ist (S, T, F) mit Anfangsmarkierung M0 lebendig, dann ist es auch
verklemmungsfrei. Lebendige Netze stellen sicher, dass es weder zu einem
Markenmangel noch zu einem Überfluss kommt. Die Eigenschaft der
Lebendigkeit eines Netzes ist insbesondere für Systeme, die für einen
Endlosbetrieb ausgelegt sind (z.B. Betriebssysteme) wichtig.
– Beispiel: Lebendiges Netz

Aufgabe: Modellierung eines FIFO-Puffers mit Kapazität 3. Und zwar so,


dass er verklemmungsfrei und lebendig ist.

Lösung: Das System besteht aus 3 Zellen, die jeweils eine Nachricht
aufnehmen können (die Stellen repräsentieren die Speicherzellen). Die
Transition t1 modelliert das Eingeben einer neuen Nachricht und die
Transition t4 modelliert die Ausgabe der Nachricht. Mit den Transitionen
ti werden die Nachrichten von Zelle si-1 zur Zelle si weitergereicht.
Voraussetzung ist, dass die entsprechende Zelle leer ist. Der Zustand "Zelle
si ist leer", wird durch die markierte Stelle ki modelliert.
Das modellierte Netz ist verklemmungsfrei und lebendig. Falls der FIFO
Puffer in ein größeres System eingebunden ist, müssen die Transition t1 (für
die Eingabe von Nachrichten) und t4 (für die Ausgabe von Nachrichten) in
das Gesamtsystem integriert werden.

71
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

k1 k2 k3

t1 t2 t3 t4

s1 s2 s3
Eingabe einer Ausgabe einer
Nachricht Nachricht

– Beispiel: Verklemmung
2 Studenten benötigen ein 2-bändiges Lehrbuch. Student 1 leiht sich zunächst
nur Band 1 aus und Student 2 leiht sich vorsorglich den noch vorhandenen
Band 2 aus. Bevor Student 1 seinen ersten Band zurückgibt, möchte er noch
den zweiten ausleihen. Auch Student 2 gibt seinen ausgeliehenen Band nicht
zurück, sondern versucht, den ersten Band auszuleihen.
∗ Vor der Ausleihe
Anfangszustand des Netzes vor der Ausleihe. Die nachfolgende Abbildung
zeigt zunächst das Netz, bevor einer der Studenten ein Buch ausleiht
und die zweite Abbildung zeigt das Netz, nachdem die Studenten die
jeweiligen Bände ausgeliehen haben.

72
Schlichter, TU München 3.3. MODELLIERUNG PARALLELER SYSTEME

Student 1 Band1 Band 2 Student 2

Band 1 Band 2
ausleihen ausleihen

Band 2 Band 1
ausleihen ausleihen

beide Bände beide Bände


zurückgeben zurückgeben

∗ Nach der Ausleihe


Zustand des Netzes nach dem Schalten Transitionen, d.h. nach der
Ausleihe. Diese Abbildung zeigt, dass das Netz verklemmt ist; es
gibt keinen Systemfortschritt mehr. Was ist das Problem unseres
Modells? Bei Student 1 und Student 2 haben die Ausleihe der Bänder
unterschiedliche Reihenfolgen; bei gleicher Reihenfolge der Ausleihe tritt
keine Verklemmung ein.

73
Schlichter, TU München 3.4. THREAD-KONZEPT

Student 1 Band1 Band 2 Student 2

Band 1 Band 2
ausleihen ausleihen

Band 2 Band 1
ausleihen ausleihen

beide Bände beide Bände


zurückgeben zurückgeben

• Weitere Eigenschaften
Weitere interessante Eigenschaften - nur ganz informell - sind

– Fairness
Gegeben sei ein Netz N mit Anfangsmarkierung M. Das Netz ist unfair für
eine Transition t, wenn es eine unendliche Sequenz gibt, in der t nur endlich
oft auftritt, obwohl t unendlich oft transitionsbereit ist.
– Verhungern
t verhungert (engl. Starvation): Es gibt eine unendliche Sequenz, in der die
Transition t niemals auftritt. Falls unfaire Sequenz: trotz Transitionsbereit-
schaft von t.

3.4 Thread-Konzept
Threads sind ein BS-Konzept für die Modellierung und Realisierung von
nebenläufigen Aktionen in einem Rechensystem. Threads (Kontrollflüsse) 2
beschreiben die Aktivitäten in einem Rechensystem. Sie können als virtuelle
2
[nehmer2001 S97]

74
Schlichter, TU München 3.4. THREAD-KONZEPT

Prozessoren aufgefasst werden, die jeweils für die Ausführung eines zugeordneten
Programms in einem Adressraum verantwortlich sind. Threads konkurrieren um
die physische CPU, um ablaufen zu können. In traditionellen Umgebungen hat
jeder Prozess genau einen Thread, der den Kontrollfluss des Prozess repräsentiert,
während in Multithreaded-Umgebungen ein Prozess mehrere Threads besitzen
kann.

Prozess

Benutzer
Adressraum

Thread Thread

Betriebssystem

3.4.1 Charakterisierung von Threads


Aus BS-Sicht ist ein Prozess definiert
durch einen Adressraum.
eine darin gespeicherte Handlungsvorschrift in Form eines sequentiellen
Programms (Programmcode).
einen oder mehreren Aktivitätsträgern, die dynamisch die Handlungsvor-
schrift ausführen ⇒ Threads.

Motivation

Ein Thread ist die Abstraktion eines physischen Prozessors; er ist ein Träger einer
sequentiellen Aktivität. Gründe für die Einführung von Threads:

• mehrere Threads ermöglichen Parallelität innerhalb eines Prozesses unter


Nutzung des gemeinsamen Adressraums. Durch die Nutzung des gemeinsamen
Adressraums wird die Interaktion zwischen den Threads (Kommunikation und
gemeinsame Nutzung von Daten) erleichtert. Jeder Thread für sich gesehen
repräsentiert ein streng sequentielles Verarbeitungsmodell.
• Aufwand für Erzeugen und Löschen von Threads ist geringer als für Prozesse.
Threads führen nicht so einen großen Ballast an Information mit sich als

75
Schlichter, TU München 3.4. THREAD-KONZEPT

Prozesse. Beispielsweise muss bei der Erzeugung eines Prozesses durch


das BS ein neuer Adressraum generiert werden; Threads laufen im bereits
vorhandenen Adressraum ab. Deshalb spricht man bei Threads auch von
Leichtgewichtsprozesse ("light weight processes"), da sie erheblich weniger
Verwaltungsinformation als normale Prozesse ("heavy weight processes")
benötigen.

• Verbesserung der Performanz der Applikationsausführung durch Nutzung


mehrerer Threads. Dieses Argument ist besonders dann von Bedeutung, wenn
die Applikation (und damit der zugehörige Prozess) sowohl CPU- als auch E/A-
intensive Aktivitäten beinhaltet. E/A-Wartezeiten innerhalb einer Applikation
können durch andere rechenbereite Threads der Applikation genutzt werden.
Dagegen gewinnen CPU-dominierte Applikationen durch die Parallelisierung
mittels Threads weniger an Performanz (falls nur eine CPU zur Verfügung
steht).

• Threads ermöglichen bei einem Multiprozessor-Rechensystem echte Paralleli-


tät innerhalb einer Applikation.

Prozess vs. Thread

Prozesse und Threads haben unterschiedliche Zielsetzungen:

Prozesse gruppieren Ressourcen,

Threads sind Aktivitätsträger, die zur Ausführung einer CPU zugeteilt


werden.

• Threadspezifische Information
Jeder Thread umfasst eine Reihe von Informationen, die seinen aktuellen
Zustand charakterisieren:
Befehlszähler, aktuelle Registerwerte, Keller, Ablaufzustand des Thread.
Ebenso wie ein Prozess befindet sich ein Thread in einem der nachfolgenden
Zustände: rechenwillig, rechnend, wartend, terminiert. Entsprechend den
ausgeführten Aktionen (z.B. Ein-/Ausgabe) und der Zuteilung bzw. des Entzugs
der CPU finden Zustandsübergänge statt. Jeder Thread hat seinen eigenen
Keller, in dem die Unterprogrammaufrufe verwaltet werden. Jeder Thread hat
seinen eigenen Satz an Registern (darunter auch den Befehlszähler), die gerettet

76
Schlichter, TU München 3.4. THREAD-KONZEPT

werden müssen, falls einem Thread die CPU entzogen wird. Bei einer CPU-
Zuteilung werden die geretteten Registerwerte des Threads in die jeweiligen
Register geladen.

• Prozessspezifische Information
Verschiedene Threads eines Prozesses sind nicht so ganz unabhängig wie
verschiedene Prozesse. Die nachfolgende Information/Ressourcen wird von
allen Threads eines Prozesses geteilt. Jeder Thread des Prozesses kann sie
verwenden bzw. darauf zugreifen.
Adressraum, globale Variable, offene Dateien, Kindprozesse (z.B. erzeugt
mit fork), eingetroffene Alarme bzw. Interrupts, Verwaltungsinformation
Dies sind Eigenschaften des Prozesses und nicht eines einzelnen Threads.
Beispielsweise, wenn ein Thread eine Datei öffnet, dann ist diese Datei auch
für die anderen Threads sichtbar, und sie können in sie schreiben bzw. aus ihr
lesen. Diese Information ist i.a. zwischen Prozessen nicht sichtbar, außer dass
vom Vaterprozess an den Kindprozess Dateideskriptoren vererbt werden.

Beispiel: Web-Server

Ein Prozess kann mehrere Threads umfassen, die unterschiedliche Aufgaben über-
nehmen. Beispielsweise kann ein Web-Server einen Verteiler-Thread ("dispat-
cher") und mehrere Server-Threads ("worker-thread") umfassen.

Web-Serverprozess

Verteiler- Server-
Thread Thread Benutzer
Adressraum

Anforderung

Betriebssystem

Netzwerk-Verbindung

Auf diese Weise ist es möglich den Server als eine Menge von sequentiellen
Threads zu realisieren. Der Verteiler-Thread ist eine unendliche Schleife, die die

77
Schlichter, TU München 3.4. THREAD-KONZEPT

Schnittstelle für den Eingang von Service-Anforderungen darstellt.

• Der Verteiler-Thread dient zur Annahme von Service-Anforderungen und


gibt sie weiter an einen der Server-Threads zur Bearbeitung. Server-Threads
können bei Eintreffen einer Service-Anforderung jeweils dynamisch erzeugt
werden, und nach Erledigung der Anforderung bzw. nach Zustellung der
Antwort terminiert werden. Zur Verbesserung der Antwortzeiten kann der
Web-Server bereits einen Pool von Server-Threads erzeugen, denen jeweils
dynamisch Anforderungen zugeteilt werden können. Server-Threads werden
nach Bearbeitung einer Anforderung nicht beendet, sondern wieder in den Pool
der freien Server-Threads eingereiht. Bei Bedarf können zusätzliche Server-
Threads erzeugt werden, falls alle Server-Threads aus dem Pool bereits belegt
sind.

• Alle Server-Threads nutzen den gemeinsamen Web-Cache.

3.4.2 Threads in Java


Java unterstützt die Programmierung mit Threads, um nebenläufige Abläufe
innerhalb einer Applikation zu ermöglichen. Java Threads können sowohl in Java-
Programmen als auch in Java-Applets verwendet werden. Die Implementierung
der Java Virtual Machine selbst beruht auf Threads: Der Java-Müllsammler
(Garbage collector) ist z.B. ein Thread zum Sammeln von nicht länger
referenzierten Objekten, der nebenläufig zum Java Programm abläuft. Hier
erfolgt nur eine sehr kurze Wiederholung einiger der Aspekte, die bereits in der
Informatik-Einführungsvorlesung behandelt wurden. 3

Definition

Threads können durch Implementierung der Schnittstelle Runnable realisiert


werden. Eine weitere Möglichkeit besteht durch SubClassing der Klasse Thread
selbst, d.h.

public class ReturnDigest extends Thread { ....... }

• Thread Implementierungen überschreiben die run-Methode der Schnittstelle


Runnable.
3
siehe Einführung in die Informatik I/II von Prof. Seidl.

78
Schlichter, TU München 3.4. THREAD-KONZEPT

public class CallbackDigest implements Runnable {


....
public void run() { .... }
}
• Thread Instanzen werden durch den Aufruf der start-Methode der Schnittstelle
Runnable gestartet. Diese Methode sollte durch eine Thread-Implementierung
nicht verändert werden. Die start-Methode ruft die run-Methode auf, wodurch
die Instanz der Thread-Implementierung ausgeführt wird.
public static void main(String[] args) {
....
CallbackDigest cb = new CallbackDigest(...);
Thread t = new Thread(cb);
[Link]();
}
Die Anweisung [Link]() ruft die run-Methode der Klasse CallbackDigest
auf.

Ergebnisrückgabe

Der Ablauf der Threads ist asynchron, d.h. die Ausführungsreihenfolge einer
Menge von Threads ist nicht fest vordefiniert. Dies ist insbesondere bei
kooperierenden Threads von Bedeutung, z.B. bei der Ergebnisrückgabe eines
Thread an einen anderen Thread. Die Ausführungsreihenfolge ergibt sich
durch die CPU-Zuteilung (Scheduling) durch das Betriebssystem oder das
Laufzeitsystem. Dies bedeutet, dass bei der Kommunikation zwischen Threads
nicht von einem bestimmten Zeitverhalten der Threads ausgegangen werden kann,
d.h. wann welche Threads ausgeführt werden.

• Direkter Ansatz
Angenommen jeder Thread liest eine Datei und erzeugt daraus die zugehörige
Hash-Information (z.B. verwendet für verschlüsselte Datenübertragung).
public class ReturnDigest implements Runnable {
private File input;
private byte[] digest;
public ReturnDigest(File input) { [Link] = input; }
public void run() {
......
digest = .......
}
public byte[] getDigest() { return digest; }

79
Schlichter, TU München 3.4. THREAD-KONZEPT

}
public class ReturnDigestUserInterface {
......
public static void main(String[] args) {
......
for (int i = 0; i < [Link]; i++) {
File f = new File(args[i]);
ReturnDigest dr = new ReturnDigest(f);
Thread t = new Thread(dr); [Link](); Berechnung
Hash
.....
byte[] digest = [Link](); Abruf von Hash
....
}
}
}
Jeder Thread speichert das Ergebnis der Dateibearbeitung in der Variablen
digest, auf die über die Methode getDigest zugegriffen werden kann.
[Link]() ruft die run-Methode auf und berechnet die Hash-Information, die
in der lokalen Variablen digest gespeichert wird.

– Die Ausführung führt zu dem Fehler

Exception in thread "main" [Link]


at [Link].
Die Variable digest wird vor der Thread-Initalisierung benutzt. Dies liegt
daran, dass das Hauptprogramm nach der Erzeugung des Thread Zugriff
auf die Variable digest erhält, ohne dass der Thread die Möglichkeit der
Intialisierung bzw. zur Berechnung des Wertes für digest erhielt.
In einer single-threaded Umgebung würde dieses Programm korrekt ab-
laufen, da nach [Link]() sofort der entsprechende Thread ausgeführt
wird.
In einer multi-threaded Umgebung laufen die Threads dagegen asyn-
chron ab, d.h. die CPU-Zuteilung hängt vom Laufzeitsystem (bzw. Be-
triebssystem ab). Man könnte nun den main-Thread künstlich verzögern,
jedoch es besteht eine "Race-Condition" zwischen den kooperierenden
Threads und man kann keine Aussage über die Java Virtual Machine ma-
chen, wann welcher Thread rechnend gesetzt wird.
Aufruf des interaktiven Beispiels: "java ReturnDigestUserInterface testda-
[Link] [Link] [Link]".

80
Schlichter, TU München 3.5. SYNCHRONISATION

• Callback Ansatz
Nicht das main-Programm holt die Ergebnisse ab, sondern die aufgerufenen
Threads rufen jeweils eine Methode des main-Programms auf, um die
Ergebnisse zu übergeben ⇒ Callback .
public class CallbackDigest implements Runnable {
private File input;
public CallbackDigest(File input) { [Link] = input; }
public void run() {
......
byte[] digest = ........;
[Link](digest);
}
public byte[] getDigest() { return digest; }
}
public class CallbackDigestUserInterface {
......
public static void receiveDigest(byte[] digest) {
.....
}
public static void main(String[] args) {
......
for (int i = 0; i < [Link]; i++) {
File f = new File(args[i]);
CallbackDigest dr = new CallbackDigest(f);
Thread t = new Thread(dr); [Link]();
}
}
}
Im Gegensatz zum main-Programm des direkten Ansatzes dient das main-
Programm dieses Ansatzes nur zum Starten der verschiedenen Threads. Es
versucht nicht die Berechnungen der getriggerten Threads direkt zu lesen
und zu verarbeiten. Dies wird durch separate Methode receiveDigest
erledigt. Aufruf des interaktiven Beispiels: "java CallbackDigestUserInterface
[Link] [Link] [Link]".

3.5 Synchronisation
Eine wichtige Systemeigenschaft betrifft die Synchronisation paralleler Ereignis-
se. In einem Rechensystem konkurrieren parallele Aktivitäten um wiederholt ex-

81
Schlichter, TU München 3.5. SYNCHRONISATION

klusiv (d.h. zu einem Zeitpunkt darf höchstens eine Aktivität die Ressource nut-
zen) benutzbare Ressourcen, wie beispielsweise die CPU, den Drucker etc. Zu-
sätzlich dazu können aber parallele Aktivitäten auch kooperieren, indem sie Daten
über gemeinsam benutzte exklusive Objekte austauschen oder sich Nachrichten
zusenden. In all diesen Fällen haben wir das Problem, den wechselseitigen Aus-
schluss (engl. mutual exclusion) zu gewährleisten, d.h. sicherzustellen, dass nur
höchstens ein Prozess zu einem gegebenen Zeitpunkt eine exklusiv benutzbare
Ressource belegt.

3.5.1 Beispiele
Die beiden Beispiele basieren auf der speicherbasierten Prozessinteraktion,
d.h. Prozesse (oder auch Threads) interagieren über gemeinsam zugreifbare
Speicherzellen.

Beispiel: gemeinsame Daten

P1 und P2 sind nebenläufige Prozesse, die in einem Multiprozessorsystem parallel


ablaufen. Die Variable x ist gemeinsame Variable. Prozess P1 läuft auf CPU 0
mit Prozess P2 auf CPU 1 gleichzeitig ab. Das Problem ergibt sich auch bei
quasiparallelem Ablauf (zeitliche Verschränkung der Arbeit der Prozesse). Z sei
ein Zeitpunkt nach Ausführung der Aktionen A und B. Welchen Wert hat x zum
Zeitpunkt Z?
Das Ergebnis des Ablaufs kann je nach zeitlichem Ablauf x = 1, 2, 3 sein.
Der grundlegende Nichtdeterminismus der Nebenläufigkeit wegen der Asynchro-
nität schlägt hier auf die Ergebnisse der Prozesse durch.

82
Schlichter, TU München 3.5. SYNCHRONISATION

int x; x = 0

Prozess P1 Prozess P2

A: x = x + 1
B: x = x + 2

Zeitpunkt Z

• Das Ergebnis ist vom zeitlichen Ablauf abhängig. Es sind folgende Fälle
möglich:

– Fall 1
P1 liest x = 0, erhöht, speichert x = 1;
P2 liest x = 1, erhöht, speichert x = 3; => Wert von x = 3
– Fall 2
P2 liest x = 0, erhöht, speichert x = 2;
P1 liest x = 2, erhöht, speichert x = 3; => Wert von x = 3
– Fall 3
P1 und P2 lesen x = 0;
P1 erhöht, speichert x = 1;
P2 erhöht, speichert x = 2; => Wert von x = 2
– Fall 4
P1 und P2 lesen x = 0;
P2 erhöht, speichert x = 2;
P1 erhöht, speichert x = 1; => Wert von x = 1
• Verhinderung des Nichtdeterminismus nur dadurch möglich, dass man garan-
tiert, dass die Veränderung von x in den beiden Prozessen unter wechselseiti-
gem Ausschluss (engl. mutual exclusion) erfolgt. Die Asynchronität der Pro-
zesse muss also genau an dieser Stelle eingeschränkt werden. Vernderung be-
steht in diesem Zusammenhang aus 3 Schritten: Lesen des Wertes, Erhöhen und
Speichern des neuen Wertes.

83
Schlichter, TU München 3.5. SYNCHRONISATION

Erzeuger-Verbraucher-Problem

Ein Beispiel für einen synchronisierten Zugriff auf eine gemeinsame Ressource,
nämlich einen Puffer 4 , haben wir bereits kennengelernt. Interpretiert man das
bereits angesprochene → Petri-Netz (siehe Seite 68) als eine Komposition aus drei
Teilen:
einem Erzeuger von Nachrichten (links),
einem Puffer für Nachrichten (Mitte) und
einem Verbraucher von Nachrichten (rechts).
So kann man sehen, dass durch diese Modellierung gewährleistet wird, dass
Erzeuger und Verbraucher nicht gleichzeitig etwas in den Puffer eintragen und
aus ihm entnehmen können; sie greifen wechselseitig ausgeschlossen zu.

3.5.2 Definition: Wechselseitiger Ausschluss


Gegeben sei ein Petri-Netz (S, T, F) und eine Anfangsmarkierung M0.
Wenn zwei Transitionen t1, t2 ∈ T wechselseitig ausgeschlossen sind,
dann ist keine Markierung M’ erreichbar, so dass t1 und t2 unter dieser
Markierung gleichzeitig transaktionsbereit sind. Wir sagen, dass Transitionen, die
wechselseitig ausgeschlossen auszuführen sind, kritische Abschnitte (engl critical
section, critical region) eines Systemablaufs modellieren.

• Beispiel: gemeinsame Daten


Der Zugriff auf gemeinsame Ressourcen, z.B. auf gemeinsame Variable,
muss koordiniert werden. Bei exklusiven Ressourcen wird die Nutzung
sequentialisiert. Die gemeinsame Ressource wird in einem kritischen Bereich
bzgl. der gemeinsamen Ressource benutzt.
4
Dieses Problem wurde bereits in der Einführungsvorlesung zu Informatik ausführlich
behandelt.

84
Schlichter, TU München 3.5. SYNCHRONISATION

Prozess P1: Prozess P2:


main () { main () {
....... .......
region x do region x do
x = x + 1: x = x + 2:
end region end region
........ ........
} }

3.5.3 Modellierung
Modelliert man parallele Einheiten, die kritische Abschnitte besitzen, durch Petri-
Netze, so sind vier Phasen dieser parallelen Aktivitäten von Interesse:
1. Ausführen unkritischer Abschnitte/Transaktionen
2. Betreten eines kritischen Abschnitts
3. Ausführen der Transaktion(en) des kritischen Abschnitts
4. Verlassen des kritischen Abschnitts.
Modellierung jeder Phase durch eine Transition; Koordinierung des wechselseiti-
gen Ausschluss durch Kontrollstelle s.

Prozess 1 Prozess 2

t2 Eintritt Eintritt
t1: Phase 1; unkritische Transition
t2: Phase 2; Eintritt in kritischen Abschnitt
t3: Phase 3; Ausführung des kritischen
Abschnitts
t4: Phase 4; Verlassen des kritischen
Abschnitts
s: Kontrollstelle
k.A.
t1 t3 s

t4 Austritt Austritt

• Beispiel: Leser-Schreiber-Problem

85
Schlichter, TU München 3.5. SYNCHRONISATION

Betrachten wir als Beispiel ein weiteres klassisches Synchronisationsproblem:


das Leser-Schreiber-Problem. Eine einfache Version des Leser-Schreiber-
Problems ist wie folgt gegeben. Das System umfasst Lese-Aktivitäten, die in
ihrem kritischen Abschnitt lesend auf eine gemeinsame Ressource zugreifen
und Schreib-Aktivitäten, die in ihrem kritischen Abschnitt schreibend auf die
gemeinsame Ressource zugreifen. Wir fordern:
1. Lese-Aktionen im kritischen Abschnitt können parallel stattfinden, wobei
die Anzahl der parallelen Leser begrenzt sei, z.B. auf drei.
2. Lese- und Schreib-Aktionen sind wechselseitig ausgeschlossen.
3. auch Schreib-Aktionen sind untereinander wechselseitig ausgeschlossen.
Die Abbildung zeigt eine mögliche Modellierung mittels eines Petri-Netzes
mit drei Lesern und drei Schreibern. Die Anfangsmarkierung der Stelle s
beschreibt die Anzahl der Leser, die maximal parallel im kritischen Abschnitt
arbeiten dürfen. Will ein Schreiber den kritischen Abschnitt betreten, so müssen
alle drei Marken auf s liegen (kein Leser im kritischen Abschnitt). Durch
die Kantengewichtung, werden beim Betreten des kritischen Abschnitts alle
Marken von s durch den Schreiber konsumiert. Beim Verlassen des kritischen
Abschnitts, werden wieder drei Marken produziert, also allen Lesern wieder ein
Zugriff ermöglicht.

Leser Schreiber

Eintritt Eintritt

k.A. k.A.
s

Austritt Austritt

Jedes Token im Leserteilnetz repräsentiert einen Leser; jedes Token im


Schreiberteilnetz repräsentiert einen Schreiber.

86
Schlichter, TU München 3.5. SYNCHRONISATION

3.5.4 Synchronisierungskonzepte
Ziel: Einführung wichtiger Realisierungskonzepte zur Synchronisierung paralleler
Abläufe. Dazu Konkretisierung des Prozessbegriffs. Um die modellierten Eigen-
schaften eines System zu realisieren, benötigt man Konzepte zur Formulierung
paralleler Abläufe. Auf der programmiersprachlichen Ebene sind dies Sprachkon-
strukte, wie die Java-Threads oder die Ada-Tasks. Für das Folgende benötigen
wir einen Prozessbegriff, der den abstrakten → Prozessbegriff (siehe Seite 52)
zunächst nur so konkretisiert, dass wir damit erste wichtige Konzepte zur Rea-
lisierung von Abhängigkeiten zwischen parallelen Aktivitäten einführen können.
Dies ist ein erster Schritt in die Richtung auf einen Prozess, wie er auf der Be-
triebssystemebene benötigt wird. Auf die weitere Konkretisierung eines Prozesses
als Betriebssystem-Verwaltungseinheit zusammen mit den Maßnahmen zur seiner
Verwaltung gehen wir in den folgenden Abschnitten ein.

Prozess - Konkretisierung

Ein Prozess ist ein eindeutig identifizierbarer Ablauf eines Programms in


einem Rechensystem. Der Ablauf ist bestimmt durch die Befehle und Daten
des Programms. Ein Prozess kann unterschiedliche Zustände besitzen. Wir
unterscheiden die Zustände erzeugt, rechnend, rechenwillig, wartend, terminiert.
Die Zustände eines Prozesses und Beispiele für Aktionen, die Zustandsübergänge
zur Folge haben, sind in der Abbildung angegeben.

E/A-Auftrag wartend

fork start
erzeugt rechnend
CPU-Entzug E/A-
Auftrag
end beendet
CPU
Zuteilung

termi- kill rechen- kill


niert willig

Zur Verwaltung eines Prozesses wird eine Datenstruktur benötigt, die die Infor-
mation, die einen Prozess charakterisiert, beinhaltet. Dies ist der Prozess-Kontext
(Prozess-Deskriptor), der auf dieser Konkretisierungsebene den eindeutigen Pro-
zessnamen und die Prozesszustände umfasst und später noch erweitert wird (z.B.

87
Schlichter, TU München 3.5. SYNCHRONISATION

Priorität, Registerinhalte).

Konzepte für wechselseitigen Ausschluss

Die Netz-Modellierung hat bereits gezeigt, dass man zur Synchronisation von
Prozessen spezifische Kontrollkomponenten benötigt (z.B. zusätzliche Stellen
im Petri-Netz, oder Kapazitätsbeschränkungen, die implizit durch die abstrakte
Kontrollkomponente, die die Transitionsbereitschaft von Transitionen prüft,
kontrolliert werden).
Weiterhin hat die Modellierung gezeigt, dass durch die Synchronisationsmaßnah-
men, die ja im wesentlichen durch absichtlich herbeigeführte Konflikte modelliert
wurden, ggf. unfaire Abläufe auftreten, die in einem realisierten System natürlich
unerwünscht sind. Das heißt, wir benötigen geeignete Konzepte, durch die diese
Kontrollaufgaben wahrgenommen werden und ein unfaires Verhalten vermieden
wird.

• Anforderungen
Folgende Anforderungen sind an eine Realisierung des wechselseitigen
Ausschlusses (w.A.) zu stellen:

– Die kritischen Abschnitte der Prozesse sind wechselseitig auszuschließen.


– Eine Realisierung des w.A. darf nicht von einer Annahme über die
Reihenfolge, in der die Prozesse ihre kritischen Abschnitte ausführen,
abhängen.
– Eine Realisierung des w.A. darf nicht von Annahmen über die Ausführungs-
zeit der Prozesse abhängen.
– Unter der Annahme, dass Prozesse nach endlicher Zeit ihre kritischen
Abschnitte wieder verlassen, muss gelten, dass kein Prozess einen anderen
Prozess unendlich lange daran hindern darf, seinen kritischen Abschnitt
auszuführen.

• Jede Realisierung des w.A. benötigt eine Basis, mit festgelegten atomaren, d.h.
nicht teilbaren Operationen. Diese unteilbaren Basisoperationen sind von Hard-
und/oder Software zur Verfügung zu stellen. Informell: mit einer atomaren
Operation kann überprüft werden, ob der kritische Abschnitt frei ist; falls
ja kann er sofort betreten werden (und der kritische Abschnitt damit belegt
werden). Falls die Abfrage und das Betreten nicht atomar sind, können mehrere
zeitlich-verzahnte Abfrage stattfinden, und gegebenenfalls mehrere Prozesse
den kritischen Abschnitt betreten.

88
Schlichter, TU München 3.5. SYNCHRONISATION

• Unterbrechungssperre
Der Ablauf des Prozesses darf nicht unterbrochen werden.

– In Ein-Prozessorsystemen (1 CPU) kann es ausreichend sein, mit Enable und


Disable Interrupt Operationen dafür zu sorgen, dass der Prozess, der einen
kritischen Abschnitt ausführt, dabei nicht unterbrochen wird. Dies ist nur
eine sinnvolle Vorgehensweise, wenn die kritischen Abschnitte kurz sind, da
ansonsten die Systemantwortzeiten sehr hoch werden und u.U. E/A-Aufträge
nicht rechtzeitig behandelt werden. Atomarität durch Unterbrechungssperre
funktioniert nicht unbedingt bei Mehrprozessormaschinen.
– Realisierung mit Unterbrechungssperre ist nützlich für den Betriebssystem-
kern, aber sollte nicht für allgemeine Benutzerprogramme zur Verfügung ste-
hen. Maschine ’hängt’, wenn Benutzerprogramm den kritischen Abschnitt
nicht mehr verlässt.

• Test-and-Set Operationen
Test-and-Set Operationen (Test-And-Set-Lock, TSL) erlauben auf Hardware-
Ebene (Maschinenbefehl) das Lesen und Schreiben einer Speicherzelle als
atomare Operation.

– Semantik eines Test-and-Set-Befehls


Die Instruktion liest den Inhalt eines Speicherwortes in ein Register und
schreibt einen Wert ungleich Null an die Adresse dieses Wortes. Diese beiden
Operationen werden als atomare, unteilbare Sequenz ausgeführt.
Sei a die zu untersuchende Speicherzelle; der Wert 1 in der Speicherzelle
kann dahingehend interpretiert werden, dass der Zugang in den kritischen
Bereich nicht möglich ist.
Befehl "TSL R, a" entspricht dann
Register R = inhalt von a;
a = 1
Falls R = 1 ist, ist der kritische Bereich bereits belegt, andernfalls war er
frei und er wurde vom ausführenden Prozess belegt.
Durch Hardware bereitgestellte atomare Lese- und Schreiboperationen findet
man z.B. in Sun SPARC mit Befehl: compare and swap; entsprechendes gibt
es bei Motorola, Intel 80x86, Mips R4000.
∗ Problem: wie Atomarität bei Rechensystem mit mehreren CPUs gewähr-
leistet?
∗ Lösung: Die CPU, die die TSL-Instruktion ausführt, blockiert den
Speicherbus, um andere CPU’s (Multi-Prozessorumgebung) daran zu
hindern, auf die Speichereinheit zuzugreifen.

89
Schlichter, TU München 3.5. SYNCHRONISATION

• Dienste mit passivem Warten


Unterscheidung zwischen

aktivem Warten: Prozess muss periodisch selber prüfen, ob die Vorausset-


zungen zum Weiterarbeiten erfüllt sind.

passivem Warten: Prozess wird in Warte-Zustand versetzt und aufgeweckt,


wenn das Ereignis, auf das er wartet, eingetreten ist.
Aktives Warten hat den Nachteil, dass für andere Prozesse nutzbare CPU-
Zyklen durch das wiederholte Anfragen, ob die Voraussetzungen zum
Weiterarbeiten erfüllt sind, nutzlos verschwendet werden. Nachfolgend werden
einige Dienste für passives Warten kurz aufgelistet.

– Methoden oder Dienste, so dass unter Mithilfe des Betriebssystems ein


Prozess in den Zustand wartend übergeführt wird.
– beim Eintreten eines passenden "Weckereignisses" wird der Prozess
vom Betriebssystem vom Zustand wartend in den Zustand rechenbereit
übergeführt.
– Beispiel: Java wait und notify.
Wait: passives Warten auf das Eintreffen einer Bedingung und atomar
gleichzeitig Freigabe der umfassenden Sperre einer synchronized
Methode. Wait/notify nur innerhalb von synchronized nutzbar!
Notify: Benachrichtigen eines wartenden Threads.
Aber: in Java nicht möglich anzugeben, auf WAS ein Thread warten soll
bzw. WELCHE Bedingung eingetreten ist. Nach dem Aufwecken muss
der Thread also noch einmal explizit prüfen, ob der Weckruf den Thread
wirklich betrifft. In Unix gibt es die Aufrufe Sleep and Wakeup; dies
sind Betriebssystemaufrufe, mit denen der Aufrufer blockiert und wieder
rechenbereit gesetzt werden kann.

• Semaphor-Konzept
Das Semaphor-Konzept ermöglicht die Realisierung des w.A. auf einem hö-
heren Abstraktionslevel als die bereits angesprochenen Hardwareoperationen.
Zur Realisierung wird aber auf diese wieder zurückgegriffen. Realisierung von
Semaphoren mit aktivem und passivem Warten möglich.

• Monitor-Konzept

90
Schlichter, TU München 3.5. SYNCHRONISATION

Das Monitor-Konzept basiert auf der Idee, die in einem kritischen Bereich
bearbeiteten Daten zusammen mit den darauf definierten Zugriffsoperationen
in einer sprachlichen Einheit - dem Monitor - zusammenzufassen.
soll Probleme, wie sie bei der Programmierung von Semaphoren auftreten,
vermeiden. Beispiele sind die Vertauschung der P-Operationen bei
Semaphoren, oder das Vergessen der zugehörigen V-Operation. Bei
Monitoren wird die richtige Reihenfolge der Synchronisierungsoperationen
durch den Compiler generiert.
zu einem Zeitpunkt höchstens ein Prozess innerhalb des Monitors aktiv.
Prozesse können zwar jederzeit die Methoden (Prozeduren) eines Monitors
aufrufen, jedoch können sie nicht direkt auf die internen Daten eines
Monitors zugreifen. Zu jedem Augenblick kann nur ein Prozess innerhalb
des Monitors aktiv sein. Der erfolgreiche Aufruf einer Monitorprozedur
ist gleichbedeutend mit der Sperre des Monitors, die bis zum Verlassen
der Monitorprozedur bestehen bleibt. Die Vorteile des Monitor-Konzepts
gegenüber den Semaphoren ist a) die gemeinsamen Daten werden in der
Programmstruktur der beteiligten Prozesse explizit sichtbar gemacht, und
b) Monitore kapseln alle relevanten Daten und Algorithmen des kritischen
Bereichs.

Gemeinsame Daten
Warte
schlange

Operationen

Initialisierungscode

– Definition von Bedingungsvariablen zur Spezifikation anwendungsspezifi-


scher Bedingungen. Innerhalb eines Monitors können Condition-Variable de-
finiert werden, die anwendungsspezifische Bedingungen formulieren. Jede
Condition-Variable steht für eine Bedingung, die für die Fortsetzung eines
Prozesses in einer Monitorprozedur erfüllt sein muss. Falls die Bedingung
nicht erfüllt ist, wird die wait-Operation auf dieser Condition-Variable aus-
geführt. Mit signal können Prozesse wieder aufgeweckt werden.
– Operationen auf Bedingungsvariable cond

91
Schlichter, TU München 3.5. SYNCHRONISATION

[Link](): Prozess wird wartend gesetzt. Er bleibt solange war-


tend, bis ein anderer Prozess die signal-Operation auf der Bedingungsva-
riablen cond ausführt.

[Link](): ein wartender Prozess wird aktiviert. Falls kein


Prozess wartet, hat signal keine Auswirkungen. Falls ein Prozess Q
aktiviert wird, sorgt das Monitorkonzept dafür, dass nun nicht beide
Prozesse, der aktivierende Prozess P und der aktivierte Prozess Q im
Monitor aktiv sind.
signal and wait: P wartet entweder bis Q den Monitor verlässt oder wartet
auf eine andere Bedingung.
signal and continue: Q wartet entweder bis P den Monitor verlässt oder
wartet noch auf eine andere Bedingung.

3.5.5 Semaphore
Semaphore wurden 1968 von Dijkstra eingeführt. Ein Semaphor (Signalmast) ist
eine ganzzahlige Koordinierungsvariable s, auf der nur die drei vordefinierten
Operationen (Methoden) zulässig sind:
Initialisierung,
Prolog P (kommt von protekt),
Epilog V (kommt von vrej).
In der Einführungsvorlesung von Prof. Seidl wurden die Bezeichnung down für P
und up für V verwendet.

Operationen

Die Operationen P und V sind atomar; sie sind unteilbar und sie werden
wechselseitig ausgeschlossen ausgeführt.
Sei s die Koordinierungsvariable, dann sind die P und V Operationen wie
nachfolgend definiert.
Die Operation müssen mit Hilfe von Systemdiensten so realisiert werden, dass
sie wechselseitig ausgeschlossen ausgeführt werden. Vorsicht: hier gibt es keine
ganz einheitliche Definition in der Literatur für die beiden Operationen. Mögliche
Realisierung auf Hardware-Ebene mittels des Test-and-Set Maschinenbefehls. Die
P und V Operationen werden mit Hilfe von TSL im BS-Kern auf Maschinenebene
realisiert.

92
Schlichter, TU München 3.5. SYNCHRONISATION

• Informelle Charakterisierung
public void P (int s) {
s = s - 1;
if ( s < 0 ) { Prozess in die Menge der bzgl. s wartenden
Prozesse einreihen }
}
public void V (int s) {
s = s + 1;
if ( s ≤ 0 ) { führe genau einen der bzgl. s wartenden
Prozesse in den Zustand rechenwillig über }
}
s ist mit einem ganzzahligen Wert vorbesetzt, z.B. s = 1. Falls s mit einem Wert
größer 1 vorbesetzt ist, bedeutet dies die Anzahl der Prozesse, die gleichzeitig
im kritischen Bereich erlaubt sind. Die beiden Funktionen müssen jeweils
atomar ausgeführt werden, d.h. nicht als Java Programm.

• Binäres Semaphor: die Kontrollvariable s nimmt nur boolesche Werte an.


man spricht auch von Mutex.

– Mutex in Posix
Ein Posix Mutex ist als binäres Semaphor eine einfache Sperre, die die
Nutzung gemeinsamer Ressourcen absichert.
pthread_mutex_init(mutex) ⇒ initialisiert und konfiguriert ein Mutex.
pthread_mutex_lock(mutex) ⇒ entspricht der P-Operation; sperrt ein
Mutex.
pthread_mutex_unlock(mutex) ⇒ entspricht der V-Operation; gibt ein
Mutex frei.
Mutex Objekte und Semaphore mit Integer Werten stehen auch in Windows
zur Verfügung.

Einsatz von Semaphoren

Notation: Zur Vereinfachung gehen wir im Folgenden von einem vordefinierten


Typ semaphor(int s) aus, der die P und V Operationen als vordefinierte,
atomare Methoden anbietet. Semaphor-Objekte werden als Instanzen bezüglich
des Typs semaphor erzeugt, wobei bei der Instantiierung das Semaphor mit dem
Parameter s initialisiert wird.

• Zugang zu kritischen Abschnitten

93
Schlichter, TU München 3.5. SYNCHRONISATION

Realisierung der kritischen Abschnitte von Prozessen, in denen auf eine


exklusiv benutzbare Ressource X zugegriffen wird:

1. Definition eines Semaphor-Objekts wa: semaphor(1), d.h. Initialisierung der


Kontrollvariable des Semaphor-Objekts wa mit 1.
2. Klammern der kritischen Abschnitte, in denen auf die Ressource X
zugegriffen wird, mit P und V Operationen:
wa.P
Code mit Zugriffen auf X
wa.V

• Die Anforderungen an Lösungen des wechselseitigen Ausschlusses sind mit


dem Semaphor-Konzept aus folgenden Gründen erfüllt:

– Wechselseitiger Ausschluss für alle kritischen Abschnitte. Aufgrund der


Initialisierung der Koordinierungsvariablen mit 1 kann sich stets nur ein
Prozess in einem kritischen Abschnitt befinden.
– keine Reihenfolge-Annahmen. Annahmen über die Ausführungsreihenfolge
der kritischen Abschnitte gehen nicht ein.
– keine Ausführungszeit-Annahmen. Es werden keine Annahmen über die
Ausführungszeiten der Prozesse gemacht.
– kein Verhungern. Hier muss bei der Realisierung des Semaphors eine
faire Strategie, z.B. FIFO (First-In-First-Out), zum Einsatz kommen. Wenn
die blockierten Prozesse aus dem Warteraum nach FIFO entnommen
werden und jeder kritische Abschnitt mit der P- und der V-Operation des
Semaphors geklammert ist, wird jeder blockierte Prozess nach endlicher Zeit
entblockiert und kann somit seinen kritischen Abschnitt ausführen.

Beispiel Erzeuger-Verbraucher

Im Modellierungsteil wurde das → Erzeuger-Verbraucher-Problem (siehe


Seite 68) bereits kurz vorgestellt.
Der Erzeuger-Prozess E erzeugt Datenelemente und schreibt sie in einen
Puffer W.
Der Verbraucher-Prozess V liest Datenelemente aus dem Puffer und
verarbeitet sie.
Der Zugriff der beiden Prozesse auf den Puffer ist zu synchronisieren.
Lösung dieses Problems mittels Semaphor.

94
Schlichter, TU München 3.5. SYNCHRONISATION

• Variante 1
Zugriff auf Puffer W erfolgt durch Semaphor wa: semaphor(1); sowohl der
Erzeuger-Prozess E als auch der Verbraucher-Prozess V rufen vor jedem Zugriff
auf den Puffer W die entsprechenden Operationen des Semaphors wa auf.

Erzeuger E: Verbraucher V:
while (true) { while (true) {
produziere wa.P
wa.P entnimm aus W, falls Element da; sonst warte
schreibe nach W wa.V
wa.V verarbeite
} }

Problem: es kann eine Verklemmung auftreten, wenn der Verbraucher wa.P


ausführt und warten muss, weil der Puffer kein Element enthält. Andererseits
kann der Erzeuger den Puffer nicht betreten, da bereits der Verbraucher den
Puffer exklusiv belegt hat.

• Variante 2
Einführen eines zusätzlichen Semaphors voll: semaphor(0), das die Datenele-
mente im Puffer zählt:

Erzeuger E: Verbraucher V:
while (true) { while (true) {
produziere voll.P
wa.P wa.P
schreibe nach W entnimm aus W
wa.V wa.V
voll.V verarbeite
} }

Für den Erzeuger ergibt sich natürlich ein analoges Problem, falls der Puffer W
nur eine beschränkte Kapazität besitzt. Eine Abhilfe kann analog wieder durch
die Einführung eines weiteren Semaphors "leer" erreicht werden. Dieses stellt
sicher, dass der Erzeuger den Puffer nicht betritt, wenn der Puffer bereits voll
ist.

• Variante 3

95
Schlichter, TU München 3.5. SYNCHRONISATION

Einführen eines zusätzlichen Semaphors leer: semaphor(n), das die Anzahl der
freien Elemente im Puffer zählt:

[Link](1); //kontrolliert den Zugang zum kritischen Bereich


[Link](0); //zählt die Anzahl der Einheiten im Puffer
[Link](n); //zählt die Anzahl der freien Pufferplätze

Erzeuger E: Verbraucher V:

while (true) { while (true) {


produziere Einheit; voll.P;
leer.P; wa.P;
wa.P; entnimm Einheit aus W
schreibe Einheit nach W; wa.V
wa.V; leer.V;
voll.V; verarbeiteEinheit;
} }

Darf die Reihenfolge der P-Operationen für die Semaphore leer, voll, wa
beim Erzeuger bzw. beim Verbraucher vertauscht werden, ohne dass sich
Ablaufprobleme ergeben?

Beispiel Philosophenproblem

Zu den klassischen Synchronisationsproblemen zählt das Problem der speisenden


Philosophen ("Dining Philosophers"). In einem Elfenbeinturm leben fünf
Philosophen. Der Tageszyklus eines jeden Philosophen besteht abwechselnd aus
Essen und Denken. Die fünf Philosophen essen an einem runden Tisch, auf dem in
der Mitte eine Schüssel voller Reis steht. Jeder Philosoph hat seinen festen Platz
an dem Tisch und zwischen zwei Plätzen liegt genau ein Stäbchen. Das Problem
der Philosophen besteht nun darin, dass der Reis nur mit genau zwei Stäbchen
zu essen sind. Darüber hinaus darf jeder Philosoph nur das direkt rechts und das
direkt links neben ihm liegende Stäbchen zum Essen benutzen. Das bedeutet, dass
zwei benachbarte Philosophen nicht gleichzeitig essen können.

96
Schlichter, TU München 3.5. SYNCHRONISATION

3
2 2
3
4 1
4
0 1
0

• Realisierung mit Semaphoren

– Variante 1
Für eine Lösung des Philosophenproblems seien die folgenden 5 Semaphore
definiert: stab_0, stab_1, ...., stab_4, wobei jedes der 5 Semaphore mit 1
initialisiert ist. Jeder Philosoph j, mit j ∈ {0,...,4}, führe den folgenden
Algorithmus aus:
philosoph_j:
while (true) {
Denken;
stab_i.P; mit i = j
stab_i.P; mit i = j + 1 mod 5
Essen
stab_i.V; mit i = j
stab_i.V; mit i = j + 1 mod 5
}
Der angegebene Algorithmus liefert keine korrekte Lösung des wechselsei-
tigen Ausschlusses! Wenn alle fünf Philosophen gleichzeitig die erste P-
Operation (stab_i.P mit i = j) ausführen, d.h. alle gleichzeitig ihr linkes Stäb-
chen nehmen, folgt daraus eine Verklemmungs-Situation, da kein Philosoph
das zweite Stäbchen nehmen kann. Bei Ausführung der zweiten P-Operation
stab_i.P; mit i=j+1 mod 5 werden alle Philosophen blockiert. Die Philoso-
phen verhungern somit.
– Variante 2
Nur vier Philosophen dürfen gleichzeitig zu ihrem linken Stäbchen
greifen. Dies wird durch Einführung eines weiteren Semaphors tisch:
semaphor(4), das mit 4 initialisiert wird, erreicht. Der "Anweisungsteil"
jedes Philosophen wird zusätzlich mit tisch.P und tisch.V geklammert.

97
Schlichter, TU München 3.5. SYNCHRONISATION

Dadurch ist gewährleistet, dass höchstens vier Philosophen gleichzeitig ihr


linkes Stäbchen nehmen können und somit immer mindestens ein Philosoph
auch sein zweites Stäbchen nehmen und damit essen kann. Es ergibt sich
also folgende Lösung: Jeder Philosoph j, mit j ∈ {0,...,4} führt den folgenden
Algorithmus aus:
philosoph_j:
while (true) {
Denken;
tisch.P
stab_i.P; mit i = j
stab_i.P; mit i = j + 1 mod 5
Essen
stab_i.V; mit i = j
stab_i.V; mit i = j + 1 mod 5
tisch.V
}
Ein weiterer wichtiger Aspekt ist die Reihenfolge bei der Ausführung
von P Operation, falls mehrere Semaphore belegt werden müssen.
Eine unterschiedliche Reihenfolge der P-Operationen bei den beteiligten
Prozessen kann leicht zu einer Verklemmung führen.

3.5.6 Synchronisierung von Java Threads


Java unterstützt synchronisierte Methoden. 5
public synchronized void methodname(...) { ... }
Eine synchronisierte Methode kann nur exklusiv von einem Java Thread betreten
werden. Andere Threads können die synchronisierte Methode erst dann betreten,
wenn der erste Java Thread die Methode wieder verlässt. Einer der wartenden
Threads wird aktiviert. 6

Beispiel TakeANumber Class

Nur ein Thread kann zu einem Zeitpunkt eine Nummer ziehen


class TakeANumber {
private int next = 0; //next place in line
public synchronized int nextNumber() {
next = next + 1; return next;
} //nextNumber
} //TakeANumber
5
siehe Informatik II, Kap. 14 von Prof. Brügge
6
[morelli2000, S727; harold2001, S141]

98
Schlichter, TU München 3.5. SYNCHRONISATION

Wenn ein Thread die synchronized Methode betritt und ausführt, kann kein
anderer Thread diese Methode solange nicht ausführen, bis nicht der erste Thread
die Methode wieder verlässt.
public class Customer extends Thread {
private static int number = 1000; //initial customer ID
private int id;
private TakeANumber takeANumber;
public Customer(TakeANumber gadget) {
id = ++number;
takeANumber = gadget;
} //Customer constructor
public void run() {
try {
sleep( (int)([Link]() * 1000) );
[Link]("Customer "+id+" takes ticket " +
[Link]());
} catch ......
} //run
} //Customer
public class Bakery {
public static void main(String args[]) {
[Link]("Starting Customer threads");
TakeANumber numberGadget = new TakeANumber();
.........
for (int k = 0; k < 5; k++) {
Customer customer = new Customer(numberGadget);
[Link]();
}
} // main
} //Bakery
Die Kunden kommen hierbei nicht alle gleichzeitig, sondern die Ankunftszeit
wird zufällig gewählt; sleep heißt, der jeweilige Kunde wird nach seiner
Erzeugung für eine zufällige Zeit "Schlafen" gelegt, bevor er als Kunde eine
Nummer zieht. Durch "geeignete" Wahl der Zufallszahl können Kunden auch
"fast" gleichzeitig eine Nummer ziehen. Was hier nun noch fehlt, ist eine
Verkäuferklasse, die jeweils die Kunden entsprechend ihrer gezogenen Nummer
bedient (siehe Morelli Kap 15, S 728).

Java Monitor

Ein Monitor ist ein Java-Objekt, das synchronisierte Methoden enthält.

• Ein Monitor stellt sicher, dass nur ein Thread zur Zeit in einer der

99
Schlichter, TU München 3.6. VERKLEMMUNGEN

synchronisierten Methoden sein kann. Bei Aufruf einer synchronisierte


Methode wird das Objekt gesperrt.

• Während das Objekt gesperrt ist, können keine anderen synchronisierten


Methoden des Objekts aufgerufen werden. Andere Threads müssen warten, bis
der erste Thread die synchronisierte Methode wieder verlässt, und damit die
Sperre freigibt.

• Kritische Abschnitte können in Java als Objekte mit den zugehörigen


synchronisierten Methoden spezifiziert werden. Synchronisierte Methoden
können je nach der verwendeten Java Virtual Machine sehr aufwendig und
langsam sein. Weiterhin ist zu beachten, dass zwar innerhalb eines Monitors
eine synchronisierte Methode andere synchronisierte Methoden blockiert, nicht
jedoch unsynchronisierte Methoden. Dies kann u.U. zu Problemen führen.

3.6 Verklemmungen
Mit Verklemmung (engl. deadlock) bezeichnet man einen Zustand, in dem die
beteiligten Prozesse wechselseitig auf den Eintritt von Bedingungen warten, die
nur durch andere Prozesse in dieser Gruppe selbst hergestellt werden können.
Verklemmungen können durch die gemeinsame Verwendung von Ressourcen
(synonym verwenden wir auch den Begriff Betriebsmittel), wie z.B. CPU,
Arbeitsspeicher, E/A-Geräte, Dateien auftreten. Ein Beispiel aus der allgemeinen
Praxis ist eine Verkehrskreuzung, wobei alle 4 Fahrzeuge geradeaus über die
Kreuzung fahren wollen; falls jedes Fahrzeug in die Kreuzung einfährt, können
sie sich gegenseitig blockieren. 7
Der Austausch von Information über gemeinsame Speicherbereiche ist eine
häufige Situation (speicherbasierte Prozessinteraktion), die bei unkorrekter
Verwendung von Synchronisationsoperationen (z.B. P und V bei Semaphoren)
leicht zu Verklemmungen führen kann; siehe die → Variante 1 (siehe Seite 95)
des Erzeuger-Verbraucher Lösungsansatzes. Dieser Abschnitt skizziert nur die
Ansätze zur Erkennung, Vermeidung und Verhinderung von Verklemmungen.

3.6.1 Allgemeines
Es lässt sich zeigen, dass die folgenden Bedingungen notwendig und hinreichend
dafür sind, dass eine Verklemmung auftreten kann.
7
Stallings S263.

100
Schlichter, TU München 3.6. VERKLEMMUNGEN

1. Die gemeinsam benutzbaren Ressourcen können nicht parallel genutzt werden,


d.h. sie sind nur exklusiv benutzbar.
2. Die zugeteilten/belegten Ressourcen können nicht entzogen werden, d.h. die
Nutzung ist nicht unterbrechbar.
3. Prozesse belegen die schon zugeteilten Ressourcen auch dann, wenn sie auf
die Zuteilung weiterer Ressourcen warten, d.h. wenn sie weitere Ressourcen
anfordern.
4. Es gibt eine zyklische Kette von Prozessen, von denen jeder mindestens eine
Ressource belegt, die der nächste Prozess in der Kette benötigt, d.h. zirkuläre
Wartebedingung.

3.6.2 Belegungs-Anforderungsgraph
Die Zuteilung/Belegung und Anforderung von Ressourcen kann man sich
an einem Graphen, dem Belegungs-Anforderungsgraph, veranschaulichen. Die
Knoten sind die Prozesse und Ressourcen, die Kanten spiegeln Belegungen und
Anforderungen wider.

• Beispiel
Seien P = {P1, ... , Pn} Prozesse und R= {R1, ... , Rm} Ressourcen, z.B. n = 3
und m = 4. Beispiel eines Belegungs/Anforderungsgraphen.

fordert belegt
P1 R1 P3 R4

belegt belegt belegt

fordert
R2 P2 R3
fordert

P1 und P2 warten gegenseitig aufeinander. P1 wartet auf R1, die durch P2 belegt
ist, und P2 wartet auf R2, die durch P1 belegt ist.

3.6.3 Verklemmungs-Ignorierung
In vielen Systemen wird eine ’Vogel-Strauß’-Politik in bezug auf die Deadlock-
problematik verfolgt, d.h. es werden keine Maßnahmen eingesetzt, sondern es

101
Schlichter, TU München 3.6. VERKLEMMUNGEN

wird gehofft, dass alles gut geht. In Unix wird diese Philosophie z.B. bei der
Verwaltung der Prozesstabelle verfolgt. Es ist der manuelle Eingriff des Syste-
madministrators erforderlich. Prozesstabelle ist eher einfach. Sie kann jedoch bei
der Erzeugung neuer Prozesse durch "fork" überlaufen, d.h. es können keine neu-
en Prozesse mehr eingetragen und damit erzeugt werden. Prozesse warten bis sie
einen neuen Prozess erfolgreich erzeugen können. Die Tabelle ist jedoch groß ge-
nug, so dass dieser Fall sehr selten eintritt. Meist tritt er nur bei einem fehlerhaft
programmierten Programm, z.B. unendliche while Schleife, die bei jedem Durch-
lauf ein fork absetzt.

3.6.4 Verklemmungs-Erkennung
In der Praxis häufig angewendete Strategie: Verklemmungen in Kauf nehmen,
sie erkennen und beseitigen. Man versucht eine Verklemmung festzustellen
und sie, sollte sie eingetreten sein, zu beseitigen. Indiz für Verklemmungen,
z.B. angeforderte Ressource ist nach einer gewissen Zeit immer noch nicht
zugewiesen.

• Erkennungs-Algorithmus
Ansatz 1: Suche nach Zyklen im Belegungs/Anforderungsgraph.
Ansatz 2: Prüfen, ob es eine Reihenfolge für die Ausführung der Prozesse gibt,
so dass alle Prozesse terminieren können.
• Vorgehen für Ansatz 2

1. Starte mit Prozessmenge P, die alle Prozesse enthält,


2. suche Prozess p aus P, dessen zusätzliche Anforderungen im aktuellen
Zustand erfüllbar sind, (Problem ist: woher kennt man den zusätzlichen
Ressourcenbedarf)
3. falls gefunden, simuliere, dass p seine belegten Ressourcen wieder freigibt,
4. entferne p aus P und gehe zu 2
5. falls kein Prozess mehr in P, dann terminiert Suche: keine Verklemmung,
6. falls P 6= Ø und in Schritt 2 kein Prozess mehr gefunden wird, dessen
Anforderungen erfüllbar sind, dann terminiert die Suche; P enthält die Menge
der verklemmten Prozesse.

• Auflösung einer Verklemmung in der Regel durch Abbruch einzelner


Prozesse. Dies erfordert in der Regel einen manuellen Eingriff bei der
Auswahl der abzubrechenden Prozesse. Problem: Prozesse müssen erneut

102
Schlichter, TU München 3.6. VERKLEMMUNGEN

ausgeführt werden, bei Nicht-Determinismus ggf. anderes Verhalten der neuen


Prozessabläufe. Ein temporäres Entziehen der Ressourcen eines der beteiligten
Prozesse ist in der Regel sehr schwierig.

3.6.5 Verklemmungs-Verhinderung
Die Verhinderungssverfahren beruhen darauf, dass man durch die Festlegung von
Regeln dafür sorgt, dass mindestens eine der für das Auftreten von Deadlocks
notwendigen Bedingungen nicht erfüllt ist. Aber: solche Regeln lassen sich nicht
für jedes Verklemmungsproblem finden. Deshalb wird meist ein allgemeinerer
Algorithmus gesucht: Vermeidungs-Algorithmus.

• Festgelegte lineare Reihenfolge


Bedingung "Zyklus tritt auf" in Belegungs-/ Anforderungsgraph darf nicht
erfüllt werden. Dazu wird eine lineare Ordnung über den Ressourcen definiert:
R1 < R2 < ... Rm.
Die Prozesse dürfen dann Ressourcen nur gemäß dieser Ordnung anfordern,

d.h. ein Prozess, der Ressource Ri belegt, darf nur Ressourcen Rj anfordern,
für die gilt: Rj > Ri.
Problem: wie Ordnung festlegen? Daumenregel: wichtige Ressourcen, die
gut ausgelastet genutzt werden sollten, dürfen nicht zulange einem Prozess
zugeordnet werden. Deshalb sollte für eine solche Ressource Rj gelten: Rj >
Ri, für unwichtigere Ri. Ein Problem sind jedoch interaktive Prozesse, da die
Ressourcen nicht von vorneherein feststehen, sondern sie sich erst im Laufe der
Interaktion mit dem Nutzer ergeben.

• Andere Möglichkeiten sind:


a) Zuteilung aller benötigten Ressourcen zu einem Zeitpunkt.
b) zwangsweiser Entzug aller belegter Ressourcen, falls eine Ressourcen-
Anforderung nicht erfüllt werden kann. Gerade durch die Virtualisierung
und die Bereitstellung logischer Geräte konnte dieser Ansatz verfolgt
werden. Durch die eingeführte Indirektionsstufe ist es möglich, einem
Prozess ohne dessen Wissen physische Ressourcen in kritischen Situationen
zu entziehen und damit eine der 4 notwendigen Bedingungen für das
Entstehen einer Verklemmung außer Kraft zu setzen.

103
Schlichter, TU München 3.6. VERKLEMMUNGEN

c) Spooling: nur der Spooler Prozess hat als einziger die Ressource
zugeteilt; Zugriffe anderer Prozesse gehen über diesen Prozess. Beispiel ist
das Spooling von Druckaufträgen. Die Ressource ist exklusiv dem Spooler
Prozess zugeordnet., d.h. die Ressource wird nicht mehr gemeinsam
benutzt. Der Spooler Prozess verwaltet eine Auftragswarteschlange für
Aufträge von Prozessen.

3.6.6 Verklemmungs-Vermeidung
Die Vermeidungsverfahren basieren auf der Idee,
die zukünftigen Betriebsmittelanforderungen von Prozessen zu analysieren
(bzw. diese geeignet abzuschätzen) und
solche Zustände zu verbieten (sie also zu verhindern), die zu Verklemmungen
führen könnten.
Die Verklemmungs-Vermeidung unterscheidet sich von der Verklemmungs-
Verhinderung dadurch, dass sie erst während des Betriebs und nicht schon bei
der Softwareentwicklung greift.
Ein Beispiel ist der Bankiers-Algorithmus, der 1965 von Dijkstra entwickelt
wurde.

Veranschaulichung des Algorithmus

Veranschaulichung des Verfahrens anhand eines Bankenszenarios.

• Ausgangspunkt
Idee: Verwaltung von nur einer Ressourcen-Klasse, nämlich den Bankkrediten.

– Bankier besitzt festen Geldbetrag und verleiht Geld an seine Kunden.


– Alle Kunden sind dem Bankier bekannt, jeder Kunde hat einen eigenen
maximalen Kreditrahmen, der kleiner als die zur Verfügung stehende
Geldmenge des Bankiers ist.
– Bankier hat weniger Geld als die Summe dieser Kreditrahmen.
– Kunden können jederzeit Geld in der Höhe ihres jeweiligen Kreditrahmens
fordern, müssen aber ggf. in Kauf nehmen, dass der Bankier diese Forderung
erst nach endlicher Zeit erfüllt.

• Aufgabe des Bankiers

104
Schlichter, TU München 3.6. VERKLEMMUNGEN

Verleihen des Geldes so, dass jeder Kunde seine Geschäfte in endlicher
Zeit durchführen kann und Kunden möglichst parallel bedient werden. Die
sequentielle Abfolge ist natürlich eine triviale Lösung.

Idee: Reihenfolge für Kreditvergabe finden, so dass selbst bei denkbar un-
günstigsten Kreditforderungen die Durchführung aller Geschäfte sicherge-
stellt ist.

ungünstigster Fall: alle Kunden fordern Geld bis zu ihrem jeweiligen max.
Kreditrahmen, ohne Kredite zurückzuzahlen.
• Grobes Vorgehen
1. falls ein Kunde (Prozess) eine Anforderung hat, die aktuell erfüllbar ist,
so teilt man das Geld (die Ressource) probeweise zu und
2. untersucht für den sich damit ergebenden Zustand, ob jetzt eine
Verklemmung vorliegt, indem
3. für alle anderen Kunden von deren ungünstigsten Anforderungen
ausgegangen wird und
4. ein Erkennungs-Algorithmus ausgeführt wird.
Falls keine Verklemmung auftritt, kann die Zuteilung tatsächlich erfolgen,
anderenfalls könnte bei einer Zuteilung ein Deadlock auftreten (muss aber
nicht), weshalb die Anforderung nicht erfüllt wird.
• Beispiel
Ausgangspunkt ist die folgende Situation der vier Kunden A, B, C, D (Einheiten
jeweils in Tausend Euro):
Kunde aktueller Kredit max. Kreditrahmen
A 1 6
B 1 5
C 1 4
D 4 7
Es seien noch 3 Einheiten (Tausend Euro) in der Bank als Kredit verfügbar.

– Annahme: Kunde C fordere eine weitere Einheit als Kredit an. Diese
Anforderung wird probeweise zugeteilt und mündet nicht in einem Deadlock,
da zuerst C (max noch 2 Einheiten bis Kreditrahmen) bedient werden kann.
Wenn C seine Einheiten wieder zurückgezahlt hat, können B oder D und
schließlich A bedient werden.
Probleme bei Vermeidungsverfahren: zukünftige maximale Anforderungen
müssen bekannt sein; anderenfalls nur worst-case Abschätzungen möglich.

105
Schlichter, TU München 3.6. VERKLEMMUNGEN

Algorithmus ist sehr zeit- und speicherplatzaufwendig. Der Habermann-


Algorithmus ist eine Erweiterung des Verfahrens auf verschiedene Ressour-
cen.

3.6.7 Vergleich der Ansätze

Ansatz Verfahren Vorteile Nachteile


Erkennung periodischer Prozesserzeugung Verlust durch Ab-
Aufruf des wird nicht verzö- bruch
Erkennungs gert; erleichtert
Algorithmus interaktive Reak-
tion
Verhinderung feste Reihefolge keine Verklem- keine inkremen-
bei der Zuteilung mungsanalyse tellen Anfragen
zur Laufzeit für Ressourcen
notwendig; Über- möglich
prüfung während
Übersetzung
Zuteilung aller keine Präemp- ineffizient;
Ressourcen auf tion (Entzug) verzögert Pro-
einmal von Ressourcen zesserzeugung;
notwendig; gut Bedarf für Res-
für Prozesse mit sourcen muss
einzelner Aktivi- bekannt sein
tätsphase (single
burst)
Vermeidung Bankiers- keine Präemp- zukünftiger
Algorithmus tion (Entzug) Bedarf muss
von Ressourcen bekannt sein;
notwendig Prozesse können
längere Zeit
blockiert werden

106
Kapitel 4

Prozess- und Prozessorverwaltung

Ein Prozess ist der Ablauf eines Programms in einem Rechensystem. Dieser
Ablauf ist eine Verwaltungseinheit im jeweiligen Betriebssystem. Der Prozess
ist ein Grundbaustein einer Parallelverarbeitung unter einem Betriebssystem, d.h.
sie laufen im Prinzip parallel ab. Falls nur eine CPU vorhanden ist, erfolgt die
Bearbeitung quasiparallel, d.h. in einem zeitlichen Wechsel.

4.1 Fragestellungen
Dieser Abschnitt gibt eine kurze Einführung in eine der wichtigen Verwaltungs-
aufgaben eines Betriebssystems:

• Verwaltung von Prozessen.


• Verwaltung des Prozessors, d.h. Zuteilung der CPU an rechenbereite Prozesse
(Scheduling). Festlegung, welche Anwendung darf wann rechnen?
• Unterbrechungskonzept. Bei Eintreten von bestimmten Ereignissen kann die
Ausführung von Benutzerprogrammen unterbrochen werden, z.B. Warten auf
Eingabe. Dies ermöglicht den Mehrprogrammbetrieb, und damit eine bessere
Ausnutzung und Auslastung aller Geräte eines Rechensystems.

4.2 Prozessverwaltung
Dieser Abschnitt behandelt das Prozesskonzept, Datenstrukturen zur Beschrei-
bung des aktuellen Prozesszustandes sowie Dienste zum Aufruf von Systemfunk-
tionen.

107
Schlichter, TU München 4.2. PROZESSVERWALTUNG

Prozesse repräsentieren eine Aktivität; sie haben ein Programm, Eingaben,


Ausgaben und einen Zustand.

4.2.1 Prozesskonzept
Wir unterscheiden Benutzerprozesse, die Anwendungsprogrammen in Ausfüh-
rung entsprechen, und Systemprozesse, die Programme/Dienste des Betriebssy-
stems durchführen.
a) Jeder Prozess besitzt einen eigenen Prozessadressraum.
b) Spezielle Systemprozesse sind die Dämonen (engl. daemon); das sind
Hilfsprozesse, die ständig existieren, die meiste Zeit aber passiv sind. Sie
erfüllen i. d. R. Service-Funktionen und werden dazu durch das Eintreten
von Ereignissen aufgeweckt (z.B. Datei zum Drucken eingetroffen) oder
werden von Zeit zu Zeit aktiv, um selber zu prüfen, ob Dienste zu
erbringen sind.

Dienste der Prozessverwaltung

Die Prozesse werden durch das Betriebssystem verwaltet.

• Auslösende Ereignisse für die Erzeugung eines Prozesses


Initialisierung des Systems. Beim Booten des Betriebssystems werden eine
Reihe von Prozessen gestartet, z.B. Prozesse, die als Dämon im Hintergrund
laufen (Print-Spooler, HTTP-Serverprozess).
Systemaufruf zum Erzeugen eines Prozesses durch einen anderen Prozess.
Benutzeranforderung zum Starten eines neuen Prozesses (Start einer
Applikation).
Auslösung eines Stapelauftrags (Batch Job).
• Formen der Terminierung von Prozessen
Normale Beendigung (freiwillig).
Vorzeitige Beendigung bei einem durch den Prozess selbst erkannten Fehler
(freiwillig).
Vorzeitige Beendigung bei einem katastrophalen Fehler, erkannt durch das
BS (unfreiwillig). Ein Beispiel ist ein Zugriff auf einen Nullpointer, der
nicht durch ein Exception-Handling abgefangen wird.
Terminierung durch einen anderen Prozess (unfreiwillig). Ein Beispiel ist
die Beendigung über den Task Manager oder die Ausführung der kill-
Funktion.

108
Schlichter, TU München 4.2. PROZESSVERWALTUNG

• Prozess-Auswahl, Strategien zur Prozessorzuteilung: Scheduling. Der Schedu-


ler ist für Multitasking-Betriebssysteme von Bedeutung. Er wählt den nächsten
auszuführenden Prozess aus der Menge der rechenbereiten Prozesse aus. Dabei
werden in den Betriebssystemen unterschiedliche Verfahren angewandt, z.B.
Auswahl nach Prioritäten oder Zeitscheibenverfahren (Round Robin).

• Prozessor-Anbindung; Dispatching. Die Durchführung des Übergangs eines


Prozesses in den Zustand rechnend erfolgt durch den Dispatcher. Beispielswei-
se teilt er den vom Scheduler ausgewählten Prozess der CPU zu. Der Prozess
geht vom Zustand rechenbereit in den Zustand rechnend über; der Prozess wird
ausgeführt. Dabei muss sichergestellt, dass der entsprechende Kontext des Pro-
zesses (z.B. seine Register) geladen werden.

Prozesskontrollblock

Jeder Prozess muss als eine Verwaltungseinheit beschrieben sein. Ein Prozess
wird durch seinen Prozess-Kontext und dieser durch den Prozesskontrollblock
(PCB) beschrieben. Ein PCB wird meist programmiersprachlich als Verbund
(struct) spezifiziert. Ein PCB (process control block) enthält i.d.R. folgende
Informationen:

• eindeutiger Name, z.B. fortlaufende Nummerierung des Prozesses (z.B. pid in


Unix)

• Name des Benutzers, dem der Prozess zugeordnet ist

• der momentane Prozesszustand (wartend, rechnend, rechenwillig, ...)

• falls der Prozess rechnend ist, Angabe der zugeordneten CPU

• falls der Prozess wartend ist, eine Spezifikation des Ereignisses, auf das der
Prozess wartet (z.B. Adresse eines Semaphors).

• die Ablaufpriorität des Prozesses

• die Inhalte der programmierbaren Register (die Anzahl ist abhängig von der
jeweiligen CPU-Architektur), z.B. Kellerpointer.

• die Inhalte der Register, in denen die Anfangsadresse und Länge der pro-
zessspezifischen Speicherabbildungstabellen enthalten sind (virtuelle Adressie-
rung).

109
Schlichter, TU München 4.2. PROZESSVERWALTUNG

• das Programmstatuswort (PSW).Beispiele für dem Inhalt des PWS’s sind der
Ablaufmodus (Benutzer- oder Systemmodus), die momentane Ablaufpriorität,
die Adressierungsart im Benutzermodus (virtuelle oder direkte Adressierung)
und die Ergebnisse der letzten Vergleichsoperation auf Maschinenebene
(sogenannte Condition-Code Register, z.B. das N-Register (Ergebnis der letzten
Operation negativ).

• PCB unter Linux ist durch die Struktur task_struct spezifiert; definiert unter
include/linux/sched.h
1
. Dies ist eine umfangreiche Struktur, die Information zum Scheduling (z.B.
Zustand und Priorität), Prozess-ID, Vaterprozess, Kinder enthält. Daneben wer-
den Informationen Benutzer-/Gruppeninformationen und Ressourceninforma-
tionen (Locks, threads, etc) gespeichert.

Daneben kann ein PCB noch weitere Statistiken über die Historie des Prozesses
speichern, die beim Scheduling ausgewertet werden.

Prozesslisten

Die Prozesse werden in Zustandslisten verwaltet, die als verkettete Liste der PCBs
realisiert sind.
für E/A-Geräte (z.B. Platte, Terminal) existiert i.d.R. jeweils eine eigene
Warteschlange, die die PCBs der wartenden Prozesse enthält.
Falls mehrere CPUs vorhanden sind, verweist "rechnend" auf mehrere Elemente.

Prozessidentifikation
Rechnend
Registerzustand

Scheduling Information (z.B.


Priorität)
Rechenwillig
Adressrauminformation
Ready-Queue
Sonstiges

Wartend nächster PCB

Prozesskontrollblock PCB

Da der PCB eine Datenstruktur des Betriebssystems ist, kann die Ablage nicht im
Benutzeradressraum erfolgen. Da weiterhin die Prozesse nicht kellerartig aktiviert
1
Achilles S 21

110
Schlichter, TU München 4.2. PROZESSVERWALTUNG

und deaktiviert werden, sondern in beliebiger Folge, kann er auch nicht im Keller
des Betriebssystems abgelegt werden, sondern es wird dafür die Halde verwendet.

Zustandsmodell

Das Prozess-Zustandsmodell unterscheidet neben den bereits vorgestellten


Zuständen rechenwillig, rechnend, wartend auch den Zustand ausgelagert.
Letzterer Zustand tritt ein, wenn der Adressraum aufgrund Speichermangels aus
dem Arbeitsspeicher auf den Hintergrundspeicher verlagert wird ("swapping").
Beispielsweise verwaltet Windows auf der Festplatte eine Swap-Datei, in die
Prozesse ausgelagert werden.

resign

add retire
rechenwillig assign rechnend

block
ready

wartend

swap out
swap in
ausgelagert

Zustandsübergänge sind:
add: ein neu erzeugter Prozess wird zu der Menge der rechenwilligen Prozesse
hinzugefügt;
assign: als Folge eines Kontextwechsels wird dem Prozess die CPU zugeordnet;
block: aufgrund eines EA-Aufrufs oder einer Synchronisationsoperation wird der
Prozess wartend gesetzt;
ready: nach Beendigung der angestoßenen Operation wechselt der Prozess in den
Zustand rechenwillig; er bewirbt sich erneut um die CPU;
resign: dem rechnenden Prozess wird die CPU entzogen; er bewirbt sich
anschließend erneut um die CPU;
retire: der aktuell rechnende Prozess terminiert;
swap out: der Prozess wird auf die Festplatte ausgelagert;

111
Schlichter, TU München 4.2. PROZESSVERWALTUNG

swap in: der Prozess wird von der Festplatte in den Arbeitsspeicher geladen.

Prozesserzeugung

Ein Prozess kann andere Prozesse erschaffen. Diese sind die Kindprozesse (child
process) und der Erschaffer ist der Vater (parent process). Vater
kann auf Beendigung von Kind warten, oder
parallel weiterlaufen.

• Prozesserzeugung: 2 Vorgehensweisen
Windows NT: Vaterprozess veranlasst eine Reihe von Systemaufrufen, die
das Kind entstehen lassen.
Unix: Vater klont sich mit Systemaufruf fork(); Kind ändert selbst sein
Aufgabe.
• Unix Prozesserzeugung
Aufruf von fork() führt zu einem fast exakten Duplikat des Vaterprozesses.
Unterschiede sind
unterschiedlicher process identifier (PID)
der Ergebniswert von fork()
Vater: PID des Kindprozesses
Kind: 0
Mit Hilfe der PID kann der Vaterprozess den Kindprozess adressieren, z.B. um
ihn zu beenden.

– Beispielprogramm
#include <stdio.h>
int main(int argc, char *argv[]) {
char *myname = argv[1];
int cpid = fork();
if cpid == 0 {
printf("The child of %s is %d\n", myname, getpid());
.......
return (0);
} else {
printf("My child is %d\n", cpid);
/* wird vom Vaterprozess durchlaufen */
.....
return(0);
}
}

112
Schlichter, TU München 4.2. PROZESSVERWALTUNG

– Kind hat vieles mit dem Vater gemeinsam:


liest dieselben Dateien, gleicher Benutzername, benutzt dieselben Daten
– Unix Kind fängt mit dem Code des Vaters an und ändert sich dann
Systemaufruf exec(): ersetzt das Programmbild des Vaters mit einem
anderen.
Nach exec() beginnt die Ausführung am Anfang bei main(). NT hingegen
beginnt immer am Anfang
Beispielprogramm für exec
#include <stdio.h>
int main(int argc, char *argv[]) {
char *myname = argv[1];
int cpid = fork();
if cpid == 0 {
int rc;
rc = execl("/bin/ls", "ls", "-l", (char *) 0);
printf("Fehler bei execl Aufruf: %d\n", rc);
exit(1);
} else {
/* wird vom Vaterprozess durchlaufen */
}
}
Die Familie der exec-Systemaufrufe laden ein neues Programm in den
Adressraum und führen dies aus. Damit is auch der vorherige Programmcode
verschwunden. Dies bedeutet, dass nach einer erfolgreichen Ausführung
von execl die nachfolgenden Anweisungen printf und exit nicht mehr
vorhanden sind. Sie werden nur ausgeführt, falls execl fehlschlägt. Bei execl
werden die Parameter als Strings übergeben mit
das auszuführende Programm
der Name des Programms
die an das Programm zu übergebende Parameter
(char *) 0) markiert das Ende.
exit(1) meldet einen Fehler; exit(0) bedeutet Rückkehr ohne Fehler.
– Prinzipablauf
Mit der Systemfunktion wait wartet der Vaterprozess auf den Kindprozess.
wait vor Beendigung des Kindes: Vater ist blockiert.
wait nach Beendigung des Kindes: Kind wird nach Beendigung zum
Zombieprozess.
Nach Beendigung des Kindes erhält der Vaterprozess Information über den
Beendigungsstatus (normal, Abbruch) und den Rückgabewert der Funktion
exit des Kindes (nur bei normaler Beendigung, ansonsten undefiniert).

113
Schlichter, TU München 4.2. PROZESSVERWALTUNG

Falls der Kindprozess vor dem wait des Vaters beendet wird, entsteht ein
"Zombieprozess".
Ein Zombieprozess führt keinen Code mehr aus. Er belegt nur noch
Tabelleneinträge im BS, da der Rückgabewert und der Beendigungsstatus
für den Elternprozess bereitgehalten werden müssen.

Kind
exit
Vater
Vater Vater
fork
wait

Kind exit
Zombieprozess
Vater
Vater Vater
fork wait

Der Aufruf von wait des Vaterprozesses ist norwendig, da sonst dauerhafte
Zombieprozesse entstehen können. Terminiert der Vaterprozess vor dem
Kindprozess, verwaist er und wird als Kind dem init-Systemprozess
zugeordnet; dieser führt zu gegebener Zeit ein wait für alle Kinderprozesse
aus.

• Linux unterstützt den Systemaufruf clone() zur Erzeugung neuer Thread-


Kopien. Im Aufruf werden eine Menge von Flags spezifiziert, z.B.
CLONE_FS: Dateisysteminformation gemeinsam mit Aufrufer, z.B. aktu-
elles Arbeitsverzeichnis.
CLONE_VM: gemeinsamer Arbeitsspeicher.
CLONE_FILES: die offenen Dateien sind gemeinsam.

Prozesse und Vererbung

Bei der Verwaltung von Vater-/Kindprozess sind eine Reihe von Entscheidungen
zu treffen:

• Ausführung
Vaterprozess und Kind werden gleichzeitig ausgeführt, oder
der Vaterprozess wartet darauf, dass das Kind beendet wird

114
Schlichter, TU München 4.2. PROZESSVERWALTUNG

• Ressourcen
Vater und Kind teilen sich alle Ressourcen.
Vater und Kind teilen sich einen Teil der Ressourcen.
Vater und Kind haben keine Ressourcen gemeinsam.

• Adressraum
Das Kind ist ein Duplikat des Vaters.
Das Kind führt durch automatisches Laden ein neues Programm aus (exec-
Systemaufruf).
• Threads
Das Kind dupliziert alle Threads des Vaters.
Das Kind dupliziert nur den Thread des Vaters, der die fork-Operation
ausgelöst hat. Falls nach der fork-Operation der exec-Systemaufruf
ausgeführt wird, wird sowieso der komplette Prozess ersetzt.

4.2.2 Dispatcher
Aufgabe des Dispatchers: Realisieren der Zustandsübergänge zwischen rechnend
und rechenwillig: Prozessor binden und entbinden. Dazu ist ein Kontextwechsel
erforderlich. Dabei ist zu berücksichtigen, dass die Prozesslisten entsprechend
aktualisiert werden, d.h. der PCB des ausgewählten Prozess muss aus der
rechenwillig-Liste entfernt werden und in die rechnend-Liste eingetragen werden.

Kontextwechsel

CPU wird entzogen und einer anderen Aktivität zugeteilt; ein Kontextwechsel ist
erforderlich, falls der rechnende Prozess P1 in den Zustand wartend oder z.B.
durch Prozessorentzug in den Zustand rechenwillig übergeführt wird.

• Problem
aktueller Ausführungskontext des Prozesses muss gesichert werden und
Kontext des nächsten rechenbereiten Prozesses muss geladen werden. Falls für
den Zugriff auf eine Datei X nur ein Dateizeiger zur Verfügung steht, dann
muss die Position des Dateizeigers gerettet werden. Wenn Prozess P1 wieder
rechnend wird, dann soll er an der Position weiterlesen, an der er unterbrochen
wurde; falls zwischenzeitlich ein anderer Prozess P2 ebenfalls die Datei gelesen

115
Schlichter, TU München 4.2. PROZESSVERWALTUNG

und den Dateizeiger verändert hat, darf dies bei der Fortsetzung von P1 keine
Auswirkung haben. In Unix erhält jeder Prozess einen eigenen Dateizeiger.

Achtung: je umfangreicher ein PCB ist, desto "teurer" sind Prozesswechsel,


d.h. das Umschalten der CPU zwischen den Prozessen.

Threads

Threads haben einen sehr viel kleineren Kontext ⇒ Umschalten zwischen


Threads innerhalb eines Prozesses sehr schnell, da Adressraum und andere
Ressourcen (z.B. Dateien) gemeinsam genutzt werden. Auch TLB-Einträge
(→ Translation lookaside Buffer (siehe Seite 165)) der Seitenadressierung
müssen nicht invalidiert werden. Damit ergeben sich auch keine Folgekosten
durch Laden von Seiten bei cache-Misses. Dagegen ist das Umschalten von
Threads, die unterschiedlichen Prozessen angehören, ebenso aufwendig wie ein
Prozesswechsel.

Beispiel: Kontext-Wechsel in Unix

Kontextwechsel z.B. durch den Aufruf der Systemoperation sleep durch einen
Prozess. Beim Aufruf der Operation sleep ist ein Warteraum, in den der
Prozess eingefügt werden soll, anzugeben (z.B. E/A-Warteraum, oder warten
auf Terminieren eines Kind-Prozesses). Bei der Ausführung von sleep werden
vergröbert folgende Schritte durchgeführt.
1. Maskieren von Interrupts; Ausblenden von Unterbrechungen, da der
Kontextwechsel nicht gestört werden soll.
2. Lokalisieren der benötigten Warteschlange;
3. Neuberechnung der Priorität des Prozesses;
4. Einfügen des Prozesses in die Warteschlange;
5. Aufruf der Operation zum Kontextwechsel.
Bei der Ausführung der Operation zum Kontextwechsel wird vom Scheduler der
nächste Prozess ausgesucht, dem der Prozessor zugeteilt werden soll, und mit
dieser Information wird die Operation resume aufgerufen.
Zunächst wird der Zustand des noch aktuellen Prozesses aus den Registern in
den Prozesskontrollblock des Prozesses gespeichert.
Dann wird die Adresse des Prozesskontrollblocks des neu zu bindenden
Prozesses sowie der Zustand des neuen Prozesskontrollblocks in die Register
geladen und der Kontextwechsel ist durchgeführt.

116
Schlichter, TU München 4.2. PROZESSVERWALTUNG

Durch das Maskieren von Interrupts kann das Warten auf die relevanten
Ereignisse eingestellt werden, d.h. die anderen Interrupts werden ausgeblendet;
der Kontextwechsel soll nicht gestört werden.

4.2.3 Arbeitsmodi
Ziel für den Betrieb von Rechensystemen: kontrollierter Zugriff auf Hardware-
komponenten nur durch BS. Dadurch soll verhindert werden, dass Benutzer oder
Softwaresysteme Hardwarekomponenten unsachgemäß nutzen, und implizit an-
dere nebenläufige Aktivitäten schädigen.
Lösung: alle Zugriffe auf Hardware nur über privilegierte Befehle zulässig;
Frage: wer darf privilegierte Befehle ausführen ⇒ Antwort: Prozesse in einem
privilegierten Modus.
Herkömmlich unterscheidet man zwischen dem Benutzer- (engl. user mode) und
dem Systemmodus (engl. kernel mode).

• Benutzermodus
Es sind nur die nicht privilegierten Befehle verfügbar. Damit ist der Zugriff auf
Prozessadressraum und unkritische Register, wie Befehlszähler, Indexregister
möglich. Benutzerprozesse werden im Benutzermodus ausgeführt. Kritische
Register, über die der Kontext eines Prozesses beeinflusst werden kann
(z.B. Ablaufpriorität, Arbeitsmodus) können nur im Systemmodus verändert
werden. Wird versucht, einen privilegierten Befehl auszuführen, gibt es einen
Befehlsalarm.

• Systemmodus
Es sind auch die privilegierten Befehle verfügbar (z.B. Anhalten der Maschine,
Verändern der Ablaufpriorität). Die Dienste des Betriebssystemkerns werden
im Systemmodus ausgeführt.

• Nutzung der Hardware-Komponenten nur über Dienste des BS: Aufruf eines
BS-Dienstes über spezielle Befehle: den Systemaufruf. Dies führt zu einer →
Unterbrechung (siehe Seite 134) und damit zu einem kontrollierten Eingang in
das BS (z.B. Zugriffsrechte des aufrufenden Prozesses prüfen).

4.2.4 Systemaufrufe
Ein Systemaufruf ist eine Funktion, die von einem Benutzerprozess aufgerufen
wird, um einen BS-Kerndienst aufzuführen.

117
Schlichter, TU München 4.2. PROZESSVERWALTUNG

1. Der Systemaufruf überprüft die übergebenen Parameter und bildet daraus


eine Datenstruktur, um die Daten an den BS-Kern weiterzureichen.
2. Danach wird eine spezielle Instruktion, ein Software Interrupt (Trap), aus-
geführt. Diese Instruktion identifiziert über einen Operanden den gewünsch-
ten Systemdienst.
3. Bei Ausführung der Trap-Instruktion wird der Zustand des Benutzerprozes-
ses gerettet und es findet ein Wechsel in den Systemmodus statt.
In manchen Programmiersprachen sind Systemaufrufe (C, C++) über den
Aufruf von Prozeduren der Laufzeitumgebung, die ihrerseits die Systemaufrufe
durchführen, möglich. In Java ist kein direkter Systemaufruf möglich, sondern
dies erfolgt i.a. über Methoden, die in anderen Sprachen geschrieben sind, meist
C, C++.

• Beispiel
Lesen von Daten aus einer Datei und Kopieren in eine andere Datei. Dabei
treten die folgenden Systemaufrufe auf:
(1)
Schreiben des Prompts auf Bildschirm: Angabe der Dateinamen
(2)
Lesen der Tastatureingabe (bzw. Analoges bei Mouse-Eingabe)
(3)
Öffnen der zu lesenden Datei (open)
(4)
Erzeugen der neuen Datei
(5)
ggf. Fehlerbehandlung: Nachricht auf Bildschirm
(6)
Schleife: Lesen von Eingabedatei (ein Systemaufruf) und schreiben in
zweite Datei (auch Systemaufruf)
(7) Schließen beider Dateien
(8) Ausgabe auf Bildschirm
Jeder Schritt ist jeweils ein Systemaufruf. Durch die Verwendung von
Laufzeitroutinen ergibt sich eine höhere Abstraktionsebene ⇒ Aufruf einer
Routine, die die notwendigen Systemaufrufe durchführt.

4.2.5 Realisierung von Threads


Es existieren zwei grundlegende Ansätze, Threads in einem Rechensystem
zu realisieren: im Benutzer-Adressraum (Benutzermodus) oder im System-
Adressraum (Systemmodus).

• im Benutzer-Adressraum
Der BS-Kern verwaltet nur single-threaded Prozesse. Damit ist es auch möglich
ein Thread-Package für ein Betriebssystem zu realisieren, das auf BS-Ebene
keine Threads unterstützt.

118
Schlichter, TU München 4.2. PROZESSVERWALTUNG

Prozess Thread

Benutzer
Adressraum
(Benutzermodus)

System
BS-Kern Adressraum
(Systemmodus)

Laufzeit- Thread Prozess-


system tabelle tabelle

– Threads werden durch Laufzeitsystem im Benutzeradressraum verwaltet.


Eine Thread-Tabelle speichert Informationen (Register, Zustand, etc.) über
Threads pro Prozess.
– Prozessorzuteilung im BS-Kern erfolgt an Prozesse. Laufzeitsystem be-
stimmt, welcher Thread rechnend gesetzt wird. Jedes Laufzeitsystem hat sei-
nen eigenen Thread-Scheduler. Damit ist es möglich, dass jeder Prozess sei-
ne eigene Variante des Scheduling-Algorithmus nutzt, d.h. die Auswahl des
nächsten auszuführenden Threads. Beispielsweise kann durch eine geeignete
Strategie verhindert werden, dass der Garbage Collector zu einem ungünsti-
gen Zeitpunkt unterbrochen wird.
– Problem: Systemaufruf eines Threads blockiert die anderen Threads
des Prozesses. Dadurch wird gerade dies verhindert, was mit Threads
in Applikationen erreicht werden soll, d.h. die Ausführung paralleler
Aktivitätssequenzen, wobei trotz Blockierung einiger Threads andere
Threads desselben Prozesses weiterlaufen können.
– Problem: wie wird einem Thread die CPU entzogen? Threads müssen die
CPU durch Ausführung des Befehls thread_yield freiwillig aufgeben. Das
Laufzeitsystem wählt dann einen anderen rechenwilligen Thread aus. Falls
ein Thread die CPU nicht aufgibt, kann ihm vom Laufzeitsystem nicht (wie
im BS-Kern) die CPU entzogen werden. Innerhalb eines Prozesses existieren
keine Clock-Interrupts.

• im System-Adressraum
Neben den Prozessen werden im BS-Kern auch alle Threads verwaltet. Damit
können auch alle Funktionen zur Verwaltung von Prozessen, z.B. CPU-

119
Schlichter, TU München 4.2. PROZESSVERWALTUNG

Zuteilung, für Threads verwendet werden. Dies bedeutet jedoch auch, dass bei
Erzeugung bzw. Terminierung von Threads jeweils Systemaufrufe durchgeführt
werden müssen. Systemaufrufe sind jedoch i.a. aufwendig.

Prozess Thread

Benutzer
Adressraum
(Benutzermodus)

System
BS-Kern Adressraum
(Systemmodus)

Thread Prozess-
tabelle tabelle

– Thread-Tabelle speichert Informationen (Register, Zustand, etc.) über


Threads.
– Prozessorzuteilung im BS-Kern erfolgt an Threads. Falls ein Thread
blockiert, kann die Prozessorzuteilung entscheiden, ob ein anderer Thread
aus demselben Prozess die CPU zugeteilt bekommt, oder ein Thread eines
anderen Prozesses.
– Der Systemaufruf eines Threads blockiert nicht die anderen Threads des
Prozesses.

• Es wurden auch hybride Ansätze verfolgt, die eine Kombination beider


Möglichkeiten realisieren. Der BS-Kern verwaltet sogenannte Kernel-Threads.
Das Betriebssystem kennt nur Kernel-Threads und teilt diese der CPU zur
Ausführung zu. Threads des Benutzer-Adressraums (User-Threads) werden
jeweils auf Kernel-Threads abgebildet, dabei können gleichzeitig mehrere
User-Threads eines Prozesses verfügbaren Kernel-Threads zugeordnet werden.
Auf einen einzelnen Kernel-Thread können gleichzeitig auch mehrere User-
Threads abgebildet werden (Multiplexing).

120
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

Prozess User-Thread

BS-Kern

Kernel
Thread

4.3 Prozessorverwaltung
Eine wesentliche Aufgabe der Prozessorverwaltung besteht darin zu entscheiden,
welcher der um den bzw. die Prozessor(en) konkurrierenden Prozesse (bzw.
Threads) zu einem Zeitpunkt an den bzw. die Prozessor(en) gebunden wird.
Dazu steht die BS-Komponente Scheduler zur Verfügung. Die Durchführung der
→ Zustandsübergangs (siehe Seite 111) eines Prozesses von rechenwillig nach
rechnend ist Aufgabe des Dispatchers, während der Scheduler aus der Liste
der möglichen Prozesse einen geeigneten auswählt. Der Scheduler wählt den
Prozess aus, der durch einen assign-Zustandsübergang nach rechnend übergeht.
In folgenden Situationen 2
muss ein Scheduler auf jeden Fall aktiviert werden:
ein neuer Prozess wird erzeugt;
ein Prozess terminiert;
ein Prozess blockiert aufgrund eines EA-Auftrags;
eine EA-Unterbrechung tritt auf.
Daneben kann das Betriebssystem einem Prozess die CPU entziehen, falls er
bereits zulange rechnend ist (Ablauf der Zeitscheibe).

• Prozessablauf besteht aus einer Sequenz von alternierenden CPU- und E/A-
Perioden. Während der E/A-Perioden wartet der Prozess auf die Beendigung
2
[Tanenbaum2001, S134]

121
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

der Ein-/Ausgabe. Dies Wartezeit kann von anderen rechenwilligen Prozessen


genutzt werden. Ein E/A-orientierter Prozess hat viele kurze CPU-Perioden;
ein CPU-orientierter Prozess hat wenige lange CPU-Perioden.

• Zeitliche Verschränkung der Prozessbearbeitung bei einer CPU.

Zeit
Zuweisung
A hat CPU CPU an A A hat CPU
Prozess A

Unterbrechung
BS-Kern
hat CPU
BS-Kern
BS-Kern
Unterbrechung
hat CPU

B hat CPU
Prozess B
Zuweisung
CPU an B

Unterscheidung zwischen Prozess-Scheduling und Thread-Scheduling. Im


ersten Fall findet die Prozessorzuteilung nur zu ganzen Prozessen statt.
Multithreading findet im Benutzermodus statt. Im 2. Fall sind unterschiedliche
Varianten des Multithreading möglich: auf Benutzerebene oder als Kernel-
Threads. Für beide Arten können dieselben Strategien verwendet werden.

4.3.1 Kriterien
Der Scheduler wählt aus der Menge der rechenwilligen Prozesse den nächsten
auszuführenden Prozess aus. Es existieren unterschiedliche Verfahren die von der
jeweiligen Prozessorverwaltungsstrategie abhängen. Mögliche Leistungskriterien
für ein Schedulingverfahren:

• Fairness. Jeder Prozess soll einen fairen Anteil der CPU zum Rechnen erhalten.

• Effizienz, Prozessorauslastung. Dies ist ein Maß für die Auslastung eines
Prozessors. Ziel sollte es sein, dass möglichst alle Teile der Rechenanlage
effizient genutzt werden, z.B. CPU und EA-Geräte sollten möglichst gut
ausgelastet sein.

122
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

• Antwortzeit für interaktive Benutzer (Dialogverarbeitung). Für interaktive An-


wendungen muss die Zeitspanne zwischen Ankunft, z.B. einer Benutzereingabe
und einer potentiellen Reaktion möglichst kurz sein.
• Wartezeit, insbesondere für Batch-Jobs (Stapelverarbeitung). Darunter ist die
Verweilzeit in der Bereit-Liste zu verstehen, d.h. die Zeitdauer in der einem
rechenwilligen Prozess kein physischer Prozessor zugeordnet ist.
• Ausführungszeit, d.h. Zeitspanne von Auftragsbeginn bis Auftragsende. Die
Ausführungszeit enthält alle Zeiten in Warteschlangen, der Ausführung und der
Ein-/Ausgabe. Sie sollte minimal sein.
• Abschlusszeit, insbesondere für Realzeitsysteme. Hier geht es darum, ob die
Realzeitgarantien eingehalten werden. Wird der Prozess rechtzeitig fertig und
liefert seine Ergebnisse aus (z.B. das Videobild)?
• Durchsatz, Anzahl der Aufträge pro Zeiteinheit. Die Zahl der Aufträge pro
Zeiteinheit ist ein Maß für die Systemauslastung und sollte maximal sein.

Kriterien der Betriebsarten

Die Ziele der Schedulingverfahren hängen von der Umgebung und den
Betriebsarten des Rechensystems ab.

• Alle Systeme
Fairness - jeder Prozess bekommt Rechenzeit der CPU.
Balance - alle Teile des Systems sind ausgelastet.
Policy Enforcement - Scheduling Policy wird nach außen sichtbar
durchgeführt.
• Stapelbetrieb
Durchsatz - maximiere nach Aufträge pro Zeiteinheit.
Ausführungszeit - minimiere die Zeit von Start bis zur Beendigung.
CPU-Belegung - belege CPU konstant mit Aufträgen.
• Dialogbetrieb - interaktive Systeme
Antwortzeit - antworte schnellstmöglich auf Anfragen.
Proportionalität - Erwartungshaltung der Nutzer berücksichtigen. Der
Benutzer erwartet, dass der Aufbau einer Internetverbindung länger dauert
als deren Abbruch. Ein weiteres Beispiel ist die Dateiauswahlbox im
Windows Explorer: die Erstellung der Liste zu den hierarchisch oberen
Verzeichnissen sollte schnell erfolgen (ist jedoch nicht immer so).

123
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

• Echtzeitsysteme
Abschlusszeit - kein Verlust von Daten.
Vorhersagbarkeit - Qualitätsverlust bei Multimedia vermeiden. Schwan-
kungen können durch Pufferung von Informationen (Frames) ausgeglichen
werden, solange die Schwankungen in einem gewissen Rahmen bleiben.

Mit den Leistungskriterien gibt es Probleme: a) die Optimierungsziele sind


teilweise widersprüchlich (z.B. eine Strategie, die den Durchsatz optimiert ist
nicht notwendigerweise geeignet, um kurze Antwortzeiten zu ermöglichen),
und b) das Prozessverhalten (z.B. wann kommt der nächste E/A-Befehl) kann
vom Scheduler nicht exakt vorausgesagt werden. Deshalb werden Scheduling-
Strategien meist abhängig von der Betriebsart gewählt (Dialogbetrieb vs.
Stapelbetrieb).

4.3.2 Scheduling-Strategien
Es werden zwischen zwei Klassen unterschieden: nicht-unterbrechende (nonpre-
emptive) und unterbrechende Strategien (preemptive).

nicht unterbrechend: Scheduling nur dann möglich, wenn der rechnende


Prozess blockiert wird oder wenn er terminiert, d.h. Prozess behält CPU bis
er sie selber abgibt.
Beispiel: Microsoft Windows 3.x; unterbrechende Strategien erst ab
Windows 95

unterbrechend: Unterbrechung beim Eintreten von speziellen Ereignissen,


u.a. Eintreffen eines Prozesses mit höherer Priorität oder Prozess geht in
Wartezustand. Problematisch ist diese Strategie für die Ausführung von
Operationen des BS-Kerns. Lösung bei vielen Betriebssystemen (z.B. Unix):
Ausführung von BS-Kernoperationen sind nicht unterbrechbar (Vorsicht: hier
in bezug auf Scheduling, Interrupts können auftreten).

Zeitscheibenstrategie

Die Zeitscheibenstrategie (Round Robin) ist unterbrechend. Ziel ist die


gleichmäßige Verteilung der Rechenzeit auf rechenwillige Prozesse. Round Robin
ist eine weit verbreitete preemptive Schedulingvariante. Das Verfahren ordnet
jedem rechenwilligen Prozess ein definiertes Zeitquantum (Zeitscheibe) zu. In 4.3
BSD Unix beträgt z.B. die Zeitscheibe 100 ms. Nach dem Kontextwechsel ist

124
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

der Prozess entweder bis zum Ablauf des Zeitquantums oder bis zum Auftreten
einer blockierenden Systemfunktion im Besitz der CPU (je nachdem was zuerst
eintritt). Alle rechenwilligen Prozesse werden in einer FIFO-Warteschlange
verwaltet. Nach Ablauf der Zeitscheibe wird der Prozess am Ende der FIFO-
Warteschlange eingereiht.

• Es werden die Prozesse an den Prozessor jeweils für ein festgelegtes


Zeitquantum q gebunden und spätestens nach dem Ablauf dieser Zeitspanne
wird den Prozessen der Prozessor wieder entzogen.

• zyklisches Bedienen der Prozesse (Round Robin).

• Ready-Queue (Liste der rechenwilligen Prozesse) als zyklische Warteschlange


realisiert.

• Wahl des Zeitquantums:


falls q zu klein: viele unproduktive Kontextwechsel. Es scheint, als ob jeder
Prozess seinen eigenen Prozessor besitzt; processor sharing.
falls q zu groß: Round Robin wird zu einem reinen FCFS Scheduling
(First Come First Served), da die Wahrscheinlichkeit für einen Aufruf
eines blockierenden Systemdienst steigt. Ein zu großes Zeitquantum ist
insbesondere für interaktive Anwendungen nicht empfehlenswert, da sich
die Wartezeit für einen Prozess, und damit die Reaktionszeit erhöht. Bei
großem Qunatum nährt sich das Systemverhalten an FCFS an. Einzelne
Prozesse würden sehr lange rechnen, währendessen die anderen Prozesse
alle warten müssen. Insgesamt erhöht sich die mittlere Wartezeit über
alle Prozesse. Bei einem gut gewählten Quantum hat jeder Prozess einen
fairen Anteil an der CPU und damit einen Rechenfortschritt. Die mittlere
Wartezeit über alle Prozesse ist niedriger.
Typische Werte für q: 10 bis 100 Millisekunden.
• Für q = 100 ms gilt bei 1 MIPS Maschine (Million Instructions/Second): ca.
100.000 Instruktionen/q.

Prioritäten

Diese Strategie ist i.a. unterbrechend. Sie basiert darauf, an die Prozesse Prioritä-
ten zu vergeben. Die Prioritätenvergabe kann dabei statisch oder dynamisch sein.
Die Prioritätenstrategie kann unterbrechend und nicht-unterbrechend sein. Im er-
sten Fall wird der Ablauf eines Prozesses unterbrochen, wenn ein anderer Prozess
mit höherer Priorität rechenwillig wird. Im zweiten Fall behält der Prozess die

125
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

CPU solange bis er entweder eine blockierende Systemfunktion aufruft oder die
CPU freiwillig abgibt.

• Prioritäten sind i.a. ein festgelegter Zahlenbereich, z.B. 0, ..., 7. Achtung:


häufig: niedrige Zahl entspricht hoher Priorität, muss aber nicht so sein.

• Statische Prioritätenvergabe
jeder Prozess besitzt für die Dauer seiner Existenz eine feste Priorität.
Problem: Gefahr des Verhungerns von Prozessen mit niedriger Priorität
Lösung: Erhöhung der Priorität von lange wartenden Prozessen, d.h.
dynamische Prioritäten.
• Dynamische Prioritätenvergabe
die Prioritäten der Prozesse können sich dynamisch verändern, d.h. sie werden
in gewissen Zeitabständen neu berechnet.
Idee: lange Wartezeiten berücksichtigen (Erhöhen die Priorität).
Prozesse mit großem CPU-Verbrauch sinken in Priorität.
E/A-intensive Prozesse steigen in Priorität (damit E/A-Geräte und CPU
parallel genutzt werden).
• Zeitscheibenstrategien und Prioritätenvergabe können zu effizienten Verwal-
tungsstrategien kombiniert werden. Beispielsweise können Prozesse in Priori-
tätsklassen gruppiert werden. Innerhalb einer Gruppe wird die Zeitscheibenstra-
tegie verwendet. Beispielweise können 4 Prioritätsklassen eingerichtet werden,
wobei die Klasse 4 die höchste Priorität hat. Solange Prozesse in der Klasse
4 sind, werden diese jeweils im Zeitscheibenverfahren ausgewählt. Falls die
Klasse 4 leer, werden Prozesse der Klasse 3 ausgewählt usw. Prozesse müssen
dynamisch den Klassen zugeordnet werden, damit nicht Prozesse der untersten
Klasse verhungern.

• Windows XP Scheduling
Windows XP nutzt eine Prioritäten-basierte, unterbrechende Strategie. Thread
mit höchster Priorität wird ausgeführt, bis
er terminiert, oder
er seine Zeitscheibe ausgeschöpft hat, oder
eine Blockierung (Systemaufruf, E/A) auftritt.
Es werden Prioritäten von 0 - 31 unterschieden, die in verschiedene Klassen
eingeteilt werden

126
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

Echtzeit hoch über normal unter idle


normal normal
zeit kri- 31 15 15 15 15 15
tisch
höchste 26 15 12 10 8 6
über 25 14 11 9 7 5
normal
normal 24 13 10 8 6 4
unter 23 12 9 7 5 3
normal
niedrigst 22 11 8 6 4 2
idle 16 1 1 1 1 1
In jeder Prioritätsklasse (Echtzeit, etc) wird by-Default der Wert der Zeile
"normal" gesetzt. Außer der Klasse Echtzeit werden alle Prioritäten dynamisch
angepasst. Falls ein Thread aufgrund eines ausgeschöpften Zeitquantums
unterbrochen wird, wird die Priorität dekrementiert, jedoch nicht unter den
Default-Wert. Die Schedulingstrategie sowie die Prioritätsklassen mit den
zugehörigen Prioritäten gelten auch für Windows 7.

First-Come First-Served

Dieses nicht-unterbrechende Verfahren (FCFS) teilt einen Prozessor in der


Reihenfolge des Auftragseingangs zu. Ready-Queue wird als FIFO-Liste
verwaltet; Verfahren einfach zu realisieren.

• Ein Kontextwechsel findet nur statt, wenn der Prozess eine blockierende
Systemfunktion aufruft oder der Prozess die CPU freiwillig abgibt. Im letzten
Fall wird der Prozess sofort wieder am Ende der Ready-Queue eingereiht. Im
ersten Fall wird der Prozess nach Ende der Blockierungsursache wieder am
Ende der Ready-Queue eingereiht.

• Es kann eine hohe CPU Auslastung erreicht werden.

• Problem: Durchschnittliche Wartezeit ist hoch.


Beispiel: Prozesse P1,P2,P3 kommen nahezu gleichzeitig zum Zeitpunkt 0
an;
Dauer ihrer Berechnungszeiten: P1: 24 ms, P2: 3ms, P3: 3ms;
bei Reihenfolge P1, P2, P3: mittlere Wartezeit: (0 + 24 + 27)/3 = 17 ms
bei Reihenfolge P2, P3, P1 mittlere Wartezeit (0+3+6)/3 = 3 ms

127
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

Shortest-Jobs-First

Dieses Verfahren (SJF) führt die Prozessorzuteilung in der Reihenfolge der


wachsenden Rechenphasen ("CPU-Burst") zu, d.h. Prozess mit kürzester, nächster
Rechenphase erhält Prozessor als nächster. Das Verfahren ist nur bedingt
realisierbar, da die Länge des nächsten CPU-Bursts a priori nicht bekannt ist.
In der Praxis wird daher eine Approximation eingesetzt, die auf der Basis der
gemessenen Länge der zurückliegenden Bursts und einem Schätzwert für den
nächsten Burst ermittelt wird.

• anwendbar, falls die Dauer der nächsten Rechenphase bis E/A-Befehl, Interrupt
etc. bekannt ist.
• Beispiel: P1: 6ms, P2: 8ms, P3: 7ms, P4: 3ms
Schedule bei SFJ : P4, P1, P3, P2; Wartezeit: (3+16 +9 +0) /4 = 7 ms
bei FCFS: 10.25 ms (P1 vor P2 vor P3 vor P4)
• Problem: Kenntnis über die Bedienzeiten erforderlich. Für Stapelbetrieb
geeignet, da dort Information über Rechenzeiten zur Verfügung stehen
(Benutzer geben bei Batch-Jobs Rechenzeit an). Für SJF gibt es wieder
nicht-unterbrechende und unterbrechende Varianten. Im letzteren Fall wird
ein Prozess unterbrochen, falls ein Prozess rechenwillig, dessen nächste
Rechenphase kürzer ist als die noch verbleibende Rechenzeit des momentan
rechnenden Prozesses.
• Für interaktive Prozesse wird die Länge der nächsten Rechenphase ("Burst")
geschätzt:
X n
Sn+1 = 1/n Ti
i=1

Ti = Ausführungszeit der i-ten Rechenphase.


Si = Schätzung für die i-te Rechenphase.
S1 = Schätzung für die erste Rechenphase. Diese wird nicht berechnet.
Anpassung der Berechnung (auf diese Weise wird die erneute Berechnung der
gesamten Summe vermieden)
Sn+1 = (1/n) * Tn + (n-1)/n * Sn
Hierbei wird jeder Rechenphase gleiches Gewicht gegeben. Durch die Wahl
eines geeigneten Faktors könnte man die neueren Rechenphasen höher
gewichten als die weiter zurückliegenden Rechenphasen, z.B. Sn+1 = a * Tn
+ (1-a) * Sn mit 0<a<1.

128
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

4.3.3 Beispiel Unix Scheduling


Beim Unix-Scheduling 3 handelt sich um eine Zeitscheibenstrategie mit
dynamischer Prioritätenvergabe. Unix vergibt für seine Prozesse Prioritäten von
0 - 127 (0 ist die höchste Priorität), die in 32 Warteschlangen verwaltet werden.
Alle Prozesse einer Prioritätsklasse befinden sich in einer Warteschlange, die nach
einer Round-Robin Strategie abgearbeitet wird. Zunächst wird allen Prozessen der
höchsten Priorität die CPU zugeteilt bis die Warteschlange leer ist. Dann kommen
die Prozesse mit der nächstniedrigeren Priorität zum Zuge. Die Prioritäten
werden fortlaufend neu berechnet (multilevel-feedback-queue). Die Prioritäten
der Prozesse, die in einem gewissen Zeitabschnitt viel Rechenzeit verbraucht
haben, werden erniedrigt; Prozesse, die lange gewartet haben, erhalten eine höhere
Priorität.

• Zeitscheibenstrategie pro Warteschlange bis Warteschlange leer; dann Schedu-


ling mit nächst niedrigerer Warteschlange.
• dynamische Berechnung der Prozesspriorität:
(1) u_prio = USER_PRIO + p_cpu/4 + 2 * p_nice
p_cpu ist die Prozessornutzung des rechnenden Prozesses und wird alle 10 ms
um 1 inkrementiert.
p_nice ist ein vom Benutzer bestimmter Gewichtungsfaktor (-20 ≤ p_nice ≤
20).
USER_PRIO ist die Priorität, die dem Prozess beim Start zugeteilt worden ist.
Der Wert von p_cpu wird jede Sekunde angepasst
(2) p_cpu = (2 * load)/(2 * load + 1) * p_cpu + p_nice
load ist eine Abschätzung der CPU-Auslastung.
Die Anpassung (2) sorgt dafür, dass die bisher verbrauchte Rechenzeit nach
einer gewissen Zeit nicht mehr ins Gewicht fällt. Das "short-term-scheduling"
unterstützt das interaktive Arbeiten am Rechner. Die Prioritäten von Prozessen,
die lange auf die Ausführung von E/A-Operationen warten, werden erhöht.
Dagegen werden die Prioritäten von Prozessen, die wesentliche CPU-Zeiten auf
sich vereinigen, verringert. Dies bedeutet zusammenfassend, dass ”interaktive”
Prozesse den ”Batch”-Prozessen vorgezogen werden.
• neuere Unix Varianten unterstützen Prioritäten von 0 bis 255, unterteilt in
0 - 127: Echtzeitprozesse
128 - 177: Systemdienste
178 - 255: Benutzerprozesse
3
siehe: Leffler u.a. : Das 4.3 BSD Unix Betriebssystem, Addison-Wesley

129
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

• Linux nutzt eine Kombination von dynamischen Prioritäten und Zeitscheiben-


verfahren, wobei die Art der Prozesse, Echtzeit oder interaktiv, berücksichtigt
wird. 4
Linux hat unterschiedlich lange Zeitscheiben, je nach Priorität, z.B. 200ms
für die höchste und 10ms für die niedrigste Priorität.

4.3.4 Thread Scheduling


Die Prozessorzuteilung von Threads hängt von deren Art der → Realisierung
(siehe Seite 118) ab.

User-Threads

Realisierung der Threads im Benutzeradressraum ⇒ Kern hat keine Kenntnis


bzgl. der Threads. BS-Scheduler wählt nur Prozess aus. Laufzeitsystem des
Prozesses wählt rechenwilligen Thread des Prozesses aus; es kann ein beliebiges
→ Scheduling-Verfahren (siehe Seite 124) für Prozesse verwendet werden. Da
auf der Ebene des Laufzeitsystems keine Zeitunterbrechungen (clock interrupts)
bearbeitet werden (sie werden auf Betriebssystem-Ebene bearbeitet), können
Threads so lange laufen, bis sie selbst die CPU freiwillig aufgeben, d.h. ein
Thread kann vom Laufzeitsystem aufgrund des Ablaufs einer Zeitscheibe nicht
unterbrochen werden.

• Java Virtual Machines verwenden unterbrechendes Prioritäten-Scheduling für


Threads;
10 ist die höchste und 1 die niedrigste Priorität;
Ein rechenwilliger höher priorer Thread führt zur Unterbrechung eines
rechnenden niedriger prioren Thread ("unterbrechender Scheduler").
Weiterhin kann ein Thread auch freiwillig die CPU aufgeben ("cooperative
scheduler"). Probleme treten auf, wenn Threads die gleiche Priorität haben.
Falls ein cooperative Scheduler verwendet wird, ist der aktuelle Thread
solange rechnend, bis er freiwillig die CPU aufgibt. Falls er dies nicht
macht, sind die anderen rechenwilligen Threads nur wartend (Gefahr des
Verhungerns).
Ein unterbrechender Thread-Scheduler wird in gewissen Zeitabständen
den aktuell rechnenden Thread unterbrechen, und andere Threads gleicher
Priorität auswählen.
4
siehe Achilles S 44 für detailliertere Ausführungen.

130
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

Das Ablauf-Verhalten hängt vom Scheduling Verfahren der jeweiligen


JVM Implementierung ab, z.B. Windows verwendet unterbrechendes Thread
Scheduling, während der Mac bisher cooperative Thread Scheduling realisiert
(möglicherweise anders bei MacOS 10).

Kernel-Threads

Realisierung der Threads im Systemadressraum ⇒ BS-Scheduler wählt den


nächsten auszuführenden Thread aus.
a) Ist ausgewählter Thread demselben Prozess zugeordnet wie der vorher
rechnende Thread ⇒ geringer Kontextwechsel.
b) Ist ausgewählter Thread nicht demselben Prozess zugeordnet wie
der vorher rechnende Thread ⇒ aufwendiger Kontextwechsel. In diesem
Fall findet auch ein Adressraumwechsel statt, d.h. die Register zur
Speicherabbildung müssen angepasst werden.

4.3.5 Mehrschichtiges Scheduling


Der Scheduler wählt einen der rechenwilligen Prozesse aus. Da diese aber u.U.
nicht alle im Arbeitsspeicher vorliegen (Speicherknappheit) und ein Einlagern
eines Prozesses von der Platte in den Arbeitsspeicher aufwendig ist, verfügen
Systeme häufig über ein Mehr-Schichten Scheduling.

• Short-Term-Scheduler (CPU Scheduler)


Auswahl eines geeigneten Prozesses aus der Ready-Queue; wird häufig
aufgerufen; Verfahren siehe oben.

• Long-Term-Scheduler
Auswahl rechenwilliger neuer Aufträge (meist Jobs aus dem Hintergrundbe-
trieb (batch)) und Einlagerung in den Arbeitsspeicher; Einfügen der Prozesse
in die Ready-Queue. Scheduler kontrolliert den Multiprogramming-Grad, d.h.
wieviele Prozesse im Arbeitsspeicher liegen. Long-Term-Scheduler wird relativ
selten aufgerufen. Wenn ein Prozess das System verläßt, wird dieser Scheduler
u.U. erst nach mehreren Minuten aufgerufen.
Kriterium: guten Prozessmix erzielen, d.h. Mischung aus E/A-intensiven
und rechenintensiven Prozessen (nur E/A-intensiv: Ready-Queue häufig
leer, CPU nicht ausgelastet, andersherum: E/A-Geräte schlecht ausgelastet).
Long-term Scheduling ist nicht immer vorhanden: z.B. in Unix nicht, jeder
neue Prozess wird in Arbeitsspeicher geladen. Eine andere Zwischenstufe ist

131
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

Medium-term-Scheduling: bei Überlast werden Prozesse auf Hintergrundspei-


cher ausgelagert (swap out) und später wieder eingelagert (swap in).

• Graphische Darstellung

neue
Aufträge

Long-term
Scheduler ausgeswappte
Prozesse
swap-out
swap-in

Ready Queue CPU fertig

CPU Scheduler

E/A-Befehl

E/A-Warteschlange
Zeitscheibe
abgelaufen

sleep-Befehl
Zeit-Interrupt-
Warteschlange

Ausführung im Systemaufruf
BS-Kern

4.3.6 Echtzeit Scheduling


In Multimedia-Umgebungen treten die zu verarbeitenden kontinuierlichen Daten
(Empfangen, Dekodierenen und Anzeigen von Videoframes) in bestimmten, meist
periodischen Zeitabständen auf. Die Operationen auf diese Daten wiederholen
sich dabei immer wieder und sollen bis zu einem gewissen Zeitpunkt abgeschlos-

132
Schlichter, TU München 4.3. PROZESSORVERWALTUNG

sen sein. Prozesse in Multimedia-Anwendungen 5 führen oft zeitkritische Ope-


rationen aus. Bzgl. des Scheduling existieren zwei gegensätzliche Ziele:
a) ein unkritischer Prozess sollte nicht dauerhaft blockiert werden, weil
zeitkritische Prozesse eine Ressource gänzlich auslasten. Daher sollten
zeitkritische Prozesse und Verwaltungsarbeiten nicht die gesamte Kapazität
einer Ressource beanspruchen.
b) zeitkritische Prozesse dürfen nicht durch Scheduling-Verfahren (Round-
Robin oder Prioritäten) am zeitkritischen Fortschritt gehindert werden ⇒
Einhaltung von Zeitvorgaben.

• Zuordnung von Kenngrößen zu zeitkritischen Prozessen


Bereitzeit (ready time): frühestmöglicher Ausführungsbeginn einer
Aktivität.
Frist (deadline): spätester Zeitpunkt für die Beendigung einer Aktivität.
Ausführungszeit: worst-case Abschätzung für das zur vollständigen
Ausführung einer Aktivität notwendige Zeitintervall.
In vielen Fällen werden Aktivitäten periodisch ausgeführt. Deshalb werden
hierzu neben der Ausführungszeit Kenngrößen wie Frequenz der Aktivität
(Periode) und Versatz des Ausführungsbeginns relativ zum Anfang der Periode
(Phase) erfasst.
• Earliest Deadline First (EDF)
Der Prozessor wird immer dem Prozess mit der am nächsten in der
Zukunft liegenden Frist zugeordnet. Es existieren die beiden Varianten:
nicht-unterbrechend und unterbrechend. Fasst man die Fristen als Prioritäten
auf, dann entspricht dieses Verfahren im Prinzip dem prioritäten-basierten
Scheduling.

– nicht-unterbrechend
Eine Prozessorzuordnung bleibt bis der Prozess eine blockierende System-
funktion aufruft oder freiwillig die CPU abgibt. Neue eintreffende Prozesse
mit kürzeren Fristen werden erst beim nächsten Scheduling berücksichtigt.
– unterbrechend
Diese Variante führt einen Kontextwechsel durch, wenn ein Prozess
mit einer kürzeren Frist rechenwillig wird. Man kann zeigen, dass die
preemptive Variante immer eine Abarbeitungsreihenfolge mit Einhaltung
aller Zeitvorgaben findet, solange mindestens eine solche Reihenfolge
existiert.
5
[Steinmetz1999, S303][Nehmer2001, S123]; Videobilder nicht zu früh, sonst Pufferüberlauf;
Videobilder nicht zu spät, sonst Ablaufgeschwindigkeit nicht korrekt.

133
Schlichter, TU München 4.4. UNTERBRECHUNGSKONZEPT

• Rate-Monotonic Scheduling
Rate-Monotonic Scheduling (RMS) ist für periodische Prozesse; RMS ordnet
Prioritäten in Abhängigkeit von der Periode zu.
1) Prozesse mit der höchsten Frequenz (kleinste Periode) erhalten die
höchste Priorität.
2) Prozesse mit der geringsten Frequenz (längste Periode) erhalten die
niedrigste Priorität.
Die Priorität ist statisch; sie ändert sich nicht für den Rest der Prozesslaufzeit.
Prioritäten geben die relative Wichtigkeit eines Prozesses gegenüber der
Wichtigkeit anderer Prozesse im Rechensystem wider. RMS ist relativ einfach
zu handhaben und sie erlaubt eine Abschätzung, ob eine Echtzeitanwendung
auf einer bestimmten Rechenanlage ohne Fristverletzung ausgeführt werden
kann oder nicht.

– Auswahl der Prozesse anhand ihrer Priorität. Jedoch auch unter Berücksich-
tigung der anderen Kenngrößen, wie z.B. Bereitzeit.
– hochfrequente Prozesse werden minimal verzögert.
– Zerstückelung niederfrequenter Prozesse, da sie häufig wegen hochfrequen-
ter Prozesse unterbrochen werden.

4.4 Unterbrechungskonzept
Die optimale Ausnutzung und Auslastung aller Geräte eines Rechensystems legt
Mehrprogrammbetrieb nahe. Zerlegung der Ausführungsphasen eines Programms
in viele Einzelteile;
- Aufbrechen der Ausführung eines Prozesses in mehrere Phasen: u.a.
Rechnen, E/A, Synchronisieren mit Partner.
- Die Ausführung der Programme wird in der Regel mehrfach unterbrochen.

4.4.1 Motivation
Ursachen für Unterbrechungen
zugeteilte Prozessorzeit ist aufgebraucht;
benötigte Ressourcen stehen aktuell nicht zur Verfügung;
ein E/A-Gerät meldet sich zurück;
ein Fehler tritt auf, z.B. Division durch 0;
Systemaufruf (wurde bereits als spezielle Unterbrechung eingeführt);

134
Schlichter, TU München 4.4. UNTERBRECHUNGSKONZEPT

Die ersten 3 Ursachen sind extern veranlasst, während die letzten beiden
Unterbrechungen intern ausgelöst werden.

• Bei einer Unterbrechung wird ein gerade aktiver Prozess unterbrochen


und eine Unterbrechungsbehandlung durchgeführt. Nach Beendigung der
Unterbrechungsbehandlung kann prinzipiell ein beliebiger rechenbereiter
Prozess fortgesetzt werden.

• Es ist erforderlich, bei der Unterbrechung den CPU Status des gerade aktiven
Prozesses für die spätere Fortsetzung zu speichern. Als Minimum ist dabei
der Befehlszähler und das Programmstatuswort zu retten, da diese bei der
Einstellung des neuen Zustandes bei der Unterbrechungsausführung in der
CPU verändert werden. Weitere Zustandsinformationen wird dann in der
Unterbrechungsbehandlung des Betriebssystems gerettet.

• Forderung: Eine Unterbrechung muss so kontrolliert erfolgen, dass ein


definierter Prozessstatus festgehalten werden kann.

4.4.2 Unterbrechungsarten
Die normale Programmausführung eines Prozessors kann auch durch mehrere
Arten von Unterbrechungen verändert werden. Man unterscheidet zwischen
synchronen und asynchronen Unterbrechungen.

Unterbrechung

synchron asynchron

Alarme
Trap Interrupt
(Exception)

Der Aufruf von Systemdiensten des Betriebssystems erfolgt über "Traps"


(Software Interrupt). Bei einem Hardware Interrupt meldet z.B. ein Gerät über
ein HW-Signal ein Ereignis an die Software, z.B. E/A abgeschlossen. .

135
Schlichter, TU München 4.4. UNTERBRECHUNGSKONZEPT

Externe, asynchrone Unterbrechungen

Dies sind Unterbrechungen (Interrupts), die von außerhalb des zu unterbrechen-


den Prozesses ausgelöst werden, z.B. E/A-Kanal-"Endmeldung". Asynchrone Un-
terbrechungen sind Ereignisse im Rechensystem, die über besondere Steuerbus-
leitungen an den Prozessor weitergegeben werden. Asynchron bedeutet in diesem
Kontext, dass der eintreffende Interrupt in keiner kausalen Beziehung zum aktuell
ausgeführten Befehl steht.

• Der Ablauf im Rechnerkern (RK) wird unterbrochen und eine Unterbrechungs-


anfangsbehandlung des Betriebsystemkerns wird aktiviert.

E/A-Kanal 2 CPU (RK) BS-Kern

Ende E/A
Auftrag
Unterbrechungs-
behandlung (UBH)

Interne, synchrone Unterbrechungen

Dies sind Unterbrechungen (Alarme, Exceptions), die durch den zu unterbrechen-


den Prozess selbst ausgelöst werden, z.B. Division durch 0. Synchrone Unter-
brechungen sind eine unmittelbare Folge der aktuellen Befehlsausführung. Sie
können auch explizit durch einen speziellen Befehl (Trap) ausgelöst werden. Mit
Hilfe von Traps werden Systemdienste im Betriebssystem aufgerufen. Im Fehler-
fall spricht man auch von Alarmen ("exceptions").

• Der Ablauf im RK wird unterbrochen und eine Unterbrechungsanfangsbehand-


lung des Systemkerns wird aktiv. In der Unterbrechungsanfangsbehandlung
wird der Status des unterbrochenen Prozesses gerettet und es wird die Ursache

136
Schlichter, TU München 4.4. UNTERBRECHUNGSKONZEPT

der Unterbrechung identifiziert. Anschließend wird zu der zugehörigen Unter-


brechungsbehandlung verzweigt.

CPU (RK) BS-Kern

Unterbrechung
arithmetischer Alarm

Unterbrechungs-
behandlung (UBH)

• Beispiele von internen Unterbrechungen


Speicherschutzalarm: Prozess greift auf Speicherbereich zu, der nicht
vorhanden ist oder auf den er nicht zugreifen darf.
Befehlsalarm: dem Operationscode des Maschinenbefehls ist keine Opera-
tion zugeordnet.
Seitefehltalarm: Seite der virtuellen Adresse ist nicht im Arbeitsspeicher.
arithm. Alarm: arithm. Operation kann nicht ausgeführt werden, z.B.
Division durch 0.
Systemaufruf: kontrollierter Übergang in das Betriebssystem.

4.4.3 Behandlung externer Unterbrechungen


Synchrone und asynchrone Unterbrechungen haben hardwaremäßig die Speiche-
rung des aktuellen Prozessorzustandes zur Folge und lösen im Anschluss daran
einen indirekten Sprung über eine im Speicher befindliche Sprungtabelle aus. Da-
bei ordnet der Prozessor jeder synchronen und asynchronen Unterbrechung einen
festen Index in der Sprungtabelle zu. An dieser Stelle steht die Anfangsadresse
der Unterbrechungsroutine, die entsprechende Folgemaßnahmen einleitet. Falls
möglich (Ausnahme ist z.B. ein arithmetischer Alarm) kann die unterbrochene
Programmausführung durch die Wiederherstellung des gespeicherten Prozessor-
zustandes zu einem beliebigen, späteren Zeitpunkt fortgesetzt werden.

137
Schlichter, TU München 4.4. UNTERBRECHUNGSKONZEPT

Ablauf

• Geräte-Controller meldet Unterbrechung über spezielle Interrupt-Leitung an


CPU.

• CPU prüft im Befehlszyklus nach jeder Befehlsausführung, ob eine Unterbre-


chung gemeldet wurde.

• Falls Unterbrechung vorliegt: sichern u.a. des aktuellen Befehlszählers, des


Programmstatusworts und Sprung zu einer Unterbrechunganfangsbehandlung,
die an festgelegter Speicheradresse steht. Die restlichen Informationen, wie
Register, werden dann von der Unterbrechungsbehandlung gesichert.
Routine untersucht Unterbrechungsursache, die vom Controller über
Datenleitung gemeldet wird (Unterbrechungsnummer).
über Unterbrechungsnummer erfolgt die Auswahl der benötigten Unter-
brechungsbehandlungsroutine; Nummer ist i.a. Index in eine Tabelle, dem
Unterbrechungsvektor.
Vektor enthält Speicheradresse der Unterbrechungsbehandlungsroutine.

4.4.4 Konflikte
Konflikte bei Unterbrechungen treten z.B. in folgenden Situationen auf:
(1) während einer Unterbrechungsbehandlung treten weitere Unterbrechun-
gen auf;
(2) es treffen gleichzeitig mehrere Unterbrechungswünsche ein.

• Beispiel
E/A-Kanal 1 und E/A-Kanal 2 erledigen beide Aufträge für Prozess A.

138
Schlichter, TU München 4.4. UNTERBRECHUNGSKONZEPT

E/A-Kanal 1 Prozess A BS-Kern E/A-Kanal 2

externe
Unterbrechung

Ende E/A Unterbrechungs-


Auftrag behandlung (UBH)

externe
Konflikt
Unterbrechung
Ende E/A
Auftrag

• Mögliche Konfliktlösungen

– Andere Unterbrechungen nicht zulassen, d.h. Maskierung von Unterbrechun-


gen; anstehende Unterbrechung ignorieren oder vorläufig zurückstellen; Pro-
blem: u.a. Rechtzeitigkeit der Unterbrechungsbehandlung. Beispielsweise
sollte ein Division durch 0 in UBH sofort behandelt werden.
– Interne Unterbrechungen erfolgen stets sofort und geben der zugehörigen
Unterbrechungsbehandlung dieselbe Priorität, wie sie der unterbrochene Ab-
lauf hatte. Die Benutzerprozesse haben die niedrigste Ablaufpriorität, näm-
lich 0. Unterbrechungen von Unterbrechungsbehandlungen sind möglich.
– Externe Unterbrechungen erhalten Prioritäten z.B. (0,...,31) zugeordnet. Die
aufgerufene Unterbrechungsbehandlung erhält die Priorität (Ablaufpriorität)
der auslösenden Unterbrechung.

Eine weitere externe Unterbrechung wird während einer Unterbre-


chungsbehandlung zugelassen, wenn die Priorität der neuen Unterbre-
chung höher als die Ablaufpriorität der gerade aktiven Unterbrechungs-
behandlung ist. Trifft dieser Fall nicht zu, so wird der Unterbrechungs-
wunsch zurückgestellt, bis ein Ablauf mit einer niedrigeren Ablaufprio-
rität aktiv wird.
Konsequenz: Unterbrechungsroutinen müssen ablaufinvariant (reentrant)
sein!

139
Schlichter, TU München 4.4. UNTERBRECHUNGSKONZEPT

• Integration der Unterbrechungsbehandlung in den Befehlszyklus der CPU


prüfen ob interne Unterbrechung aufgetreten,
falls ja, Behandlung der Unterbrechung
sonst : prüfen ob externe Unterbrechung mit höherer Priorität. Wenn ja
wähle eine mit höchster Priorität.
Bei Unterbrechung: sichere alten Zustand, stelle neuen Zustand her und
führe ersten Befehl der Unterbrechungsbehandlungsroutine aus.

140
Kapitel 5

Speicherverwaltung

Der Adressraum ist eine zentrale Abstraktion, die von der Systemsoftware eines
Rechensystems zur Verfügung gestellt werden muss. Über den Adressraum sind
alle für die Ausführung eines Anwendungsprogramms notwendigen Operationen
und Datenstrukturen zugreifbar. Allgemein wird ein Adressraum durch eine
zusammenhängende Menge von Adressen und deren Inhalte definiert. Die
maximale Größe eines Adressraums kann aus dem Adressbusaufbau der
verwendeten Prozessorarchitektur abgeleitet werden. Modernde Rechensysteme
unterscheiden zwischen den Adressräumen der Programme und dem physischen
Adressraum (Arbeitsspeicher).

5.1 Fragestellungen
Dieser Abschnitt beschäftigt sich mit den Adressräumen für Programme und
deren Abbildung auf den physischen Arbeitsspeicher einer Rechenanlage:

• Programmadressraum vs. Maschinenadressraum.


• Direkte Adressierung, Basisadressierung.
• Virtualisierung des Speichers; virtuelle Adressierung, insbesondere Seiten-
adressierung.

5.2 Einführung
Die unmittelbare Nutzung des physischen Adressraums (Arbeitsspeichers) bei der
Anwendungsentwicklung ist nicht empfehlenswert. Probleme sind folgende:

141
Schlichter, TU München 5.2. EINFÜHRUNG

- Kenntnisse über Struktur und Zusammensetzung des Arbeitsspeichers


notwendig.
- Kapazitätsengpässe bei der Arbeitsspeichergröße. Werden die in einem
Rechensystem bei der Befehlsausführung durch den Rechnerkern auftreten-
den Adressen direkt als reale Speicheradressen interpretiert, so kommt man
schnell in Kapazitätsengpässe. Die Kapazität des Arbeitsspeichers reicht oft
nicht aus, um alle Daten darin abzulegen. Deshalb weicht man auf den Hinter-
grundspeicher (Platte) aus, um Teile der Daten eines Prozesses dort abzulegen.

⇒ deshalb Programmerstellung unabhängig von realer Speichergröße und


-eigenschaften. Abstrahieren von realen Eigenschaften der Hardware. Die
Handhabung der unterschiedlichen Speicher sollte für die Programmierung
in höheren Programmiersprachen ohne Belang sein, d.h. der Programmierer
soll sich nicht explizit um das Nachladen von benötigten Daten vom
Hintergrundspeicher in den Arbeitsspeicher und umgekehrt kümmern
müssen. Dies soll automatisch, d.h. transparent für den Programmierer
geschehen.

5.2.1 Adressräume
• Maschinenadressraum

Der Arbeitsspeicher besteht aus einer Folge von fortlaufend nummerierten


Bytes. Die Nummerierung beginnt bei 0. Die Nummer des Bytes bezeichnet
man als seine Adresse, genauer als seine physische Speicheradresse oder seine
Maschinenadresse.
• Programmadressraum

Wenn ein Benutzer programmiert, dann benutzt er in seinem Programm


Adressen, um seine Variablen zu bezeichnen. Diese Adressen nennen wir
Programmadressen.
Die Menge der zulässigen Programmadressen ist der Programmadressraum.
Dieser ist prozessspezifisch, d.h. Programmadressen haben nur Programm-
lokale Bedeutung z.B. als Sprungziele.
• Speicherabbildung

142
Schlichter, TU München 5.2. EINFÜHRUNG

Die CPU muss vor jedem Zugriff auf Befehle und Operanden die jeweiligen
Programmadressen in Maschinenadressen umsetzen. Diese Umsetzung wird
durch Speicherabbildungen geleistet. Die wichtigsten dieser Abbildungen
werden in den folgenden Abschnitten kurz vorgestellt.

direkte Adressierung,
Basisadressierung,
Seitenadressierung und
Segment-Seitenadressierung.

5.2.2 Organisation von Adressräumen


Im Adressraum einer Anwendung müssen alle für die Programmausführung not-
wendigen Daten zur Verfügung gestellt werden. Darunter fallen der Programmco-
de (Text), der Datenbereich (statische und dynamische Daten) und der Laufzeit-
keller. Für jede dieser Informationsarten wird ein Bereich im Adressraum spezi-
fiziert, deren Platzierung und Größe durch die Adressraumverwaltung festgelegt
wird.

Single-Threaded Adressraum

statische dynamische Daten


Programm Keller
Daten (Halde)

niedrige hohe
Adresse Adresse

Die Bereiche Programmcode und statische Daten verändern sich typischerweise


während der Programmausführung nicht. Dagegen können der dynamische
Datenbereich (Halde) und der Laufzeitkeller an Umfang erheblich zunehmen.
Beim Laufzeitkeller hängen Größenschwankungen und Ausdehnung von der
maximalen Tiefe der Prozedur/Methodenschachtelung und dem Bedarf an lokalen
Variablen ab.

143
Schlichter, TU München 5.2. EINFÜHRUNG

Multi-Threaded Adressraum

statische dynamische Daten


Programm Keller 1 Keller n
Daten (Halde)

hohe
niedrige Adresse
Adresse

Für jeden Kontrollfluss (Thread) wird ein eigener Kellerbereich vorgesehen.


Der Abstand zwischen den einzelnen Kellern wird meist standardmäßig vom
System vorgegeben. Unabhängig von der Anzahl der Laufzeitkeller muss eine
Überschneidung zwischen mehreren Kellern oder zwischen dem untersten Keller
und der Halde vermieden werden.

Beispiel - Adressräume

Moderne Betriebssysteme stellen wenigstens 32 Bit große virtuelle Adressräume


für die Anwendungen zur Verfügung, die jeweils in mehrere Bereiche unterteilt
sind. Programmcode, statische Daten, Halde und Laufzeitkeller der Anwendung
werden jeweils in dem Bereich des Adressraums abgelegt, der der Anwendung
zugänglich ist.

Windows 32 bit Adressierung

Linux 32 bit Adressierung

0 1 GByte 2 GByte 3 GByte 4 GByte

spezieller Adressbereich (Größe nicht proportional)

Der für die Anwendung nutzbare Adressbereich (weißer Bereich) schwankt

144
Schlichter, TU München 5.2. EINFÜHRUNG

zwischen ca. 2 GByte und 4 GByte. Bei allen BS wird ein unterschiedlich
großer Adressbereich am Anfang (Adressen 0 und aufwärts) für jeglichen Zugriff
gesperrt: bei Windows 95 sind es 4 KByte, bei Windows NT 64 KByte, bei BSD
Unix ist es abhängig vom Rechnertyp (4 - 8 KByte). Durch diese Sperrung wird
jeder Zugriff auf diesen Bereich und damit insbesondere das Dereferenzieren
eines Nullzeigers vom System abgefangen und die Programmausführung mit
einer Fehlermeldung abgebrochen. Gleiches gilt für den Bereich zwischen dem
Adressbereich der Anwendung und des Betriebssystems; auch hier ist ein kleiner
Bereich, z.B. 64 KB bei Windows, nicht zugreifbar, um fehlerhafte Pointer zu
erkennen.
In Windows 95 wird zusätzlich der Adressbereich von 4 KByte - 4 MByte von der
Nutzung durch 32 Bit Anwendungen ausgeklammert (Adressbereich für MS-DOS
bzw 16 Bit Anwendungen).
Im oberen Bereich des virtuellen Adressraums wird meist der Betriebssystemcode
eingeblendet (z.B. bei Windows 95 im Bereich 1 GByte - 2 GByte; dadurch
können BS-Funktionen auch ohne Adressraumwechsel genutzt werden. Bei
BSD Unix und Windows NT/2000 ist dieser Bereich vor jeglichem Zugriff
durch die Anwendung geschützt (oft wird sogar lesender Zugriff unterbunden).
Bei Windows 95 besteht dieser Schutz nicht, d.h. Anwendungen können das
Betriebssystem zum Absturz bringen.
Windows 7 bzw. Windows 10 unterstützt 64 Bit Adressierung mit einem virtuellen
Adressraum von 8 TB. Für die Größe des physikalischen Arbeitsspeichers gelten
jedoch folgende Einschränkungen:
Windows 7 Professional bis 192 GB
Windows 7 Home Premium bis 16 GB
Windows 7 Home Basic bis 8 GB
Windows 10 Professional bis 512 GB
Windows 10 Home Basic bis 128 GB
Mac OS X bis 128 GB

Haldenverwaltung

Dynamisch erzeugte Daten, z.B. Listen und Objekte werden auf der Halde (heap)
gespeichert. 1 Die Halde wird nicht nach dem Kellerprinzip verwaltet. Zellen des
Kellerspeichers werden mit Hilfe der Operation pop freigegeben. Kellerbereiche
werden nach dem LIFO-Prinzip verwaltet. Datenobjekte der Halde werden bei
Bedarf erzeugt und gelöscht. Nicht mehr benötigte Datenobjekte werden entweder
1
siehe Informatik II von Prof. Brügge.

145
Schlichter, TU München 5.2. EINFÜHRUNG

explizit durch einen Programmaufruf entfernt (z.B. durch Anweisung free(objref))


oder implizit durch das System mit Hilfe der Speicherbereinigung (garbage
collection). Garbage collection ist eine Komponente des Laufzeitsystems, das
nicht referenzierte Objekte identifiziert, und deren Speicherplatz auf der Halde
freigibt.

• Belegung Beispiel C:

void malloc(size_t size) belegt dynamisch einen Speicherbereich


und gibt einen Pointer auf diesen Speicherbereich zurück. malloc gehört
zur C Standard Bibliothek. size_t ist als unsigned int definiert. malloc
initialisiert den Speicherbereich nicht. Falls ein Fehler auftritt, wird
ein Nullpointer zurückgegeben. Mit Hilfe der Funktion free wird der
Speicherbereich wieder freigegeben. malloc ist eine Fehlerquelle in C-
Programmierung, da gelegentlich die Freigabe des belegten Speichers
vergessen wird. In Java automatische Freigabe des belegten Speichers
durch den Garbage Collector.
• Der Speicherbereich einer Halde besteht aus zwei Klassen:

– Belegtbereiche: Speicherbereiche werden für Realisierungen von Datenob-


jekten verwendet.
– Freibereiche: Speicherbereiche, die momentan nicht für Realisierungen von
Datenobjekten verwendet werden; d.h. sie sind frei. Belegt-/Freibereiche sind
nicht konsekutiv im Arbeitsspeicher organisiert, sondern bestehen jeweils aus
einer Menge von Teilbereichen.

• Buchführung des Speicherbereichs einer Halde mit Hilfe von Belegungs- und
Freigabeoperationen.

• Verwaltung der Freibereiche


Speicherbereiche (belegt, frei) sind in Blöcken unterschiedlicher Länge
organisiert. Verwaltung freier Blöcke

– implizite Liste über Längen - verlinkt alle Blöcke


jeweils Feststellen, ob der Block belegt oder frei ist.
extra Bit im selben Wort wie Blockgröße. Jeder Block spezifiziert im
ersten Wort die Blockgröße sowie in einem extra Bit Information darüber,
ob der Block belegt oder frei ist.

146
Schlichter, TU München 5.2. EINFÜHRUNG

5 4 6 2

Implementierung: sehr einfach; Allozierung in linearer Zeit. Die Belegung


und Freigabe ist sehr einfach, da bei Belegung nur nach einem Block
geeigneter Größe gesucht und das Belegtbit gesetzt werden muss. Bei
Freigabe muss nur das Belegtbit wieder freigegeben werden. Möglicherweise
kann er mit einem vorhergehenden bzw. nachfolgenden freien Block
kombiniert werden.
– explizite Liste (Freiliste) über die freien Blöcke
Allozierung: Durchsuchen der Freiliste nach geeignetem Block

5 4 6 2

Das Verfahren etwas aufwendiger als implizite Listen, da ein extra Pointer
notwendig ist. Bei impliziten Listen ist kein extra Pointer notwendig, da
aufgrund der Blockgröße der Beginn des jeweils nächsten Blocks leicht zu
bestimmen ist. Eine weitere Verfeinerung ist die Führung von getrennten
Freiliste für jede unterschiedliche Größenklasse. Damit wird die Suche bei
der Allozierung erleichtert.

• Freiliste
Die Freibereiche der Halde werden mit Hilfe einer Liste (z.B. einfach verkettet)
verwaltet.
public class freibereich {
int size;
freibereich next;
<methodendefinitionen>
}
Für jeden verfügbaren Freibereich wird jeweils die Größe in Bytes gespeichert.
Man könnte auch eine doppelt verkettete Liste anlegen.

– Auswahl eines geeigneten Freibereichs

147
Schlichter, TU München 5.2. EINFÜHRUNG

Bei Erzeugung eines neuen Datenobjektes wird die Operation belege(int


size) ausgeführt. Der Parameter size spezifiziert hier die Größe des benötig-
ten Speicherbereichs auf der Halde. Für die Auswahl eines geeigneten Frei-
bereichs zur Erfüllung der gestellten Anforderungen existieren verschiedene
Verfahren.
∗ first-fit-Verfahren
bestimme von Beginn der Freiliste den ersten Speicherbereich, der die
Anforderung erfüllt. Der gefundene freie Speicherbereich wird aufgeteilt
in den Belegtbereich und den nicht benötigten Bereich. Letzterer wird
wieder in die Freiliste eingetragen. Es kann passieren, dass am Beginn
der Freiliste die Freibereiche immer kleiner werden, d.h. nachfolgende
Anforderungen müssen mehr Elemente in der Freiliste untersuchen.
∗ next-fit-Verfahren
bestimme in der Freiliste den ersten Speicherbereich, der die Anforderung
erfüllt. Die Suche wird dort fortgesetzt, wo die letzte Suche beendet wurde.
∗ best-fit-Verfahren
bestimmt in der gesamten Freiliste den Speicherbereich, der am besten die
gestellte Anforderung erfüllt, d.h. mit möglichst wenig Verschnitt. best-
fit ist langsamer als first-fit und next-fit, da jeweils die gesamte Freiliste
durchsucht werden muss. Überraschenderweise führt es im Durchschnitt
zu größerer Speicherverschwendung; das Zuteilungsverfahren hinterläßt
mehr sehr kleine Speicherbereiche, die nicht mehr zugeteilt werden
können.
∗ worst-fit-Verfahren
bestimme in der Freiliste den größten freien Speicherbereich und teile
ihn in einen Belegtbereich (zur Erfüllung der Anforderung) und einen
verbleibenden Freibereich auf. Mit Hilfe des worst-fit-Verfahrens soll die
Problematik des best-fit-Verfahrens mit seinen vielen kleinen, meist nicht
mehr nutzbaren freien Speicherbereichen vermieden werden.
– Fragmentierung
Problematisch ist die Entstehung von vielen kleinen freien Rest-
Freibereichen, die wegen ihrer kleinen Längen als Belegtbereiche ungeeignet
sind. Zur Vermeidung dieser nutzlosen, kleinen Freibereiche ist es zweckmä-
ßig, eine Minimallänge für Freibereiche festzulegen und bei Belegungsanfor-
derungen entsprechend längere Belegtbereiche zu erzeugen. Auch wird mit
Hilfe des worst-fit-Verfahrens die Problematik etwas reduziert.

• Garbage Collection
Java sammelt belegten Speicher, der nicht mehr benötigt wird, auf. In C muss
der Speicher explizit durch free freigegeben werden; deshalb oft sogenannte

148
Schlichter, TU München 5.2. EINFÜHRUNG

Memory-Leaks. Garbage Collection geht zurück auf die Lisp Systeme, die in
den 1960’er Jahren von McCarthy am MIT entwickelt wurden.
automatische Rückgewinnung von nicht mehr benötigtem Speicher
üblich in Spachen wie Java, Lisp, Perl, ....

– Woher kennt der Speichermanager nicht mehr benötigte Objekte?


i.a. nicht bekannt
allerdings können gewisse Blöcke nur dann benutzt werden, wenn
Pointer zu Ihnen existieren.
– Annahmen über Pointer
Speichermanager müssen Pointer von anderen Objekten unterscheiden
können. Und zwar von Objekten, die keine Pointer sind.
Alle Pointer müssen auf den Blockanfang zeigen.
– Speicher als Graph
Annahme
jeder Block ist ein Knoten
jeder Pointer ist eine Kante
Kantenausgangsknoten ist nicht auf der Halde (sondern im Keller) ⇒
Knoten ist Wurzel

Wurzelknoten
erreichbar
nicht
Haldenknoten
erreichbar

Besttimmung erreichbarer Knoten. Ein Knoten (Block) ist erreichbar, wenn


es einen Pfad von einer Wurzel zum Knoten gibt. Nicht-erreichbare Knoten
sind Garbage.
∗ Mark and Sweep
Aufsammeln mittels markieren und durchlaufen
Mark: an Wurzeln starten, Pfade durchlaufen und alle erreichbaren
Speicherblöcke markieren
Sweep: Scannen aller Blöcke; Freigabe nicht markierter Blöcke
– Zeitpunkt der Durchführung von Garbage Collection
wenn kein weiterer Platz mehr vorhanden ist, z.B. new gibt Fehler zurück

149
Schlichter, TU München 5.2. EINFÜHRUNG

automatisch im Hintergrund, wenn System nicht ausgelastet ist. Hier


wird meist davon ausgegangen, dass der Prozentsatz des belegten
Speichers einen bestimmten Schwellenwert überschreitet.

Animation Haldenverwaltung
siehe online Version

5.2.3 Fragmentierung
Unter dem Begriff Fragmentierung versteht man verschiedene Formen der
Zerstückelung des noch freien und nutzbaren Teils des Adressraums in kleine
Bereiche. Fragmentierung kann jedesmal dann entstehen, wenn eine neue
Speicherplatzanforderung aus der Menge noch freier Speicherbereiche mit einem
einzigen zusammenhängenden Bereich befriedigt werden muss. Unterscheidung
zwischen externer und interner Fragmentierung.

• Externe Fragmentierung
Es wechseln sich benutzte und unbenutzte Speicherbereiche innerhalb des
Adressraums ab. Speicheranforderungen werden jeweils genau erfüllt.

Anforderung

belegt belegt belegt

belegt belegt belegt belegt

freie Speicherbereiche

Im Fall eines Anwendungsadressraums tritt dies beim dynamischen Daten-


bereich (Halde) auf; Fragmentierung entsteht durch die unterschiedlichen

150
Schlichter, TU München 5.2. EINFÜHRUNG

Speicheranforderungs- und Freigabemuster. Durch zeitaufwendiges Zusam-


menschieben der Belegtbereiche (Kompaktifizieren) entsteht aus vielen kleinen
Speicherresten ein großer Freibereich. Beim Kompaktifizieren müssen u.U. die
Adressen in den Programmen angepasst werden (z.B. Verweise auf Absolut-
adressen).

• Interne Fragmentierung
Der Speicher ist in Bereiche fester Größe untergliedert und Speicheranforde-
rungen werden nur in Vielfachen dieser festen Grundgröße befriedigt.

Anforderung

freier Speicherbereich

Der Verschnitt findet innerhalb dieser Bereiche fester Größe statt. Beispiels-
weise kann Plattenspeicher nur blockweise belegt werden; die Blockgröße
schwankt zwischen 512 Byte und 4-8 Kbyte. Selbst für die Speicherung eines
einzigen Bytes muss ein ganzer Block belegt werden.

5.2.4 Forderungen an Adressraumrealisierung


Aus der Sicht der Anwendungsprogrammierung können für einen Adressraum
eine Reihe wichtiger Forderungen an dessen Realisierung gestellt werden.
Hier geht es um den Programmieradressraum für Prozesse, und nicht um den
Maschinenadressraum (Arbeitsspeicher).

151
Schlichter, TU München 5.3. SPEICHERABBILDUNGEN

• Homogene und zusammenhängende Adressbereiche. Dies ermöglicht eine


Programmentwicklung ohne das ansonsten notwendige Wissen über Position,
Typ und Größe der referenzierbaren Speichermodule und E/A-Controller.

• Größe des genutzten Adressraums unabhängig von der Kapazität des


physischen Adressraums (Arbeitsspeichers).

• Erkennen fehlerhafter Zugriffe. Beispielsweise Zugriffe, die aus dem


Adressraum herausführen

• Erkennen von Überschneidungen zwischen Halde und Keller sowie zwischen


mehreren Laufzeitkellern.

• Schutz funktionstüchtiger Anwendungen gegenüber fehlerhaften Anwendun-


gen. Hier geht es darum, dass die Adressbereiche der Anwendungen und auch
des Betriebssystems voneinander abgeschottet werden. Ist dieser Schutz nicht
gewährleistet, können fehlerhafte Programme den Adressraum einer anderen
Anwendung verändern und damit Folgefehler in dieser auslösen ⇒ nicht de-
terministische Fehler. Fehler dieser Art sind schwer zu reproduzieren und ihre
Lokalisierung ist meist extrem schwierig und langwierig.

• Kontrollierbares und kontrolliertes Aufteilen der Speicherressourcen auf alle


Anwendungen.

• Speicherökonomie, minimale Fragmentierung. Es sollten gängige Techniken


eingesetzt werden, um die durch dynamische Anforderungen bedingte Spei-
cherfragmentierung und den tatsächlichen Speicherbedarf jeder Anwendung zu
minimieren, z.B. gemeinsame Nutzung von Funktionsbibliotheken durch meh-
rere parallel laufende Anwendungen ⇒ Funktionsbibliothek muss nur einmal
geladen werden.

5.3 Speicherabbildungen
Dieser Abschnitt behandelt einige Mechanismen zur Abbildung von Programm-
adressen auf Maschinenadressen des Arbeitsspeichers.

5.3.1 Direkte Adressierung


Bei der direkten Adressierung werden die Programmadressen direkt als
Maschinenadressen interpretiert. Es treten drei Probleme auf:

152
Schlichter, TU München 5.3. SPEICHERABBILDUNGEN

Verschiebbarkeit,
Programmgröße,
Speicherausnutzung.

Verschiebbarkeit

In einem Mehrprozesssystem sind i.d.R. mehrere Programme im Arbeitsspeicher.


Bei direkter Adressierung werden die Programme beim Laden fixiert und
müssen dann bis zu ihrem Ende an derselben Stelle bleiben. Eine Verschiebung
ist nicht möglich, da der Benutzer mit Adressen rechnen kann und deshalb
positionsabhängige Adressen in seinen lokalen Variablen hat.
• Problem
Externe Fragmentierung des Arbeitsspeichers. Sei der Arbeitsspeicher zunächst
lückenlos mit Programmen P1, P2, P3 gefüllt.

P1 P2 P3

Nach Beendigung des Programms P2 entsteht eine Lücke.


Neue Programme passen u.U. nicht exakt in die zurückgebliebene Lücke.
Auf diese Weise entstehen immer mehr Lücken. Möglicherweise passen
Programme nicht mehr in den Arbeitsspeicher, weil keine ausreichend große
Lücken vorhanden ist, obwohl insgesamt noch ausreichend Platz wäre. Dies
ist das Problem der externen Fragmentierung des Arbeitsspeichers. Da die
Programme wegen der direkten Adressen nicht verschiebbar sind, ist eine
Speicherbereinigung erst möglich, nachdem alle angefangenen Programme
beendet sind.
Ein verwandtes Problem tritt bei Programmverdrängungen auf. Das verdrängte
Programm muss zur weiteren Ausführung später wieder an dieselbe Stelle
geladen werden, dies ist jedoch in der Regel nicht mehr möglich, da andere
Programme im benötigten Speicherbereich stehen können.
• Forderung
In Mehrprogramme/Mehrprozesssystemen müssen daher Programme ver-
schiebbar sein.

Programmgröße

Programme können wesentlich größer als der verfügbare Arbeitsspeicher werden.


Bei direkter Adressierung muss der Benutzer sein Programm selbst in Segmente

153
Schlichter, TU München 5.3. SPEICHERABBILDUNGEN

zerlegen und diese nach Bedarf selbst nachladen. Man spricht von der
sogenannten Overlay-Technik (veraltet). Die Overlay-Technik ist aufwendig,
schwierig und damit auch fehleranfällig. Da die Zerlegung statisch ist, kann
die Zerlegung des Programms nicht dynamisch an den konkret vorhandenen
Arbeitsspeicher angepasst werden und damit die jeweilige Maschine gut
ausnutzen.

• Forderung
Es muss daher gefordert werden, dass die Programmgröße unabhängig von der
realen Arbeitsspeichergröße ist.

Speicherausnutzung

Programme bestehen aus Modulen, die nur zu bestimmten Zeiten verwendet


werden. Beispielsweise wird bei einer Matrizenmultiplikation nur auf die Module,
die das Multiplikationsprogramm und auf die Module, die die Daten enthalten,
zugegriffen. Es ist nun wünschenswert, von einem Programm nur den Ausschnitt
im Arbeitsspeicher zu halten, der momentan und in naher Zukunft benötigt wird.
Damit lassen sich mehr Programme im Arbeitsspeicher unterbringen und parallel
verarbeiten. Dies steigert den Datendurchsatz des Systems.

• Forderung
Arbeitsspeicher beinhaltet nur die momentan bzw. in naher Zukunft notwen-
digen Ausschnitte des Programms. Nutzen der Lokalitätseigenschaft von Pro-
grammen:
durch Datenstrukturen z.B. Arrays, oder
Programmstrukturen: Prozeduren, Schleifen.

5.3.2 Basisadressierung
Die Basisadressierung hat eine einfache Abbildungsvorschrift:
Maschinenadresse = Basisadresse + Programmadresse

• Die Basisadresse ist programmspezifisch. Sie steht in einem Register des


Rechnerkerns und ist dem Programm, das im Benutzermodus abläuft, nicht
zugänglich. Sie wird vom Betriebssystem festgelegt.
• Die Programmadressen aller Programme beginnen jeweils mit Null. Durch die
Basisadressierung wird das Problem der Verschiebbarkeit gelöst. Die anderen
Probleme bestehen jedoch weiterhin. Deshalb wird die Basisadressierung in
modernen Betriebssystemen nicht mehr eingesetzt.

154
Schlichter, TU München 5.3. SPEICHERABBILDUNGEN

• Speicherverwaltungsstrategien
Aufgabe: Finden eines zusammenhängenden Arbeitsspeicherbereichs, der groß
genug ist, um das Programm zu speichern ⇒ siehe Verfahren zur → Verwaltung
der Halde (siehe Seite 147). Hier kommen die Strategien zum Einsatz, die
bereits bei der Haldenverwaltung diskutiert wurden, insbesondere deren Vor-
und Nachteile. Beispielsweise erfordert best-fit immer den Durchlauf durch die
gesamte Freibereichsliste. Zusätzlich liefert diese Strategie mit der Zeit immer
kleinere Fragmente ⇒ externe Fragmentierung.

– first-fit
Durchsuche die Liste der Freibereiche vom Anfang an und nimm den ersten
passenden Frei-Bereich: Spalte nicht benötigten Speicher ab und füge ihn als
freien Bereich in die Freibereichsliste ein. Problem: am Anfang häufen sich
kleine Reststücke, die bei jeder Suche neu durchsucht werden müssen.
– next-fit
Durchsuche die Liste der Freibereiche nach first-fit, jedoch beginne die Suche
dort, wo man bei der letzten Suche aufgehört hat. Problem von first-fit mit
den kleinen Reststücken am Anfang wird vermieden.
– best-fit
Durchsuche die Liste der Freibereiche vom Anfang an und nimm den
passenden Frei-Bereich, der die Speicheranforderungen des Programms am
besten erfüllt: Spalte nicht benötigten Speicher ab und füge ihn als freien
Bereich in die Freibereichsliste ein.
– worst-fit
Durchsuche die Liste der Freibereiche vom Anfang an und nimm den Frei-
Bereich, der die Speicheranforderungen des Programms am schlechtesten
erfüllt: Spalte nicht benötigten Speicher ab und füge ihn als freien Bereich in
die Freibereichsliste ein.
– Buddy-Systeme
Speicheranforderungen werden in Größen von Zweierpotenzen vergeben,
d.h. eine Anforderung wird auf die nächste Zweierpotenz aufgerundet
Anforderung 280 Bytes ⇒ Belegung von 512 Bytes = 29
In Linux wird dieses Verfahren in Kombination mit der Seitenadressierung
verwendet. Zusammenhängende Kacheln des Arbeitsspeichers werden
mittels des Buddy-Verfahrens zugeordnet.
∗ am Anfang besteht der Arbeitsspeicher aus einem großen Stück. Abhängig
von der Größe des Arbeitsspeichers.

155
Schlichter, TU München 5.4. SEITENADRESSIERUNG

∗ Speicheranforderung von 2k: ist Speicherbereich dieser Größe vorhanden,


dann Unterteilung eines Speicherbereichs der Größe 2k+1 in 2 Speicherbe-
reiche der Größe 2k Bytes. Ihre Anfangsadressen sind gleich bis auf das
k-te Bit; dies ist invertiert. Dies läßt sich ausnutzen, um in einem Schritt
zu überprüfen, ob für ein freigewordenes Speicherstück das entsprechende
Partnerstück existiert und frei ist.
∗ Freigabe eines Speicherbereichs von 2k: falls auch entsprechendes
Partnerstück frei ist, dann Verschmelzung der beiden Speicherbereiche zu
einem Speicherstück der Größe 2k+1.

5.4 Seitenadressierung
Die virtuelle Adressierung wurde Ende der 50er Jahre 2 eingeführt. Viele
weiterführende Arbeiten erfolgten dann später im Rahmen des Projektes MAC
und des Systems MULTICS (Vorgänger von UNIX) in den USA in den 60er
Jahren. Ziel ist
Virtualisierung des Speichers,
Verstecken von realen Beschränkungen, wie Speichergröße,
Speicher als sehr großes Feld gleichartiger Speicherzellen zu betrachten.
Die Seitenadressierung ("paging") ist die Grundform der virtuellen Adressierung.

5.4.1 Ansatz
Der Programmadressraum, der sogenannte virtuelle Adressraum eines Prozesses
wird in aufeinanderfolgende Seiten (engl. page) gleicher Größe unterteilt.
Man spricht deshalb von virtuellen Adressen des Prozesses, anstatt von
seinen Programmadressen. Gängige Größen für virtuelle Adressräume heutiger
Architekturen:
232 , also 32-Bit Adressen zum Ansprechen der Speicherzellen.
Fortgeschrittene Architekturen: 264, also 64-Bit Adressen (z.B. Sun ULTRA-
Sparc).
Die Seiten sind keine logische Aufteilung des Speichers. Denkaufgabe: was hat
das für Vor- und Nachteile?

• Der Maschinenadressraum, also der physische Adressraum des Arbeitsspei-


chers, wird in Kacheln (engl. frame) unterteilt. Seiten und Kacheln sind i.d.R.
2
Fotheringham, J. : Dynamic storage allocation in the ATLAS computer including an automatic
use of backing store. CACM 4:10, 435-436, Oct 1961.

156
Schlichter, TU München 5.4. SEITENADRESSIERUNG

gleich groß. Es ist auch möglich, dass die Seitengröße ist ein Vielfaches der Ka-
chelgröße ist. Im Folgenden wird von gleichen Größen ausgegangen. Typische
Seitengrößen sind 4 - 8 KByte.

• Eigenschaften der Seitenadressierung

– Die Seiten eines Prozesses können im Arbeitsspeicher oder auf dem


Hintergrundspeicher (Platte) gespeichert sein.
– Die Kacheln nehmen die Seiten der Prozesse auf. Wichtig ist, dass sowohl
die Seiten als auch die sie aufnehmenden Container, die Kacheln, eine
einheitliche Größe besitzen. Das erleichtert die Speicherverwaltungsaufgabe
erheblich.
– Wenn während der Prozessausführung eine virtuelle Adresse des Prozess-
adressraums verwendet wird, so muss die Seite, in der sich die Adresse be-
findet, in einer Kachel des Arbeitsspeichers geladen (eingelagert) sein. Es ist
eine Abbildungsvorschrift notwendig, die die virtuelle Adresse auf die reale
Kacheladresse (Maschinenadresse) abbildet. Ein Problem ist:
woher weiss das BS welche Seite eines Prozesses sich wo im
Arbeitsspeicher befindet, d.h. welche Kachel welcher Seite zugeordnet
ist?

Antwort: Beschreibung der Seiten erforderlich; dazu Verwendung von


Deskriptoren, die in Tabellen verwaltet werden (Seiten-Kacheltabelle).

– Die Zuordnung, welche Seite in welcher Kachel gespeichert ist, und wo sich
die Seite auf dem Hintergrundspeicher befindet, erfolgt mittels der Seiten-
Kacheltabelle, die die Seitendeskriptoren enthält. Die Zuordnung von Seite
zu Kachel kann sich im Laufe eines Programmablaufes ändern.
– Befindet sich bei einer Befehlsausführung die erforderliche Seite nicht im
Arbeitsspeicher, so löst ein solcher Zugriff eine Unterbrechung aus ⇒
Seitenfehler ⇒ Einlagerung der Seite bei Bedarf ("Demand Paging").
Der Seitenfehler ist eine synchrone Unterbrechung, die vom Betriebssystem
zu behandeln ist, d.h. die geforderte Seite ist in den Arbeitsspeicher zu laden.
Man spricht deshalb auch vom Demand Paging. Nach dem erfolgreichen
Laden der Seite wird der Befehl, der zum Alarm führte, erneut ausgeführt.
Der gesamte Vorgang heißt Seiteneinlagerung (engl. paging).
– Falls eine Seite eingelagert werden muss, aber gleichzeitig bereits alle
Kacheln des Arbeitsspeichers besetzt sind, so muss eine der eingelagerten
Seiten aus dem Arbeitsspeicher verdrängt werden. Man spricht von

157
Schlichter, TU München 5.4. SEITENADRESSIERUNG

der Seitenauslagerung. Die Strategien, die man hierbei einsetzt, heißen


Seitenersetzungsstrategien. Ziel dieser Strategien ist es, eine möglichst
günstige Seite auszuwählen, und diese auf den Hintergrundspeicher
auszulagern. Günstig bedeutet hier, eine Seite, die entweder für den
Prozessablauf nicht mehr benötigt wird, oder die erst sehr viel später benötigt
wird, als die anderen Seiten im Arbeitsspeicher.

• virtueller Speicher - Arbeitsspeicher


Der Zusammenhang zwischen dem virtuellen Speicher, hier den virtuellen
Adressräumen der Prozesse, und dem Arbeitsspeicher sowie Hintergrundspei-
chermedien wird nachfolgend skizziert. Auf die einzelnen Bereiche gehen wir
im Folgenden näher ein. Wir gehen hier vereinfachend davon aus, dass auch die
Blöcke als Einheiten des Hintergrundspeichers die Größe einer Seite besitzen.
virt. Adressraum von P1

Seite 1 von
Kachel 1
P1
Seiten-Kachel
Tabelle
Seite 2 von
... Kachel 2 Auslagern
P1
...
...
..... ... Kachel 3
...
...
... Kachel 4
Seite 1 von ...
P2
Deskriptor
Kachel 5 Einlagern
Seite 2 von Hintergrundspeicher
P2 mit Blöcken

...

.....
Arbeitsspeicher
mit Kacheln
virt. Adressraum von P2

• Vorteile
Bei der Seitenadressierung werden durch eine flexible Speicherabbildung alle
Probleme der → direkten Adressierung (siehe Seite 152) gelöst. D.h. die
Programme können:
verschoben werden,
größer als der Arbeitsspeicher sein,
auch ausschnittsweise im Arbeitsspeicher sein.
– Zusätzliche positive Eigenschaften

158
Schlichter, TU München 5.4. SEITENADRESSIERUNG

∗ Es können gemeinsame Speicherbereiche zwischen Prozessen realisiert


werden. Programme können gemeinsame Speicherbereiche haben, bei-
spielsweise bei gemeinsamen Daten nebenläufiger Prozesse. Auch Code-
Bereiche können im Hinblick auf eine bessere Speicherausnutzung ge-
meinsam sein, beispielsweise muss der Code eines Compilers nur einmal
geladen werden, auch wenn ihn mehrere Benutzer gleichzeitig verwen-
den. Dies ist besonders interessant für ablaufinvarianten Code (reentrant),
der während der Ausführung nicht verändert wird.
∗ Es ist ein differenzierter Zugriffsschutz innerhalb eines Prozesses möglich.
Zugriffsrechte für einzelne Seiten können unterschiedlich vergeben
[Link] haben eine Seite, in der Programmcode, aber keine Variablen
gespeichert sind. Sie können auf dieser Seite nur lesen bzw. ausführen
erlauben, dagegen kein Verändern. Ein Verändern würde ja bedeuten, dass
der Programmcode im Ablauf modifiziert wird. Dies nutzen Angreifer, die
sich in einem Wirtprogramm "einnisten".

5.4.2 Adressabbildung
Bei der Seitenadressierung erfolgt die Umsetzung der Programmadressen, also die
Umsetzung der virtuellen Adressen in Maschinenadressen durch eine Abbildung
von Seiten auf Kacheln. Eine virtuelle Adresse v ist gegeben durch v = (s, w),
wobei s die Seitennummer und w das Offset in der Seite angibt. Die Adresse v
wird abgebildet auf die reale Adresse p = (k, w), wobei k die Kachelnummer
angibt, die die Seite enthält.

Seitentabellenregister virtuelle Adresse

s w
Seiten-Kacheltabelle

L
k

k w

Längenregister Adresse im Arbeitsspeicher

D.h. die virtuelle Adresse wird von der CPU nicht direkt auf den Speicherbus

159
Schlichter, TU München 5.4. SEITENADRESSIERUNG

gelegt, sondern an die MMU (Chip oder mehrere Chips) weitergeleitet. Die MMU
berechnet die reale Adresse und legt sie auf den Bus. Falls s > L ist, kann mit Hilfe
des Längenregisters sofort ein Adressierungsfehler entdeckt werden.

Beispiel für Adressrechnung

Gegeben sei ein 16-Bit virtueller Adressraum und eine Seitengröße von 4K. D.h.
der Adressraum zerfällt in 16 Seiten; man benötigt 4 Bit, um die Seitennummern
zu identifizieren und 12-Bit, um die 4096 Byte innerhalb einer Seite zu
adressieren.

v= 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0

present/
s=2 absent Bit
0 010 1
1 001 1
2 110 1
12 bit offset w
3 000 1
wird kopiert
4 100 1
5 011 1
6 000 0
7 000 0
Seiten-
8 000 0 Kacheltabelle
9 101 1
10 000 0
11 111 1
12 000 0
13 000 0
14 000 0
15 000 0

p= 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0

k=6

Die Anzahl der Bits von s (Seitennummer) und k (Kachelnummer) können sich
unterscheiden. Die Zahl der Bits von s hängt von der Größe des virtuellen
Adressraums ab, während sich die Anzahl der Bits von k aus der Größe des
Maschinenadressraums ergibt. Damit können s und k unterschiedliche lang sein.

160
Schlichter, TU München 5.4. SEITENADRESSIERUNG

Memory Management Unit

Die Adressrechnung wird von der Hardware, der MMU (Memory Management
Unit), durchgeführt.

Speicherbus
Arbeits
CPU MMU
speicher
virtuelle physische
Adressen Adressen

Meist ist die MMU auf dem CPU-Chip integriert.

• Translation Lookaside Buffer


Zur Adressumsetzung enthält die MMU die Tabelle Translation Lookaside
Buffer (TLB), die häufig auftretenden Seitennummern die Kachelnummer
zuordnet. TLB umfasst wenige Einträge (z.B. 8, 16, oder 32) und kann als
Cache interpretiert werden.
Bei jedem Zugriff auf eine virtuelle Adresse wird überprüft, ob sich die
zugehörige Seite und damit die Kacheladresse im TLB befindet. TLB ist
als assoziativer Cache organisiert ([Link]!), d.h. alle Einträge werden
gleichzeitig auf Übereinstimmung mit dem Seitenanteil der referenzierten
Adresse verglichen. Ist kein entsprechender Eintrag in der TLB (TLB-
miss), erfolgt die Adressabbildung über den relevanten Deskriptor der Seiten-
Kacheltabelle.
Ein Eintrag in der TLB enthält eine virtuelle und zugeordnete reale Adresse
⇒ kein aufwändiges Page Table Lookup für TLB-Einträge erforderlich.
Designziel bei der Verwaltung der TLB-Einträge ist eine gute Trefferrate (TLB-
hit).

161
Schlichter, TU München 5.4. SEITENADRESSIERUNG

virtuelle Adresse

s w

Seitennr Kachelnr
TLB hit

k w

TLB Adresse im
Arbeitsspeicher

Seiten-Kacheltabelle

s
TLB miss
k

Ohne TLB sind für die Umrechnung 2 Zugriffe im Arbeitsspeicher notwendig:


1. Zugriff auf Seiten-Kacheltabelle, 2. Zugriff auf Speicherstelle. Falls für die
Seite noch kein Eintrag in TLB vorhanden ist, wird zunächst der entsprechende
Seitendeskriptor in den TLB geladen.
Zugriffszeit
Sei
TLB Suche: 20 ns
Speicherzugriff: 100 ns
Bei einem TLB hit ergibt sich Zugriffszeit 120 ns und bei einem TLB miss
sind dies 220 ns. Im letzteren Fall ergibt sich dies aus der Summe: 20 ns (TLB
Suche) + 100 ns (Zugriff auf Eintrag in Seiten-Kacheltabelle) + 100 ns (Zugriff
auf Speicherzelle)
Bei einer TLB-Treffer Wahrscheinlichkeit von 80% ergibt sich als durchschnitt-
liche effektive Speicherzugriffszeit
0,80 * 120 + 0,20 * 220 = 140 ns
Für einen Speicherzugriff ergibt sich damit eine 40% Verzögerung gegenüber
der direkten Adressierung. Gegenüber der Seitenadressierung ohne TLB ergibt
sich eine Verbesserung von 30%.

162
Schlichter, TU München 5.4. SEITENADRESSIERUNG

5.4.3 Seiten-Kacheltabelle
Die Adressabbildung erfolgt mittels der Seiten-Kacheltabelle (SKT). Wir benöti-
gen Informationen über die zu verwaltenden Seiten. Dazu wird jede Seite eines
Prozesses durch einen Seitendeskriptor beschrieben. Die Seiten-Kacheltabelle ist
i.a. prozessspezifisch. Neben der Zuordnung Seite-Kachel enthält ein Seitende-
skriptor noch weitere Informationen, wie z.B. die Zugriffsrechte und den Zustand
der Seite.

Struktur eines Seitendeskriptor

Informationen in einem Seitendeskriptor:

• Zugriffsrechte (A)
Angabe, ob der Prozess
- ausführend (x ∈ A),
- lesend (r ∈ A),
- schreibend (s ∈ A).
auf die Seite zugreifen darf. Diese Information wird vom Betriebssystem
eingetragen und in der CPU vor dem Zugriff ausgewertet.

• Seite existent (e)


Es müssen nicht alle Seiten existent sein. Beispielsweise sind oft die
Seiten zwischen Ende der Halde und Kellerende nicht existent. Generell
besteht die Vorstellung, dass in einem Adressraum mehrere Objekte (Daten
oder Programmteile) sind, zwischen denen Lücken liegen können. Seiten
des Adressraums, in denen keine Objekte sind, sind nicht existent. Wird
versucht, auf eine nicht existente Seite zuzugreifen, dann gibt es einen
Speicherschutzalarm.

• Seite geladen (v)


Die Abbildung ist gültig (engl. valid). Die Seite ist also in den Arbeitsspeicher
geladen, d.h. ihr ist eine Kachel zugeordnet. Es kann auf sie zugegriffen werden.
Eine nicht geladene, aber existente Seite steht im Verdrängungsbereich (engl.
swap area) auf dem Plattenspeicher. Soll auf eine existente, aber nicht geladene
Seite zugegriffen werden, dann löst die CPU einen Seitefehltalarm aus, d.h. ein
Seitenfehler tritt ein. Die Seite wird vom Hintergrundspeicher geladen, und das
Programm an der Stelle fortgesetzt, die den Seitefehltalarm auslöste.

163
Schlichter, TU München 5.4. SEITENADRESSIERUNG

• Zugriffsbit (r)
Das Zugriffsbit (engl. reference bit) dient zur Unterstützung der Seitenerset-
zungsalgorithmen. Es wird von der CPU nach dem Laden der Seite gelöscht
und bei einem Zugriff auf eine Seite von der CPU gesetzt. Nach einem gewis-
sen Zeitintervall wird es wieder zurückgesetzt.

• Veränderungsbit (m)
Die Seite wurde verändert (modifiziert). Dieses Bit dient ebenfalls zur
Unterstützung der Seitenersetzungsalgorithmen. Es wird nach dem Laden
der Seite von der CPU gelöscht und nach einem schreibenden Zugriff auf
die Seite gesetzt. Beispielsweise könnte eine Verdrängungsstrategie bevorzugt
Seiten auslagern, die nicht modifiziert wurden, d.h. ein Übertragen der Seite
auf den Hintergrundspeicher ist nicht notwendig, da die Seite auf dem
Hintergrundspeicher noch aktuell ist ⇒ man spart sich den Datentransfer.

Probleme

Es gibt einige Probleme mit der Seitenadressierung, die sich auf die Speichereffi-
zienz und die Performanz beziehen.

• Größe der Seiten-Kacheltabelle


Die Seiten-Kacheltabelle kann sehr groß werden, z.B. bei Seitengröße 4K
(früher üblich!) ergeben sich für 32-bit Adressraum insgesamt 1 Million Seiten
pro Prozess.
Lösung? Mehrstufige Tabellen: Seiten-Kacheltabelle ebenfalls in Seiten
unterteilen, die ihrerseits in Tabellen gehalten werden. Technisch wird bei
einem mehrstufigen Verfahren der Seitenanteil der virtuellen Adresse in
Abhängigkeit von der Stufenzahl weiter unterteilt, z.B. s1, s2,...sn. In der
Regel wird mit der Adressabbildung ab dem höchstwertigen Bit begonnen.
Der Anteil s1 definiert den Index für die Seitentabelle erster Stufe, s2 den
Index für den Anteil zweiter Stufe, etc.

164
Schlichter, TU München 5.4. SEITENADRESSIERUNG

virtuelle Adresse

s1 s2 w

Deskriptor

Deskriptor k w

Beispielsweise kann ein 32-Bit Adressraum auf der ersten Stufe in 128 Seiten
(27) mit je 32 MByte unterteilt werden. Ein Seitentabellen-Deskriptor verweist
auf eine Seitentabelle, die die 32 MByte große Seite in weitere Seiten unterteilt,
z.B. 256 KByte. Es muss nicht die gesamte Tabelle im Arbeitsspeicher gehalten
werden. Das schrittweise Durchlaufen u. U. mehrstufiger Seiten-Kacheltabellen
nennt man Page-Table Lookup.
3
– Linux verwendet ein 3-stufiges Paging Verfahren
jede virtuelle Adresse ist in 4 Teile aufgeteilt.

• Performanz
Schnelle Umrechnung der virtuellen auf realen Adressen erforderlich, da
Berechnung bei jedem Zugriff notwendig ist! Häufig verwendete Adressen
werden in einem Schnellzugriffspeicher (cache) der MMU gehalten, dem
Translation Lookaside Buffer (TLB).

Varianten der SKT

Varianten für den Aufbau einer Seiten-Kacheltabelle.

• Prozess-spezifisch, Index-basiert (PI)


Zugriff auf Deskriptor für Seite si über Index i.
3
Tanenbaum01 S 770

165
Schlichter, TU München 5.4. SEITENADRESSIERUNG

• Prozess-spezifisch, assoziativ (PA)


Hier wird die Seitennummer mit in den Seitendeskriptor aufgenommen. Die
SKT ist prozessspezifisch. Es sind nur die geladenen Seiten aufgeführt.
• Global, assoziativ (GA)
Es gibt nur eine SKT im System. Da die Seitennummer allein nicht eindeutig
ist, muss das Prozesskennzeichen (PID), d.h. der eindeutige Prozessname,
ebenfalls in den Deskriptor aufgenommen werden. Es sind nur die geladenen
Seiten aufgeführt. Die maximale Anzahl der Elemente dieser SKT ist die
Anzahl der Kacheln, falls gemeinsame Speicherbereiche der Prozesse nicht
betrachtet werden.
• Global, indiziert (GI)
Enthält auch PID und es erfolgt eine Reihung gemäß der Kachelnummer;
freie Kacheln werden durch einen speziellen Eintrag gekennzeichnet. Kacheln,
denen keine Seite zugeordnet ist, erhalten einen speziellen Eintrag bei PID.
Damit enthält die Tabelle so viele Elemente wie Kacheln im Arbeitsspeicher
vorhanden sind. Da die Angabe der Kachelnummern sich aus der Position
in der Tabelle ergibt, kann diese Angabe entfallen. Der Ansatz entspricht
einer invertierten Seitentabelle. Tabelle muss nach Seitennummer durchsucht
werden (im schlechtesten Fall die gesamte Tabelle) ⇒ Verwendung von
Haschcodierung bei Tabellenzugriff (Hashwert auf Seitennummer).

5.4.4 Seitenfehlerbehandlung
Der Zugriff auf eine Seite, die nicht im Arbeitsspeicher ist, führt zu einem
Seitenfehler.
Arbeitsspeicher

Seiten- Kachel 1
Kacheltabelle

Kachel 2
(4)
(5) Aktuali- Einlagern
(1) Zugriff sieren
Kachel 3
load M
(6) Befehl
erneuert
..... Hintergrundspeicher
mit Blöcken
(2) page fault

Prozess P1 Seitenfehler- (3) Seite auf Hintergrundspeicher


behandlung des
BS

166
Schlichter, TU München 5.4. SEITENADRESSIERUNG

Ablauf der Seitenfehlerbehandlung

1. Beim Zugriff auf eine virtuelle Adresse (z.B. LOAD-Befehl) tritt ein
Seitenfehler auf.
2. Die Adressrechnungshardware löst einen Alarm aus, so dass die Unterbre-
chungsbehandlung des BS aktiviert wird. Dieser wird beispielsweise in der
MMU bei der Adressrechnung ausgelöst. Der Prozesszustand muss gerettet
werden, u.a. der Befehlszähler und die Registerbelegungen. Weiterhin muss der
Unterbrechungsbehandlung die Adresse übergeben werden, die den Seitenfeh-
ler auslöste.
3. Das BS stellt eine freie Kachel zur Verfügung, lokalisiert die Seite auf der
Platte und initiiert die Einlagerung der Seite (Lesen von Platte). Falls aktuell
keine Kachel frei ist, muss eine Seite auf den Hintergrundspeicher verdrängt
werden. Falls die Daten nicht auf der Festplatte vorhanden sind, wird ein
Speicherschutzalarm ausgelöst.
4. Die Seite wird eingelagert.
5. Der Seitendeskriptor wird aktualisiert und verweist jetzt auf die belegte Kachel
(im Beispiel k = 3).
6. Der unterbrochene Befehl wird erneut gestartet. Die Daten sind jetzt
zugreifbar. Dazu muss zunächst wieder der Prozesszustand geladen werden,
d.h. Befehlszähler, Register etc. Anschließend wird der Befehl fortgeführt, als
ob keine Unterbrechung stattgefunden hätte.

5.4.5 Seitenverwaltungsstrategien
Aufgabe der Arbeitsspeicherverwaltung: Laden der für die Ausführung der
Prozesse benötigten Seiten in die Kacheln. Es ergeben sich drei strategische
Aufgaben:

Ladestrategie

Frage: welche Seite ist zu Laden?

• Lösungsansätze

– Einzelseitenanforderungsstrategie (on demand): eine Seite wird genau dann


geladen, wenn auf sie zugegriffen wird und sie sich noch nicht im
Arbeitsspeicher befindet.

167
Schlichter, TU München 5.4. SEITENADRESSIERUNG

– Seiten-Prefetching: Seiten werden im Voraus geladen, um sie sofort bei


Bedarf verfügbar zu haben. Wann ist Prefetching sinnvoll und was benötigt
das BS? Beispielsweise am Anfang beim Laden des main-Programms.
∗ Windows XP kombiniert "Demand Paging" mit "Prefetching": bei einem
Seitenfehler werden die gewünschte Seite sowie auch einige nachfolgende
Seiten (falls möglich) in den Arbeitsspeicher eingelagert.

Platzierungsstrategie

Frage: in welche Kachel ist eine Seite zu Laden?

• Lösung

– keine strategische Entscheidung erforderlich, da alle Kacheln gleichwertig


sind und damit keine Auswahl getroffen werden muss. Vorteil der uniformen
Realisierungskonzepte (Seite, Kachel).

Seitenverdrängungsstrategie

Frage: welche Seite ist aus dem Arbeitsspeicher zu entfernen, wenn für eine zu
ladende Seite keine freie Kachel mehr zur Verfügung steht? Im Idealfall baut
ein Verdrängungsverfahren auf der Referenzlokalität vieler Programme (Verbot
von Goto-Befehlen) und der sich ergebenden Lokalitätsmenge auf. Solange
sich die Lokalitätsmenge jedes Prozesses im Arbeitsspeicher befindet, ist die
Seitenfehlerrate sehr gering. Auf der Grundlage der Working-Set-Theorie ergibt
sich damit für ein Seitenverdrängungsverfahren die Aufgabe, bevorzugt solche
Seiten auszulagern, die nicht in der Lokalitätsmenge enthalten sind.

• FIFO Strategie
FIFO (first-in first-out): Verdrängen der ältesten Seite, einfach zu implementie-
ren. Das Verfahren berücksichtigt die Lokalitätsmenge nicht. So werden über
längere Zeit hinweg häufig referenzierte Seiten verdrängt (z.B. Seiten mit Kon-
stanten und globalen Variablen, die am Anfang geladen und häufig referenziert
werden). Umgekehrt bleiben auch wenig referenzierte Seiten im Mittel genau-
so lange im Arbeitsspeicher wie häufig referenzierte Seite. Vorsicht bzgl der
FIFO-Anomalie, d.h. trotz Vergrössern des zur Verfügung stehenden Arbeits-
speichers können u.U. mehr Seitenfehler (d.h. Seiteneinlagerungsoperationen)
auftreten, als bei kleinerem Speicher. (Warum, woran könnte so etwas liegen?
Antwort: FIFO beachtet nicht, wann die Seite zuletzt benutzt wurde. D.h. ei-
ne häufig benutzte globale Variable, die zu einem frühen Zeitpunkt eingelagert

168
Schlichter, TU München 5.4. SEITENADRESSIERUNG

wurde, könnte z.B. dazu führen, dass diese Seite nach dem Entfernen gleich
wieder eingelagert werden muss.)

– Belady’s Anomalie
Zuordnung von zusätzlichen Kacheln an einen Prozess reduziert nicht
notwendigerweise die Anzahl der Seitenfehler. Das Gegenteil ist möglich.
Beispiel:
∗ Aufrufsequenz von benötigten Seitennummern: 1, 2, 3, 4, 1, 2, 5, 1, 2, 3,
4, 5
∗ jeweils 3 Seiten im Arbeitsspeicher:
(1, 2, 3), (2, 3, 4), (3, 4, 1), (4, 1, 2), (1, 2, 5), (2, 5, 3), (5, 3, 4) ⇒ 9
Seitenfehler
∗ jeweils 4 Seiten im Arbeitsspeicher:
(1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 1), (4, 5, 1, 2), (5, 1, 2, 3), (1, 2, 3, 4),
(2, 3, 4, 5) ⇒ 10 Seitenfehler

• Second-Chance
Variante von FIFO, die vermeidet, dass ältere Seiten, obwohl sie häufig benutzt
werden, ausgelagert werden. Neben dem Status "älteste Seite" wird auch
Zugriffsbit r betrachtet:
r = 1: Seite wird an das Ende der FIFO Liste gestellt; r wird auf 0 gesetzt.
Die Seite wird so behandelt, als ob sie neu angekommen wäre.
r = 0: Seite wird ausgelagert; bei Modifikation (m-Bit gesetzt) wird Seite
zurückgeschrieben.

– Clock-Algorithmus
Eine Implementierungsart von Second-Chance ist der Clock-Algorithmus.
4
Die Seiten werden in einem Ring angeordnet. Ein Pointer zeigt auf den
nächsten Kandidat für eine Auslagerung. Falls r=1 ist, wird das Zugriffsbit
zurückgesetzt und der Pointer auf die nächste Seite im Ring gesetzt.
Oft in Kombination mit dem m-Bit (Modifikation).

4
Tanenbaum01 S 238, Stallings S370

169
Schlichter, TU München 5.4. SEITENADRESSIERUNG

Seite 7 Seite 9
r=0 r=0
m=1 m=1
Seite 94
r=0
m=0
Seite 47 Seite 95
r=1 r=1
m=1 m=0
Seite 46 Seite 45
r=1 r=1
m=0 m=0

Verfahren
1. beginnend von der aktuellen Pointerposition suche die erste Seite mit
(r=0, m=0); diese Seite wird ausgelagert. Die Zugriffsbits werden nicht
verändert, d.h. zurückgesetzt.
2. Falls 1. Schritt fehlschlägt, suche nach der ersten Seite mit (r=0; m=1);
diese Seite wird ausgelagert. Von untersuchten Seite wird das r-Bit
zurückgesetzt. Die Zugriffsbits aller untersuchten Seiten werden auf 0
zurückgesetzt.
3. Falls 2. Schritt fehlschlägt, starte von der ursprünglichen Pointerposition;
wiederhole den 1., und falls notwendig, den 2. Schritt. Bei Beginn des 3.
Schritts sind alle R-Bits der im Ring gespeicherten Seiten auf 0 gesetzt.
Dieses Mal wird auf jeden Fall (im 1. Schritt oder spätestens im 2.
Schritt) eine Seite für die Auslagerung identifiziert. Im Prinzip geht der
Algorithmus zyklisch durch die Menge der Seiten, um eine Seite, die nicht
modifiziert und in letzter Zeit nicht referenziert wurde.

• Weitere Strategien

– LIFO (last-in first-out): Verdrängen der jüngsten Seite, einfach zu implemen-


tieren. Diese Strategie berücksichtigt Lokalitätseigenschaft von Programmen
(häufig in Schleifen, Prozeduren ⇒ Zugriff auf gleiche Seiten) nicht.
– LRU (Least recently used): Verdrängen der am längsten nicht genutzten Seite;
wird am häufigsten realisiert, wobei LRU approximiert wird, da eine exakte
Realisierung zu aufwendig ist. Eine exakte Realisierung ist durch spezielle

170
Schlichter, TU München 5.4. SEITENADRESSIERUNG

Hardware möglich, die jeder Seite ein Zeitfeld assoziiert und dieses bei
jedem Zugriff aktualisiert.
Frage: wie LRU-Verhalten approximieren
Antwort: Nutzen eines Referenz-Bits (siehe r-Bit der Seitendeskriptor-
Informationen) pro Seite, das durch Hardware bei einem Seitenzugriff
gesetzt wird. Jeder Seite wird ein Zähler zugeordnet. Das BS inspiziert
in regelmäßigen Abständen die Seiten, und inkrementiert den Zähler
der Seiten mit nicht gesetztem Bit. Für jede referenzierte Seite werden
dagegen Zähler und r-Bit gelöscht. Verdrängt wird immer die Seite mit
dem höchsten Zählerstand, da diese am längsten nicht referenziert wurde.
– Working-Set Modell
Working-Set ist die Menge der Seiten, die ein Prozess zu einem bestimmten
Zeitpunkt benutzt.
w(k,t) = Menge der Seiten, die zum Zeitpunkt t in den letzten k
Speicherzugriffen benutzt wurden. t ist hierbei als Position in der
Seitenreferenzfolge zu interpretieren.
die Zahl k kann dynamisch angepasst werden.
t kann hier als Position in der Seitenreferenzfolge interpretiert werden, und
nicht als physikalische Zeit. Bei Windows XP wird für das Working Set ein
Minimum und Maximum spezifiziert; in der Regel ist das Minimum 35 und
das Maximum 345 Seiten.
∗ Verdrängungsstrategie: ersetze eine der Seiten, die nicht zum aktuellen
Working-Set gehören.
∗ Verdrängung einer Seite notwendig, obwohl alle Seiten zu w(k,t) gehören:
verkleinere den Parameter k
Reduziere die Anzahl der Prozesse im Arbeitsspeicher ⇒ Auslagern
eines Prozesses auf die Festplatte (Swapping).
∗ Working-Set kann nur näherungsweise über Zugriffsbits (r) und Verände-
rungsbit (m) bestimmt werden.
– Optimale Strategie: Seite, auf die in Zukunft am längsten nicht zugegriffen
wird. Die optimale Strategie ist unrealistisch, da das zukünftige Verhalten
i.d.R. nicht bekannt ist. Leistungsdaten dieser Strategie, d.h. wieviele
Seitenfehler treten bei gegebener Arbeitsspeichergröße und gegebenen
Zugriffscharakteristika von Prozessen auf, gibt Obergrenze für Erreichbares
an. Die Strategie ist gut für Vergleiche von Algorithmen, d.h. zur
Bestimmung der Güte eines Verfahrens.

171
Schlichter, TU München 5.4. SEITENADRESSIERUNG

Weitere offene Fragen

• Wahl einer vernünftigen Seitengröße


Die Wahl der Seitengröße steht unter widersprüchlichen Zielsetzungen; daher
ist ein Kompromiss erforderlich.
1. Je kleiner die Seite, desto rascher die Transfers zwischen ASP und Platte.
2. Je kleiner die Seite, desto geringer der Verschnitt (interne Fragmentie-
rung) durch nicht voll ausgenützte Seiten.
3. Je größer die Seite, desto geringer der Overhead für Transport zwischen
Arbeitsspeicher und Platte pro Byte (Arm positionieren, Warten bis Spur
unter Lese-Schreib-Kopf).
4. Je größer die Seite, desto mehr Information kann zwischen Arbeitsspei-
cher und Platte je Zeiteinheit transportiert werden.
5. Je größer die Seite, desto seltener Transfers erforderlich.

– Beispiele für Seitengrößen: Intel 80386 4K, Pentium II 4K oder 4MB,


UltraSPARC 8K, 64K, 512K oder 4MB. Tendenz: grössere Seiten. Warum?
schnelle CPU und großer Arbeitsspeicher, Seitenfehler haben großen
Einfluss auf Performanz des Rechensystems, deshalb möglichst wenige.

• Seitenflattern
Seitenflattern (engl. thrashing) tritt auf, wenn im System zuviele Prozesse
sind, die nebenläufig voranschreiten wollen und Kacheln beanspruchen. Gerade
verdrängte Seiten müssen zu schnell wieder eingelagert werden, das System ist
im schlimmsten Fall nur noch mit Ein- und Auslagern beschäftigt.

5.4.6 Linux - Virtuelle Adressierung


Das Speichermanagementsystem von Linux orientiert sich am Speichermanage-
ment von anderen Unix Implementierungen. Linux hat jedoch einige spezielle
Charakteristika. Die virtuelle Adressierung in Linux basiert auf mehrstufigen Sei-
tentabellen
Seiten-Directory ("page directory"). Jeder aktive Prozess hat ein einzelnes
Seiten-Directory, das jeweils im Arbeitsspeicher liegt. Einträge verweisen auf
mittlere Seiten-Directories. Ein Seiten-Directory hat die Größe einer Seite.
mittleres Seiten-Directory ("page middle directory"). Es kann sich über
mehrere Seiten erstrecken.
Seitentabelle ("page table").

172
Schlichter, TU München 5.4. SEITENADRESSIERUNG

Register

+
Seitentabelle
+ Seite
Seiten-Directory
+

mittleres Seiten- +
Directory

Seiten Directory mittleres Directory Seitentabelle Offset

Die Seitentabellenstruktur von Linux ist Plattform unabhängig; sie würde


ursprünglich für die 64-bit Adresstruktur des Alpha Prozessors entwickelt. Für
die 32-bit Pentium/x86 Architektur wird die 3-Stufen Struktur auf eine 2-Stufen
Struktur angepasst (x86 unterstützt nur zwei Stufen), in dem die Größe des
mittleren Seiten Directories auf eins gesetzt wird.

• Seitenallokation
aufeinanderfolgende Seiten werden auf zusammenhängende Kacheln abgebil-
det. Auf diese Weise wird die Performanz beim Lesen und Schreiben von Seiten
in bzw. aus dem Arbeitsspeicher erhöht.
Behandlung von Gruppen mit 1, 2, 4, 8, 16, oder 32 Seiten. Auf der x86-
Architektur ist die Seitengröße 4 KBytes. Gruppen von Kacheln werden
gemäß dem Buddy-System vergeben.
• Seitenverdrängung
Anwendung eines modifizierten Clock-Algorithmus. Zugriffsbit r wird durch
einen 8-bit Zähler ersetzt.
bei jedem Zugriff wird der Zähler inkrementiert.
Linux dekrementiert periodisch die Zähler aller Seiten im Arbeitsspeicher.
Linux scannt dazu periodisch durch alle Seiten, die im Arbeitsspeicher sind,
und dekrementiert jeweils den Zähler. Auf eine Seite deren Zählerwert 0 ist,
wurde seit einiger Zeit nicht mehr zugegriffen und sie wird als Kandidat für
die Auslagerung betrachtet. Eine Seite, auf die in letzter Zeit öfters zugegriffen
wurde, ist eher weniger eine Kandidat für die Auslagerung. Linux realisiert eine
Form der LFU.

173
Schlichter, TU München 5.5. SEGMENT-SEITENADRESSIERUNG

5.5 Segment-Seitenadressierung
Unterteilung des Programmadressraums in logische Einheiten unterschiedlicher
Länge, sogenannte Segmente. Ein Segment umfasst inhaltlich bzw. organisato-
risch zusammengehörige Speicherbereiche, z.B. Daten, Code und Laufzeitkeller-
Segment. Im Gegensatz dazu ist die Seiteneinteilung systembedingt und vom
jeweiligen Programm unabhängig. Die Segmentunterteilung ist programmspezi-
fisch.

• Jedes Segment besitzt eine maximale Größe. Die Länge der einzelnen Segmente
kann unterschiedlich sein und sich dynamisch verändern.

• Jedes Segment wird durch einen Segment-Deskriptor beschrieben. Die


Segmentdeskriptoren werden in einer Segmenttabelle verwaltet.

• Jedes Segment besteht aus Seiten, die jeweils beginnend mit Null fortlaufend
numeriert sind.

• Ein Zugriff auf ein nicht existentes Segment führt zum Speicherschutzalarm.

• Um in dieser Situation möglichst kompakte Speicherabbildungstabellen zu


erhalten, wird die Seiten-Kacheltabelle aufgeteilt. ⇒ je Segment eine
eigene Seiten-Kacheltabelle gehalten. Die (Maschinen-) Adressen der Seiten-
Kacheltabellen werden in einer Segmenttabelle gehalten.

Segmenttabellenregister Seiten-Kacheltabelle

0
Segmenttabelle
0

+ s k
+ sg

Adresse im
Arbeitsspeicher
sg s w

virtuelle Adresse k w

174
Schlichter, TU München 5.6. SPEICHERHIERARCHIE / CACHES

Bei der Adressierung der Tabellen muss natürlich jeder Index mit der Länge eines
Seiten- bzw Segmentdeskriptors multipliziert werden. Falls ein Eintrag 4 Byte
lang ist, ergibt sich damit z.B.
Adresse des Segmentdeskriptors =
Wert Segmenttabellenregister + sg * 4.
Entsprechendes gilt auch für die Seiten-Kacheltabelle.

5.6 Speicherhierarchie / Caches


Einige fundamentale Eigenschaften von Hardware und Software
schnelle Speichertechnologien kosten mehr Geld pro Byte und haben kleinere
Kapazitäten.
Lücke zwischen CPU und Arbeitsspeichergeschwindigkeit wächst.
gut geschriebene Programme tendieren dazu, gute Lokalität zu haben
zeitliche Lokalität: kürzlich referenzierte Objekte werden in naher
Zukunft wieder referenziert.
räumliche Lokalität: Objekte mit beieinander liegenden Adressen,
tendieren dazu, ungefähr zur gleichen Zeit referenziert zu werden.
Der Lokalitätseffekt wurde bereits beim Working-Set bzgl. der Verdrängung von
Seiten berücksichtigt.

5.6.1 Speicherhierarchie - Beispiel

175
Schlichter, TU München 5.6. SPEICHERHIERARCHIE / CACHES

CPU Register enthält Wort geholt vom


L0 Register Cache Speicher

kleiner On-chip L1 enthält Cache Zeilen geholt vom


L1
schneller cache L2 cache
teuerer
Off-chip L2 enthält Cache Zeilen geholt vom
L2 Arbeitsspeicher
cache
größer enthält Blöcke geholt vom
langsamer L3 Arbeitsspeicher
Hintergrundspeicher
billiger
lokaler Hintergrundspeicher enthält Dateien geholt von
L4
(Festplatte) entfernten Fileservern

L5 entfernter Hintergrundspeicher
(entferntes Filesystem)

5.6.2 Cache Speicher


Cache: Eine kleine, schnelle Speichereinheit, die als Bereitstellungsraum für eine
Teilmenge der Daten von einer größeren, langsameren Einheit dient.

• Fundamentale Idee hinter der Speicherhierarchie:


für jedes k agiert die schnellere, kleinere Einheit auf Schicht k als Cache
für die größere, langsamere Einheit auf Schicht k+1
• Warum funktionieren Speicherhierarchien
Programme tendieren dazu auf Daten der Schicht k häufiger zuzugreifen,
als auf Daten der Schicht k+1. Dies ist bedingt durch das Lokalitätsprinzip.

deshalb okay, wenn Speicher auf Schicht k+1 langsamer und preiswerter
ist.

5.6.3 Caching in der Speicherhierarchie


kleinere, schnellere, teuere Einheiten auf Schicht k cachen Daten von größeren,
langsameren, preiswerteren Einheiten der Schicht k + 1.

176
Schlichter, TU München 5.6. SPEICHERHIERARCHIE / CACHES

Teilmenge der Blöcke


Schicht k 4 9 10 3
der Schicht k+1

Daten werden
blockweise kopiert

0 1 2 3

4 5 6 7 Einheiten der Schicht


Schicht k+1 sind in Blöcke
k+1 partitioniert
8 9 10 11

12 13 14 15

Programm braucht Objekt d in Block b

• Cache-Treffer (hit): Programm findet b im Cache der Schicht k, z.B. in Block


10

• Cache-Fehler (miss): b ist nicht auf Schicht k; Cache muss b von Schicht k+1
holen (z.B. Block 8).
wenn Schicht k Cache voll, muss ein Block entfernt werden, z.B. nach LRU.
Dies ist vergleichbar mit der Verdrängung von Seiten.

– Typen von Cache Problemen


Es können unterschiedliche Arten von Problemen unterschieden werden:
∗ kalter Cache: der Cache ist leer
∗ Kapazitätsfehler: resultieren daraus, dass die Summe der aktiven Cache
Blöcke größer ist als der Cache
∗ Konfliktfehler
Caches limitieren meist Platzierungsmöglichkeiten der Blöcke der
Schicht k+1 auf eine 1-elementige Teilmenge der Blöcke der Schicht
k, d.h. die Blöcke von k+1 können nur an bestimmten Stellen im Cache
platziert werden (nicht so bei der Seitenadressierung),
z.B. Block i muss auf Block i mod 4 platziert werden
Konfliktfehler entstehen, wenn der Cache groß genug ist, aber mehrere
Datenobjekte auf denselben Block der Schicht k abgebildet werden.
z.B. Zugriff auf Blöcke 0, 8, 0,8, 0, 8, ... jedesmal ein Fehler

177
Schlichter, TU München 5.6. SPEICHERHIERARCHIE / CACHES

• Beispiele aus der Cache Hierarchie


Caches werden auf unterschiedlichen Ebenen in modernen Rechensystemen
genutzt.

Cache Typ was wird geca- wo wird geca- kontrolliert


ched ched
Register 4 Byte Wort CPU Register Compiler
TLB Address Transla- On-Chip TLB Hardware
tion
L1 Cache 32 Byte Block On-Chip L1 Hardware
L2 Cache 32 Byte Block Off-Chip L2 Hardware
virtual memory 4 KB page Arbeitsspeicher Hardware + BS
buffer cache Teile von Datei- Arbeitsspeicher BS
en
network buffer Teile von Datei- lokale Platte NFS client
cache en
Browser cache Web Seiten lokale Platte Web Browser
Web cache Web Seiten entfernte Server Web Proxy Ser-
Platte ver
TLB ist der Translation Lookaside Buffer zur Beschleunigung der Abbildung
von virtuellen Addressen auf Maschinenadressen.

5.6.4 Realisierung von Caches


Obwohl je nach der Ebene der Cache Hierarchie unterschiedliche Varianten der
Umsetzung existieren, folgen diese doch gemeinsamen allgemeinen Prinzipien.

• Allgemeine Cache Organisation


Angenommen, das Rechensystem hat Arbeitsspeicheradressen mit m bits ⇒ M
= 2m eindeutige Adressen.
Cache ist ein Array von Mengen (S = Anzahl von Mengen).
jede Menge enthält eine oder mehrere Reihen (E = Anzahl von Reihen pro
Menge).
jede Reihe enthält einen Datenblock (B ist Blockgröße pro Reihe).
Cachegröße = B * E * S Bytes. Die Blockgröße ändert sich je nach Ebene in
der Speicherhierarchie. Je weiter oben in der Hierarchie, desto kleiner sind die
Blöcke.

178
Schlichter, TU München 5.6. SPEICHERHIERARCHIE / CACHES

1-gültig Bit t tagbits B = 2b Bytes pro


pro Reihe pro Reihe Cache Block
valid tag 0 1 B-1
E Reihen
set 0
pro Menge
valid tag 0 1 B-1

valid tag 0 1 B-1


S set 1
Mengen
valid tag 0 1 B-1

valid tag 0 1 B-1


set s-1
valid tag 0 1 B-1

• Adressierung von Caches


Die Cache Organisation bedingt eine Strukturierung der Speicheradresse
das Wort an Adresse A ist im Cache, falls die Tagbits einer der gültigen
Reihen der Menge "set Index" den Tag "tag" besitzen
der Wortinhalt beginnt am Offset "block offset" Bytes vom Blockanfang

179
Schlichter, TU München 5.6. SPEICHERHIERARCHIE / CACHES

tag set Index block offset


Adresse A t bits s bits b bits

valid tag 0 1 B-1


set 0
valid tag 0 1 B-1

valid tag 0 1 B-1


set 1
valid tag 0 1 B-1

valid tag 0 1 B-1


set s-1
valid tag 0 1 B-1

Angenommen, wir haben ein System mit CPU, Registern, L1 Cache und
Arbeitsspeicher. Die CPU führt einen Befehle aus, der auf das Speicherwort
w zugreift. w wird vom L1 Cache angefordert. Falls w im L1 Cache vorhanden
ist (Cache Hit), wird w unmittelbar an CPU ausgeliefert. Ansonsten haben wir
einen Cache Miss und die CPU wartet, bis der L1 Cache den Block, der das
Speicherwort w beinhaltet, vom Arbeitsspeicher angefordert und ausgeliefert
bekommen hat. Der Block mit w wird im L1 Cache gespeichert und w wird an
die CPU ausgeliefert. Damit ergibt sich die Folge CPU ⇒ L1 Cache ⇒ ASP.

• Direct-Mapped Cache
Einfachste Art des Caches mit genau einer Reihe pro Menge; Zugriff erfolgt in
der Reihenfolge
Mengenselektion: Benutzung der "set Index" bits zum Bestimmen der
relevanten Menge.
Reihenabgleich: Finden der gültigen Reihe in der selektierten Menge mit
dem richtigen Tag. Da pro Menge nur eine Reihe vorhanden ist, müssen
nur die Tagbits der vorhandenen Reihe mit den Tagbits der Adresse
auf Übereinstimmung verglichen werden. Es ist keine Durchsuchung der
ausgewählte Menge notwendig. Weiterhin muss das "Valid" Bit gesetzt
sein, um anzuzeigen, dass die Reihe gültig ist.

180
Schlichter, TU München 5.6. SPEICHERHIERARCHIE / CACHES

Wortselektion: Benutzung des block offsets zum Bestimmen des relevanten


Wortes.

set 0
3
0 1 2 3 5 6 7
set 1 1 0110 w0 w1 w2 w3
1

2 0110 00001 100


=?
tag set Index block offset
set s-1

Falls Mengenselektion und Reihenabgleich erfolgreich sind und das Gültigbit


gesetzt ist, befindet sich das gewünschte Wort im Cache. Mit Hilfe von
Blockoffset wird das erste Byte des gewünschten Wortes im Cache angesteuert.

• Mengen Assoziativer Cache


Mehr als eine Reihe pro Menge, d.h. E > 1;
Mengenselektion: identisch zu direct-mapped Cache.
Reihenabgleich: Vergleich der Tags für jede gültige Reihe in der
selektierten Menge. Es werden nur die Reihen mit gesetztem Valid Bit
analysiert.
Wortselektion: identisch zu direct-mapped Cache.

set 0

0 1 2 3 5 6 7
set 1 1 1001
1
1 0110 w0 w1 w2 w3
3
2
0110 00001 100
=?
tag set Index block offset

set s-1

Falls Mengenselektion und Reihenabgleich erfolgreich sind und das Gültigbit


gesetzt ist, befindet sich das gewünschte Wort im Cache. Mit Hilfe von
Blockoffset wird das erste Byte des gewünschten Wortes im Cache angesteuert.

181
Schlichter, TU München 5.6. SPEICHERHIERARCHIE / CACHES

Daneben gibt es noch einen voll assoziativen Cache (fully assoziative), der
nur aus einer Menge besteht, die alle Cache Reihen aufnimmt. In diesem
Fall entfällt die Mengenselektion und es werden nur gültige Reihen auf ihre
Übereinstimmung mit den Tagbits überprüft. Voll assoziative Caches sind nur
für sehr kleine Caches geeignet, z.B. Translation Lookaside Buffer (TLB) im
virtuellen Speicher, der Einträge in der Seitenkacheltabelle cached.

5.6.5 Cache freundlicher Code


Die Performanz eines Caches wird anhand der auftretenden Cache Misses und
Cache Hits gemessen. Die Fehlerrate ist der Bruchteil der Speicherzugriffe, die
nicht durch den Cache erfüllt werden können, und somit zu einem Nachladen
eines neuen Blocks in den Cache erfordern.
Fehlerrate = #Cache Misses / # Speicherzugriffe
Neben der Cache Größe und der Blockgröße in den Reihen kann die
Performanz eines Caches durch Cache freundliche Programmierung beeinflusst
werden. Beispielsweise bei einer Matrixmultiplikation kann durch eine günstige
Zugriffsreihenfolge auf die Elemente die Fehlerrate niedrig gehalten werden.

Beispiel: Summe einer Matrix

Betrachten wir 4-Byte Worte. Weiterhin umfasse der Cache nur eine Menge mit
genau einer Reihe.
Ein Cacheblock der Reihe umfasse vier 4-Byte Worte.
pro Matrixelement (vom Typ int) ist ein Wort (d.h. 4 Bytes) notwendig.
die Matrix a[M, N] sei zeilenweise im Speicher abgelegt und passt nicht
vollständig in den Cache. D.h. zunächst alle Elemente der ersten Zeile,
dann die der zweiten Zeile usw. Neben der Summenbildung könnte auch
die Multiplikation zweier Matrizen und die Speicherung der Ergebnisse in
einer dritten Matrix eindrucksvoll die unterschiedlichen Fehlerraten je nach
der Anordnung der Laufschleifen demonstrieren.

• Zeilenweises Aufsummieren
int i, j, sum = 0;
for (i = 0; i < M; i++)
for (j = 0; j < N; j++) sum += a[i][j]
return sum
Fehlerrate der inneren Schleife = 1/4 = 25%. Ausgangspunkt ist ein leerer
Cache. Der Zugriff a[0, 0] führt zum Laden eine Blocks mit den ersten 4

182
Schlichter, TU München 5.6. SPEICHERHIERARCHIE / CACHES

Matrixelementen der 0-ten Zeile in den Cache. Die nachfolgenden Zugriffe auf
a[0, 1], a[0, 2] und a[0, 3] können durch den Cache befriedigt werden. Erst der
Zugriff auf a[0, 4] führt einem Laden eines neuen Blocks in den Cache.

• Spaltenweises Aufsummieren
int i, j, sum = 0;
for (j = 0; j < N; j++)
for (i = 0; i < M; i++) sum += a[i][j]
return sum
Fehlerrate der inneren Schleife = 100%. Beim Zugriff von a[0, 0] werden die
ersten 4 Elemente der ersten Zeile in den Cache geholt. Als nächstes Element in
der inneren Schleife wird a[1, 0] benötigt, was jedoch nicht im Cache ist. Jeder
Zugriff auf eine Matrixelement in der inneren Schleife führt zu einem Cache
Miss.

183
Kapitel 6

Prozesskommunikation

Disjunkte Prozesse, d.h. Prozesse, die völlig isoliert voneinander ablaufen, stellen
eher die Ausnahme dar. Häufig finden Wechselwirkungen zwischen den Prozessen
statt ⇒ Prozesse interagieren. Die Unterstützung der Prozessinteraktion stellt
einen unverzichtbaren Dienst dar. Betrachtet man diese Prozesswechselwirkungen
1
genauer, dann lassen sich 2 grundlegende Interaktionsmuster unterscheiden:
Konkurrenz und Kooperation. Eine Konkurrenzsituation liegt vor, wenn sich
Prozesse gleichzeitig um ein exklusiv benutzbares Betriebsmittel bewerben
⇒ Prozesssynchronisation. Bei Prozesskooperation geht es darum, dass die
beteiligten Prozesse gezielt Informationen untereinander austauschen.

6.1 Fragestellungen
Dieser Abschnitt beschäftigt sich mit den Mechanismen von Rechensystemen
zum Austausch von Informationen zwischen Prozessen.

• Kommunikationsarten.

• nachrichtenbasierte Kommunikation, insbesondere Client-Server-Modell. Die


speicherbasierte Kommunikation, d.h. über gemeinsame Speicherbereiche,
wurde bereits im Zusammenhang mit → Synchronisation (siehe Seite 81) und
Semaphoren behandelt.

• Netzwerkprogrammierung auf der Basis von Ports und Sockets.


1
[nehmer2001 S32]

184
Schlichter, TU München 6.2. EINFÜHRUNG

6.2 Einführung
Prozessinteraktion kann Rechner-lokal und Rechner-übergreifend stattfinden.
Prozesse können auf vielfältige Weise Informationen austauschen.

6.2.1 Kommunikationsarten

Prozesskommunikation

breitbandig schmalbandig

explizit explizit Ereignisse


implizit asnychron snychron
Alarme
1:1 1:1 RPC Signale

n:1 1:m RMI

1:m n:m

n:m Ströme

Die Bandbreite des Kommunikationskanals bestimmt die Datenrate, in der Daten


zwischen Prozessen ausgetauscht werden können. Breit- bzw. schmalbandig
bezieht sich hier auf die Menge der ausgetauschten Information und nicht
auf die Bandbreite des darunterliegenden Kommunikationsnetzes. n:1 wird bei
explizit synchroner Kommunikation nicht separat aufgeführt; es ist im Grunde ein
Spezialfall von n:m. .
Ströme wurden asynchron realisiert. Während bei der Art n:m (bzw. 1:1, 1:n,
n:1) die einzelne Nachricht im Vordergrund steht, geht es bei Ströme um
die Übermittlung eines Daten-/Zeichenstroms. Der Sender kann in mehreren
Operationen Zeichen auf den Strom legen (jeweils eine Menge an Zeichen,
die unterschiedlich sein kann). Diese Grenzen sind für den Empfänger
nicht mehr ersichtlich; er erhält nur eine Sequenz an Zeichen. Ströme
werden typischerweise als asynchroner Nachrichtenaustausch auf Ebene der
Netzprotokolle realisiert

185
Schlichter, TU München 6.2. EINFÜHRUNG

Schmalbandige Kanäle

Schmalbandige Kanäle werden im Betriebssystem zum Melden von Ereignissen


oder für die Synchronisation unterstützt. Übertragung von wenigen Bits an
Information, z.B. Setzen von Flags

• Dienste des Betriebssystems


Melden von Ereignissen,
Warten auf Ereignisse,
Ereignisverwaltung.
Unterbrechungsereignisse und deren Verwaltung in einem Betriebssystem
wurden bereits eingeführt.

• Beim Ablauf von Prozessen können Alarme entstehen (z.B. arithmetische Alar-
me). Da das BS keine genauen Kenntnisse über den internen Berechnungszu-
stand eines Prozesses besitzt, kann man mit den allgemeinen Standardalarmbe-
handlungen des BS einen Prozess höchstens abbrechen. Es ist somit sinnvoll,
die Alarmbehandlung dem Prozess selber zu überlassen.

• Die Alarme werden über Namen identifiziert, die im BS vereinbart sind. Das
BS stellt Dienste zur Zustellung von Alarmen zur Verfügung. Bemerkung:
schmalbandige Informationskanäle sind für den Bereich der Datensicherheit
problematisch, da sie schwierig zu beherrschen sind. Über diese Kanäle können
sich Angreifer Informationen über das System beschaffen und ausnutzen.
Beispiel: Einloggen unter Solaris 7.0 liefert bereits nach Eingabe der Kennung
Informationen, dass diese Kennung korrekt ist. Lässt sich für einen Passwort-
Cracking-Angriff ausnutzen.
Im folgenden werden wir uns vertiefend mit breitbandigen Kommunikations-
formen beschäftigen, und zwar nicht nur im lokalen Bereich, sondern auch im
verteilten Bereich.

Implizite Kommunikation

Implizite Kommunikation ist eine breitbandige Kommunikationsform. Die


Kommunikation erfolgt über einen gemeinsamen Speicher (Dateien, Register,
Datenstrukturen). Ein Beispiel dafür sind Pipes in Unix.

• Die Kommunikation findet ohne direkte Unterstützung und ohne Kenntnis des
BS statt.

• Vorteil: einfach und schnell (kein Kopieren zwischen Adressräumen).

186
Schlichter, TU München 6.2. EINFÜHRUNG

• Nachteil:
a) gemeinsame Bereiche sind nicht immer vorhanden: z.B. in physisch
verteilten, vernetzten Systemen gibt es i.d.R. keinen gemeinsamen
Speicher. Eine Ausnahme bilden sogenannte DSM (Distributed Shared
Memory) Realisierungen.
b) gegebenenfalls aufwendiges busy waiting ⇒ Mischform: Ereigniszustel-
lung, d.h. schmalbandige Kommunikation, die das Vorhandensein von Da-
ten signalisiert.
• Implizite Kommunikationsformen
Verschiedene Formen der impliziten Kommunikation
1:1 ein Puffer pro Sender/Empfänger-Paar
n:1 n Sender senden Nachrichten an einen Empfänger, z.B.
Sender: Prozesse senden Druckaufträge
Empfänger: Drucker-Server

1:m Mitteilung an alle Prozesse (Broadcast, Multicast);

Broadcast: z.B. Erfragen, wo ein spezieller Dienst angeboten wird;


Shutdown Message an alle Rechner.

Multicast: z.B. Nachricht an Gruppe gleichartiger Server. Broadcast und


Multicast ist in lokalen Netzen mit busartigen Medien (z.B. Ethernet)
sehr einfach zu realisieren; dort hören alle angeschlossenen Rechner das
Medium ab.

n:m n Erzeuger schreiben in Puffer und m Verbraucher lesen aus Puffer.

n:m Kommunikationsform ist beispielsweise sinnvoll, wenn eine Menge


gleichartiger Dienste zur Verfügung steht, und ein Auftrag von einem
beliebigen dieser Dienstanbieter erledigt werden kann.

187
Schlichter, TU München 6.2. EINFÜHRUNG

S1 S1 Sn S1 Sn

prozess- prozess-
spezifischer spezifischer
Briefkasten
oder oder
(mail box)
zentraler zentraler
Puffer Puffer

E1 E1 E1 Em

1:1 Kommunikation n:1 Kommunikation n:m Kommunikation

Si i-ter Senderprozess
Ei i-ter Empfängerprozess

Explizite Kommunikation

Diese Kommunikationsart wird realisiert durch den Austausch von Nachrichten


("message passing") ⇒ nachrichtenbasierte Kommunikation. Die Nachrichten-
kommunikation ist immer dann die geeignete Kommunikationsform, wenn die
beteiligten Prozesse in disjunkten Adressräumen liegen, und damit keine Mög-
lichkeit haben, auf einen gemeinsamen Speicher zuzugreifen.

• Betriebssystem enthält einen Nachrichtendienst ND (das Kommunikationssy-


stem), der den Austausch der Nachrichten zwischen Prozessen realisiert. ND
unterstützt 2 Systemdienste:
send (E: process, m: message)
receive (S: process, m: message)
Mittels send wird eine Nachricht m für den Empfänger E an den
Nachrichtendienst ND übergeben. Mit receive entnimmt ein Empfänger E die
Nachricht m, die vom Sender S gesandt wurde, von ND. Der Absender wird
gewöhnlich in der Nachricht m codiert.

• prinzipieller Ablauf
Der Nachrichtendienst ND ist meist Teil des Betriebssystemkerns.

188
Schlichter, TU München 6.2. EINFÜHRUNG

Nachricht m Nachricht m
Sende Nachrichten Empfänger
prozess S dienst ND prozess E
send receive

Falls die Prozesse auf unterschiedlichen Rechnern sind, sind die Nachrichten-
dienste der beteiligten Betriebssysteme involviert. In diesem Fall findet eine
Kommunikation zwischen den beiden Nachrichtendiensten statt.

• Aufbau einer Nachricht


Eine Nachricht besteht aus 2 grundlegenden Komponenten:
Nachrichtenkopf: Verkehrsinformation, z.B. Sender- und
Empfängeridentifikation
Nachrichteninhalt: Nutzlast (payload)
• explizite Kommunikation ist besonders geeignet in verteilten, vernetzten Syste-
men. Die nachfolgenden Abschnitte werden sich mit der nachrichtenbasierten
Kommunikation, insbesondere in verteilten Systemen beschäftigen.

6.2.2 Verteilte Systeme


Bisher haben wir uns mit systemnahen Konzepten von zentralen Systemen
beschäftigt. Seit Ende der 80er Jahre haben jedoch verteilte Systeme rapide an
Bedeutung gewonnen. Die Verteilung bezieht sich sowohl auf die Verteilung
von Hardwarekomponenten (Rechner, Peripherie), als auch auf die Verteilung
von Daten und Verarbeitung. Im letzteren Fall spricht man von einer verteilten
Anwendung, d.h. eine Anwendung besteht aus mehreren kooperierenden
Teilkomponenten, die auf verschiedenen Rechnern ausgeführt werden.

• Ansätze zur Kopplung von Recheneinheiten

Vielfach CPU-
Systeme

eng gekoppelt lose gekoppelt

Multiprozessoren Multicomputer verteiltes System

189
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

Multiprozessor Multicomputer verteiltes System


Konfiguration nur CPU CPU, Ar- kompletter
beitsspeicher, Rechner
Netzschnittstelle
Peripherie gemeinsam gemeinsam, au- getrennt
ßer Festplatte
Ort gemeinsames gemeinsamer weltweit verteilt
Gehäuse Raum
Kommunikation gemeinsamer direkte Verbin- Netzwerk
Arbeitsspeicher dung
Betriebssystem ein gemeinsames getrennt, jedoch getrennt, viel-
BS gleicher Typ fach unterschied-
lich
Verwaltung eine Organisati- eine Organisati- viele Organisa-
on on tionen
Die Einteilung in Multicomputer oder verteiltes System hängt etwas von der
verwendeten Betrachtungsweise ab.

6.3 Nachrichtenbasierte Kommunikation


Bei nachrichtenbasierter Prozessinteraktion tauschen Prozesse gezielt Informatio-
nen durch Verschicken und Empfangen von Nachrichten aus; ein Kommunikati-
onssystem unterstützt an der Schnittstelle wenigstens die Funktionen send und
receive. Nachrichtenkommunikation ist die natürliche Form der Prozessinterak-
tion in Rechnernetzen. Prozesse, die auf verschiedenen Rechnerknoten platziert
sind, müssen ein physisches Übertragungssystem benutzen, um miteinander in
Kontakt zu treten.

6.3.1 Elementare Kommunikationsmodelle


Klassifikationsschema für die Nachrichtenkommunikation anhand von 2 Dimen-
sionen:
generelles Muster der Nachrichtenkommunikation.

zeitliche Kopplung der beteiligten Prozesse.

190
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

Klassifikationsschema

• Elementare Kommunikationsmuster sind Meldung ("signal") und Auftrag


("request").

Meldung: Einweg Nachricht vom Sender zum Empfänger (unidirektional).


Die entsprechende Nachrichtentransaktion beginnt mit dem Versenden
der Nachricht und endet mit der Übergabe an den Empfänger. Zu einer
Meldung gehört nicht die anschließende Verarbeitung der Nachricht durch
den Empfänger.

Auftrag: Zweiweg Nachricht zwischen Sender und Empfänger (bidirektio-


nal). Sie beginnt mit dem Versenden eines Auftrags an den Empfänger und
endet mit der Übergabe einer Erfolgsbestätigung über den durchgeführ-
ten Auftrag an den Sender. "Dazwischen liegt die Auftragsbearbeitung auf
Empfängerseite, die weitere Nachrichten zur Übertragung der Eingabepara-
meter bzw. zur Rückübertragung des Resultates auslösen kann. Im einfach-
sten Fall genügen für einen Auftrag 2 Nachrichten: die Auftragsnachricht
und die Resultatnachricht, die gleichzeitig als Quittung dient. Ausbleibende
Quittungen können mittels Timeouts erkannt werden; sie sind gleichbedeu-
tend mit negativen Quittungen, die auf Senderseite als nicht durchgeführter
Auftrag interpretiert wird."
• Synchronität definiert den Kopplungsgrad zwischen Prozessen bei der
Durchführung einer Nachrichtentransaktion:

asynchron: Entkopplung des Senders und Empfängers. "Dies bedeutet,


dass ein Sender Nachrichtentransaktionen in schnellerer Folge für einen
Empfänger erzeugen kann, als dieser in der Lage ist, sie zu bearbeiten.
Asynchrone Nachrichtenübertragung erfordert deshalb die Pufferung von
Nachrichten auf dem Übertragungswege zwischen Sender und Empfänger.
Parallelarbeit ist möglich."

synchron: beide Prozesse werden zur Nachrichtenübertragung


synchronisiert.

191
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

Es ist auch möglich das Merkmal Synchronität nicht auf die Nachrichtentrans-
aktion, sondern getrennt auf Sender und Empfänger anzuwenden. Damit las-
sen sich asynchrone und synchrone Formen des Nachrichtenversands und -
empfangs beliebig kombinieren.

Meldung

• Asynchrone Meldung
Sender wird lediglich bis zur Ablieferung der Meldung an das Nachrichtensy-
stem (Kommunikationssystem) blockiert.

Sender S Nachrichtendienst ND Empfänger E

send
Meldung
receive

Zeit

– Nachrichtendienst des Betriebssystems puffert Nachricht;


Sender S kann seine Ausführung fortsetzen, sobald Nachricht N in den
Nachrichtenpuffer des ND eingetragen ist.
S wartet nicht, bis E die Nachricht empfangen hat.
– Empfänger E zeigt durch receive an, dass er am Empfang der Nachricht N
interessiert ist.
Empfänger wird blockiert, bis Sender Nachricht bereit stellt.

• Synchrone Meldung
Sender und Empfänger von Meldungen sind zeitlich gekoppelt.

192
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

Sender S Nachrichtendienst ND Empfänger E

send Meldung

receive

Quittung

Zeit

Über die Ablieferung der Nachricht wird der Sender durch eine Quittungsnach-
richt informiert, die zur Aufhebung der Blockade des Senders führt.

– Rendezvous-Technik: Sender und Empfänger stellen vor Austausch der


eigentlichen Meldung die Sende- und Empfangsbereitschaft her. In diesem
Fall braucht die Nachricht nirgends gepuffert werden, sondern sie kann direkt
vom Adressraum des Senders in den Adressraum des Empfängers übertragen
werden. Das Erreichen des Rendezvous-Punktes definiert den Zeitpunkt, zu
dem Sender- und Empfängerseite wechselseitiges Einverständnis über das
Vorliegen der Sende- und Empfangsbereitschaft erklärt haben.

Auftrag

• Synchroner Auftrag
Bearbeitung der Nachricht durch Empfänger und Senden der Resultatnachricht
sind Teil der Nachrichtentransaktion.

193
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

Sender S Nachrichtendienst ND Empfänger E

send Auftrag receive

Auftrags
bearbeitung
Resultat reply

Zeit

Synchrone Aufträge schränken die Parallelarbeit zwischen Sender und Emp-


fänger noch stärker ein als synchrone Meldungen, da die zeitliche Kopplung
auch die Bearbeitung der Nachricht umfasst. Diese Kommunikationsform wird
gerade im Zusammenhang mit dem Client-Server Modell sehr oft verwendet.
Das RPC-Konzept ("Remote Procedure Call") ist eine sprachbasierte Variante
der synchronen, auftragsorientierten Kommunikation.

• Asynchroner Auftrag
Auftrag und Resultat werden als Paar unabhängiger Meldungen verschickt.

194
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

Sender S Nachrichtendienst ND Empfänger E

send Auftrag receive

Auftrags
bearbeitung
receive Resultat reply
result

Zeit

Zwischen send und receive result kann der Sender u.U. noch weitere
Aufträge versenden (an den gleichen oder andere Empfänger).

Vorteile/Nachteile asynchrones Senden

• Vorteile asynchrones Senden

– nützlich für Realzeitanwendungen. Speziell in Situationen, bei denen


sendender Prozess nicht blockiert werden darf.
– ermöglicht parallele Abarbeitung durch Sender und Empfänger.
– anwendbar zum Signalisieren von Ereignissen.

• Nachteile asynchrones Senden

– Verwaltung des Nachrichtenpuffers durch BS erforderlich. Überlauf des


Puffers, Zugriffsprobleme, Absturz von Prozessen.
– Benachrichtigung des Senders S im Fehlerfall und Behandlung von Fehlern
ist problematisch. Warum: Sender hat weitergearbeitet, gegebenenfalls
bereits terminiert; Nachricht kann u.U. nicht mehr wiederholt werden. Ein
Zurücksetzen der Prozesse kann zum Dominoeffekt führen, da Empfänger
von Nachrichten selbst wieder zum Sender geworden sein können.

195
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

– Entwurf und Nachweis der Korrektheit des Systems ist schwierig. Auftreten
von Fehlern abhängig von Pufferinhalten und dem Zeitverhalten des
verteilten Systems (Last des Kommunikationssystems).

6.3.2 Erzeuger-Verbraucher Problem


Auf der Basis der nachrichtenbasierten Kommunikation wird das Erzeuger-
Verbraucher Problem mit Hilfe von send und receive Operationen realisiert.
Erzeuger S:
while (true) {
produziere Dateneinheit;
send (E, Dateneinheit);
}
Verbraucher E:
while (true) {
receive (S, Dateneinheit);
verbrauche Dateneinheit;
}
Es existiert kein gemeinsamer Speicherbereich, der bzgl. der Zugriffe von
Erzeuger und Verbraucher synchroniert werden muss. Die Synchronisation von
Erzeuger und Verbraucher erfolgt durch das Kommunikationssystem selbst. Es
sind keine Semaphore notwendig.

6.3.3 Modellierung durch ein Petrinetz


Petri-Netze dienen häufig zur Modellierung von Kommunikationsabläufen,
sogenannten Kommunikationsprotokollen. Sie ermöglichen die Analyse der
Protokolle, z.B. Erkennung von Verklemmungen. Modellierung einer synchronen
Kommunikation:

196
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

Sendebereit

send receive
message message
buffer full
Prozess 1 wait Prozess 2
for message
ack. received

receive
send
ack.
ack.

buffer full

ack. received ack. sent

Problem: unendliches Warten

Dies trifft auf, wenn das Acknowledgement nicht gesendet wird oder verloren
geht. Pragmatische Lösung mit Hilfe von Timeouts

• Sender bzw. Empfänger warten nur eine festgelegte Zeit, Sender: falls kein
Acknowledgement (Quittung) eintrifft, z.B. erneutes Senden.

• Probleme dabei? u.a. Duplikate müssen vom Empfänger erkannt werden;


gesendete Nachrichten kommen zu spät an, sind veraltet etc. Gleiche Probleme
auch in Rechnernetzen: dafür gibt es Protokolle, die die Abläufe genau regeln.
Sequenznummern können als Nachrichtenidentifikatoren dienen.

6.3.4 Ports
Bisher wurde davon ausgegangen, dass ein Prozess eine Nachricht mittels
receive in seinen Adressraum entgegennehmen kann. Dazu wurde jedem
Prozess ein eigener Nachrichtenpuffer für neu eingetroffene, jedoch noch nicht
abgelieferte Nachrichten zugeordnet. Bisher bestand zwischen Sender und
Empfänger eine feste Beziehung, die über Prozessidentifikatoren (z.B. Namen
oder Nummer) hergestellt wurde. Nachteile

197
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

Prozessnummern ändern sich mit jedem Neustart.


Prozessnamen sind nicht eindeutig, z.B. falls Programm mehrmals gestartet
wurde.
⇒ Deshalb Senden von Nachrichten an Ports. Sie stellen Endpunkte einer
Kommunikation dar. Sie können bei Bedarf dynamisch eingerichtet und gelöscht
werden. Dazu existieren folgende Funktionen:
portID = createPort();
deletePort(portID);
send([Link], message);
receive(portID, message);
Mittels createPort wird ein neuer Kommunikationsendpunkt eingerichtet und
mit dem Adressraum des Prozesses (z.B. Empfänger E) verbunden. Andere
Prozesse, z.B. Sender S, kann nun Nachrichten an den Port des Empfängers
senden. Die receive Operation benötigt nun den Parameter portID zur
Selektion des Ports. Ports sind eine logische Abstraktion der Adressräume; sie
repräsentieren keine physischen Ports (z.B. serieller oder paralleler Anschluss).
Der Port agiert hier wie eine Warteschlange für den Empfänger E; die
Auslieferung der Nachricht kann willkürlich, festgelegt durch die Reihenfolge
des Eintreffens der Nachrichten, oder festgelegt durch die Nachrichtenprioritäten
erfolgen.

• ein Port ist mit dem Adressraum des zugehörigen Prozesses verbunden.

• der Empfängerprozess kann sender-spezifische Ports einrichten. Jedem Port


kann ein eigener Thread zugeordnet werden, der die Nachrichten an diesen
Port bearbeitet. Im Ruhezustand ist kein Port eingerichtet, d.h. der Empfänger
kann nur über den fest mit seinem Adressraum assoziierten Nachrichtenpuffer
angesprochen werden.

• ein Rechner mit einer IP-Adresse unterstützt mehrere tausend Ports. Für das
TCP-Protokoll sind es 65 535 unterstützte Ports.

• der Name des Ports ist für einen Rechner eindeutig. Ein Betriebssystem
verwaltet eine bestimmte Anzahl von Ports, die es entweder fest oder
dynamisch verschiedenen Protokollen bzw. deren zugehörigen Applikationen
zuordnen kann.

• die Portnummern 1 - 1023 sind fest reserviert für bestimmte Protokolle (bzw.
deren Applikationen).

• Übersicht: fest zugeordnete Ports

198
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

Protokoll Port Beschreibung


FTP 21 Kommandos für Dateitransfer (get, put)
Telnet 23 interaktive Terminal-Sitzung mit entfern-
tem Rechner
SMTP 25 Senden von Email zwischen Rechnern
time 37 Time-Server liefert aktuelle Zeit
finger 79 liefert Informationen über einen Benutzer
HTTP 80 Protokoll des World Wide Web
POP3 110 Zugang zu Email durch einen sporadisch
verbundenen Client
RMI 1099 Zugang zum Registrieren von entfernten
Java Objekten.
Offene Ports sind ein Sicherheitsrisiko, da darüber von außen Angriffe gestartet
werden können. Deshalb gehen Betriebssystemhersteller den Weg, dass nur
diejenigen Ports aktiviert sind, die für den aktuellen Betrieb notwendig sind.
Nutzer müssen Ports meist manuell aktivieren. Bemerkung: breitbandige,
verbindungsorientierte Kommunikation kann auch für Angriffe in vernetzten
Systemen ausgenutzt werden. Ein Beispiel aus der Vergangenheit: Angriffe
auf Yahoo und [Link]. Aufbau einer Vielzahl Port-Verbindungen,
Übertragung großer Datenmengen (1 GB) führte zum Lahmlegen des Dienstes
("Denial of Service").

6.3.5 Kanäle
Bisher wurde von einer verbindungslosen Kommunikation ausgegangen, d.h. eine
Nachricht kann an einen Port geschickt werden. Bei einer verbindungsorientierten
Kommunikation muss zuerst eine logische Verbindung zwischen den Kommuni-
kationspartner eingerichtet werden ⇒ Kanal ("socket").

• Einrichtung eines Kanals zwischen Ports, d.h. Verknüpfen zweier Ports.

• bidirektionale Übertragung über Kanäle. Ports sind nicht mehr nur Empfangs-
stellen für Nachrichten, sondern sie dienen auch als Quellen. Damit sind kom-
plexere Auftragsbeziehungen zwischen den Kommunikationspartnern möglich.
Beispielsweise müssen nicht alle benötigten Daten in der Auftragsnachricht
mitgeschickt werden, sondern sie können bei Bedarf vom beauftragten Prozess
angefordert werden.

• Die Sende- bzw. Empfangsoperation bezieht sich auf die lokale PortID;

199
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

send(local portID, message);


receive(local portID, message);
• TCP/IP unterstützt verbindungsorientierte Kommunikation.

6.3.6 Ströme
Ströme (engl. streams) sind eine Abstraktion von Kanälen. Sie verdecken die
tatsächlichen Nachrichtengrenzen. Ein Sender schickt mittels send-Operationen
Nachrichten an den Empfänger. Die Nachrichten werden jedoch logisch zu
einem Bytestrom vereinigt, dem man auf Empfangsseite die Nachrichtengrenzen
nicht mehr entnehmen kann. Der Empfänger kann den Bytestrom in Portionen
verarbeiten, ohne sich an den ursprünglichen Nachrichtengrenzen zu orientieren.

send (120 Bytes)


send (74 Bytes)
Sender send (233 Bytes)
Strom receive (50 Bytes)
receive (377 Bytes)

Empfänger
1 Byte

• BS-Dienste: Verbindungsauf- und -abbau, schreiben in Strom, lesen aus Strom.

• Dienste für Dateizugriffe oder Zugriffe auf Geräte: spezielle Ausprägung der
stromorientierten Kommunikation.

• I/O in Java basiert auf Ströme.


Klasse [Link] zum Schreiben von Daten
Klasse [Link] zum Lesen von Daten
Spezialisierungen z.B. durch FileOutputStream, BufferedOutputStream oder
FileInputStream.

6.3.7 Pipes
Realisierung von Strömen über Pipe-Konzept (z.B. in Unix, Windows); Strom
zwischen 2 Kommunikationspartnern
unidirektional

200
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

FIFO-artiger Datentransfer mit Operationen: open pipe, read, write. Die


Operationen werden über Systemaufrufe realisiert.
gepuffert und zuverlässig.
Pipes können als Dateien ohne Plattenbeteiligung betrachtet werden.

Prozess 1 Prozess 2

Schreiben Lesen

Ordnung der Zeichen bleibt erhalten (Zeichenstrom)


Blockieren bei voller Pipe (write) und leerer Pipe (read)

• Beispiele für Unix Pipes


ls -l | head
grep "name" [Link] | sort | more
cat [Link] | awk ’{print $1}’ | more
• Prinzipieller Aufbau
Der pipe-Systemaufruf erzeugt ein i-node Objekt sowie 2 File-Objekte. Damit
können Prozesse mit read() und write() Systemaufrufen darauf zugreifen. Der
Aufbau orientiert sich an Linux.
struct pipe_inode_info {
wait_queue_head_t wait; /* Warteschlange blockierter
Prozesse, die auf Pipe zugreifen wollen */
char *base; /* Adresse des Kernel Buffers */
unsigned int len; /* Anzahl geschriebener, aber noch nicht
gelesener Bytes */
unsigned int start; /* Leseposition im Buffer */
unsigned int readers; /* Anzahl lesender Prozesse */
unsigned int writers; /* Anzahl schreibender Prozesse */
unsigned int waiting_writers;
unsigned int r_counter; /* Anzahl der Prozesse, die auf
neue Zeichen in der Pipe warten */
unsigned int w_counter; /* Anzahl der Prozesse, die
Zeichen in die Pipe schreiben möchten */
}
Zugriffe auf Pipe müssen intern über Semaphore geregelt werden. "Jeder
Schreib-/Lesevorgang bzgl. der Pipe beantragt zunächst den Zugang über ein
Semaphore."

201
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

• Beispielnutzung einer Pipe


Die Pipe wird im Vaterprozess angelegt, der anschließend 2 Kindprozesse
startet, die über eine Pipe kommunizieren.
Systemaufruf dup() ermöglicht Umlenkung von Standard-Ein/-Ausgabe
auf Pipe
main (int argc, char *argv[]) {
int fhandle[2]; int rc;
pipe(fhandle); /* erzeugt Pipe*/
rc = fork();
if (rc ==0) {
close(0); /* Schließen Standard Eingabe */
dup(fhandle[0]); /* Umlenken von fhandle[0] auf
Standard Eingabe */
close(fhandle[0]); /* Schließen der nicht mehr
benötigten fhandle[0] */
/* der nun gestartete Prozess liest bei Zugriff auf
Standard Eingabe aus der Pipe */
rc = execl("kind1", "Kind 1", "\0");
} else {
rc = fork(); /* Vaterprozess */
if (rc == 0) {
close(1); /* Schließen Standard Ausgabe */
dup(fhandle[1]); /* Umlenken von fhandle[1] auf
Standard Ausgabe */
close(fhandle[1]); /* Schließen der nicht mehr
benötigten fhandle[1] */
/* der nun gestartete Prozess schreibt bei
Zugriff auf Standard Ausgabe in die Pipe;
zwischen den Kindern ist dadurch eine
unidirektionale Kommunikation mittels Pipes
erzeugt worden */
rc = execl("kind2", "Kind 2", "\0");
}
sleep(1);
exit(0);
}
sleep(1) vor exit(0)? Damit wird sichergestellt, dass die Kinderprozesse vor
Terminierung des Vaterprozesses aktiv werden können.

– Kinderprozesse
Kind 1 liest aus der Pipe, während Kind 2 in die Pipe schreibt.

202
Schlichter, TU München 6.3. NACHRICHTENBASIERTE KOMMUNIKATION

/* Kind 1 */
main (int argc, char *argv[]) {
char buffer[100];
read(0, buffer, 28); /* Prozess liest von Pipe */
write(1, buffer, 28); /* schreibt auf Standard Aus */
exit(0);
}
/* Kind 2 */
main (int argc, char *argv[]) {
write(1, "Dies erscheint in der Queue\n", 28);
exit(0);
}
Das Lesen der pipe erfolgt durch read(fhandle[0], block, anzahl). Ist
die Pipe beim read-Aufruf leer, so wird der Prozess blockiert.

• Named Pipes
Problem: nur Prozesse, die über fork() eng miteinander verwandt sind, können
im Beispielprogramm kommunizieren.
Einführung von Named Pipes, die mittels mknod erzeugt werden.
ermöglicht die Kommunikation zwischen Prozessen, die nicht miteinander
verwandt sind.
main (int argc, char *argv[]) {
int rc;
mknod("myfifo", 0600, S_IFIFO);/* 0600 spezifiziert die
Zugriffsrechte.*/
if (rc == 0) {
int fd;
fd = open("myfifo", O_WRONLY);
write(fd, "Satz 1\n", 7);
close(fd);
exit(0)
} else {
int fd;
char block[20];
fd = open("myfifo", O_RDONLY);
rc = read(fd, block, 7);
write(1, ":", 1);
if (rc > 0) { write(1, block, rc); }
else printf("Fehler: %d\n", rc);
close(fd);
exit(0)
}
}

203
Schlichter, TU München 6.4. CLIENT-SERVER-MODELL

6.4 Client-Server-Modell
Client-Server Modell basiert i.a. auf der Kommunikationsklasse der synchronen
Aufträge. Server stellen Dienste zur Verfügung, die von vorher unbekannten
Clients in Anspruch genommen werden können. Der Client ruft die Operation
eines Servers auf; nach Ausführung der Operation wird das Ergebnis an Client
übergeben. Während der Ausführung der Operation wird Ablauf des Client meist
unterbrochen. Eine leere Antwort ist möglich, falls die Operation kein Ergebnis
liefert (z.B. Eintrag einer Informationseinheit in eine Datenbank).

• Client-Server Architektur

Client C Server S

Auftrag

blockiert
Ausführung
Resultat

Zeit

• Definitionen

– Definition: Client
Ein Client ist eine Anwendung, die auf einer Clientmaschine läuft und i.a.
einen Auftrag initiiert, und die den geforderten Dienst von einem Server
erhält.

Clients sind meist a-priori nicht bekannt. Clients sind oft Benutzerprozesse,
die dynamisch erzeugt und gelöscht werden.
– Definition: Server
Ein Server ist ein Subsystem, das auf einer Servermaschine läuft und einen
bestimmten Dienst für a-priori unbekannte Clients zur Verfügung stellt. Es
existiert eine einfache n:1 Auftragsbeziehung zwischen den Clients und
einem Server.

204
Schlichter, TU München 6.4. CLIENT-SERVER-MODELL

– Server sind dedizierte Prozesse, die kontinuierlich folgende Schleife


abarbeiten.
while (true) {
receive (empfangsport, auftrag);
führe Auftrag aus und erzeuge Antwortnachricht;
bestimme sendeport für Antwortnachricht;
send (sendeport, resultat);
}
Der Empfangsport ist server-lokal; der Sendeport ist lokal beim Client.
Ein Server kann intern aus einer Menge von Threads aufgebaut sein. Ein
Thread, der sogenannte Listener wartet auf Aufträge. Er verteilt eintreffende
Aufträge an sogenannte Worker-Threads, die die Bearbeitung eines Auftrags
übernehmen. Die Ergebnisse werden direkt vom Worker-Thread an den
Client weitergeleitet.
– Client und Server kommunizieren über Nachrichten, wobei beide Systeme
auf unterschiedlichen Rechnern ablaufen können und über ein Netz
miteinander verbunden sind.

• Beispiele für Dienste (Services), die mittels Server realisiert werden:


Dateidienst, Zeitdienst, Namensdienst.

• Multi-Tier
ein System kann sowohl Client als auch Server sein.

Server
Client Server
Client

– Beispiel

205
Schlichter, TU München 6.4. CLIENT-SERVER-MODELL

Web HTTP cgi


Web Anwendungs
Browser
Server Server
(Applets)

SQL

Daten
bank

• Peer-to-Peer Computing
Es findet keine Unterscheidung zwischen Client und Server statt
⇒ Systeme übernehmen beide Rollen, d.h. sie sind sowohl Client als auch
Server (Peers).
Damit soll der Server-Flaschenhals eliminiert werden.

– Teilnahme an einem P2P-System erfordert explizites Beitreten. Bevor ein


Knoten an einem P2P-System teilnehmen kann, muss er dem Netzwerk
der Peers beitreten. Erst anschließend kann dieser Knoten seine Dienste
bereitstellen, bzw. Dienste anderer Knoten in Anspruch nehmen.
– Feststellung, welche Dienste im P2P-Systeme verfügbar sind
ein Knoten registriert seine Dienste bei einem zentrale Directory-
Service. Ein Knoten, der einen speziellen Dienst in Anspruch nehmen
will, durchsucht zunächst den Directory-Service. Die nachfolgende
Kommunikation erfolgt direkt zwischen Client und Dienstprovider.
es existiert ein Discovery-Protokoll, mit Hilfe dessen ein Client-Knoten
eine Liste möglicher Dienste im P2P-System erstellen kann. Dazu schickt
der Client-Knoten mittels Broadcast eine Anfrage an alle anderen Knoten
des P2P-Systems, um herauszufinden, welche Dienste die jeweiligen
Knoten anbieten. Vorteil dieses Ansatzes ist, dass es keine zentrale Stelle
gibt.
– Beispielsysteme sind Napster und Gnutella. Napster kann der ersten
Kategorie zugeordnet werden; Gnutella der zweiten Kategorie.
– P2P-Systeme wurde in der Vergangenheit häufig im Zusammenhang mit
Musik-Tauschbörsen eingesetzt ⇒ rechtliche Probleme.

206
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

6.5 Netzwerkprogrammierung
Bedingt durch rasche Verbreitung des Internet hat auch das Interesse an Netz-
Anwendungen sehr zugenommen. Netz-Anwendungen sind verteilte Anwendun-
gen, die jeweils aus mehreren Teilkomponenten bestehen und die im Netz verteilt
auf verschiedenen Rechensystemen ausgeführt werden. Teilkomponenten sind
hier nicht einzelne Objekte, sondern komplexe Verarbeitungseinheiten (z.B. ein
Modul bestehend aus einer Menge von Objekten). Eine verteilte Anwendung ist
eine Anwendung A, dessen Funktionalität in eine Menge von kooperierenden Teil-
komponenten A1, .., An, n ∈ IN, n > 1 zerlegt ist;
Jede Teilkomponente umfasst Daten (interner Zustand) und Operationen, die
auf den internen Zustand angewendet werden.

Teilkomponenten Ai sind autonome Prozesse, die auf verschiedenen Rechen-


systemen ausgeführt werden können. Mehrere Teilkomponenten können dem-
selben Rechensystem zugeordnet werden.

Teilkomponenten Ai tauschen über das Netz untereinander Informationen aus.


Die Teilkomponenten können z.B. auf der Basis des Client-Server Modells reali-
siert werden. Beispiele von verteilten Anwendungen sind Softwaresysteme für
verteilte Geldautomaten oder Flugbuchungssysteme. Netzwerkprogrammierung
ist ein Hilfsmittel zur Implementierung verteilter Anwendungen.

6.5.1 Einführung
In Berkeley Unix wurde das Konzept von Sockets eingeführt, um die
Netzwerkprogrammierung zu erleichtern. Sie erlauben jede Netzverbindung
als einen Strom von Bytes zu betrachten, die gelesen bzw. geschrieben
werden können. Ein Socket definiert einen einfachen, bidirektionalen →
Kommunikationskanal (siehe Seite 199) zwischen 2 Rechensystemen, mit Hilfe
dessen 2 Prozesse über ein Netz miteinander kommunizieren können.

207
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

Input Strom

Client Server

Output Strom

Socket Verbindung

Socket Grundlagen

Sockets abstrahieren von den technischen Details eines Netzes, z.B. Übertra-
gungsmedium, 2 Paketgröße, Paketwiederholung bei Fehlern, Netzadressen. An-
fänglich standen Sockets nur in Unix Umgebungen zur Verfügung. In der Zwi-
schenzeit werden sie auch von Windows, dem MacOs und von Java unterstützt.

• Ein Socket kombiniert 2 Ströme, einen Input- und einen Output-Strom.


• Ein Socket unterstützt die folgenden Basisoperationen:
richte Verbindung zu entferntem Rechner ein ("connect").
sende Daten.
empfange Daten.
schließe Verbindung.
assoziiere Socket mit einem Port.
warte auf eintreffende Daten ("listen").
akzeptiere Verbindungswünsche von entfernten Rechnern (bzgl. assoziier-
tem Port).
Die ersten 4 Operationen sind sowohl für den Client als auch den Server
relevant (siehe Java’s Socket Class), während die letzten 3 Operationen nur
für einen Server von Bedeutung sind (siehe Java ServerSocket Class). Die
Endpunkte einer Socket werden durch Ports repräsentiert.

6.5.2 Server Protokoll


Ein Server kommuniziert mit einer Menge von Clients, die a priori nicht bekannt
sind. Ein Server benötigt eine Komponente (z.B. ein → Verteiler-Thread (siehe
2
optisch/elektrisch/Funk, LAN/WAN/WLAN.

208
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

Seite 77)), die auf eintreffende Verbindungswünsche reagiert. Diese Komponente


wird auch Listener genannt. Der Hauptunterschied zwischen Client und Server
bzgl. der Socket-Verbindung liegt darin, dass ein Server die Assoziierung mit
einem Port vornimmt und Verbindungswünsche akzeptiert.

• Informeller Ablauf aus Serversicht

1. Erzeugen eines SocketServer und Binden an einen bestimmten Port. Ein Port
entspricht einer FIFO Warteschlange. Sie sammelt die Verbindungswünsche
der Clients. Die maximale Länge ist abhängig vom Betriebssystem, z.B. 50.
Falls die Warteschlange voll ist, werden keine weiteren Verbindungswünsche
akzeptiert.
2. Warten auf Verbindungswünsche von Clients. Falls der Client bzgl. einer
Socketverbindung autorisiert ist, akzeptiert der Server den Verbindungs-
wunsch. Der Server wird blockiert, bis die accept-Methode des Servers die
Verbindung zwischen Client und Server eingerichtet hat. Die beiden Ströme
der Socketverbindung werden eingerichtet.
3. Austausch von Daten zwischen Client und Server entsprechend einem
wohldefinierten Protokoll (z.B. HTTP).
4. Schließen einer Verbindung (durch Server, durch Client oder durch beide);
weiter bei Schritt 2.

• Programmstück
Socket socket; //reference to socket
ServerSocket port; //the port the server listens to
try {
port = new ServerSocket(10001, ...);
socket = [Link](); //wait for client call
// communicate with client
[Link]();
}
catch (IOException e) {[Link]();}
• Für das Abhören des Ports kann ein eigener Verteiler-Thread spezifiziert
werden; die Bearbeitung übernehmen sogenannte Worker-Threads. Der Unix
FTP Server hat früher für jede Verbindung einen eigenen Prozess erzeugt, was
einen großen Overhead verursacht ⇒ FTP Server konnte deshalb oft nicht mehr
als 400 offene Verbindungen unterstützen, falls noch vernünftige Antwortzeiten
erwartet werden.

209
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

6.5.3 Client Protokoll


Der Client initiiert eine Socket-Verbindung durch Senden eines Verbindungswun-
sches an den Port des Servers.

Informeller Ablauf aus Clientsicht

1. Erzeugen einer Socket Verbindung. Dazu muss die Adresse des Servers (z.B.
Internet-Adresse) und der Port, auf dem der Server wartet, angegeben werden.

2. Austausch von Daten zwischen Client und Server über die Duplex-Verbindung
entsprechend einem wohldefinierten Protokoll (z.B. HTTP).

3. Schließen einer Verbindung (durch Server, durch Client oder durch beide).

Programmstück

Socket connection; //reference to socket


try {
connection = new Socket("[Link]", 10001);
........ // communicate with client
[Link]();
}
catch (IOException e) {[Link]();}

6.5.4 Bidirektionale Stromverbindung


Sockets bestehen aus 2 Strömen für die Duplexverbindung zwischen Client
und Server. Diese beiden Ströme werden automatisch beim Einrichten einer
Socket-Verbindung erzeugt. Durch die Verwendung von Strömen kann dieselbe
Programmiermethode verwendet wie bei I/O, Dateizugriff, etc.

• Schreiben auf Socket


void writeToSocket(Socket sock, String str) throws
IOException {
oStream = [Link]();
for (int k = 0; k < [Link](); k++)
[Link]([Link](k));
}

210
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

• Lesen von Socket


String readFromSocket(Socket sock) throws IOException {
iStream = [Link]();
String str = "";
char c;
while ( (c = (char) [Link]()) != ’\n’)
str = str + c;
return str;
}
Man beachte, dass ein Byte und Char nicht direkt verglichen werden können.
Deshalb muss das Byte in ein Char konvertiert werden. Vom Strom wird jeweils
bis zum nächsten Zeilenende gelesen. Die gelesene Zeile wird als Ergebnis
zurückgegeben.

6.5.5 Java Socket Class


Java unterstützt die beiden grundlegenden Klassen:

[Link] zur Realisierung der Client-Seite einer Socket.

[Link] zur Realisierung der Server-Seite einer Socket.

Client-Seite einer Socket

• Constructor
public Socket(String host, int port)
throws UnknownHostException, IOException
Der Parameter host ist ein Rechnername, z.B. [Link]. Falls der
Domain Name Server den Parameter host nicht auflösen kann, wird die
Exception UnknownHostException ausgelöst. Falls die Socket aus einem
anderen Grund nicht geöffnet werden kann, wird IOException ausgelöst, z.B.
der entfernte Host akzeptiert keine Verbindungen. Es gibt noch eine Reihe
anderer Konstruktoren, z.B.
public Socket(InetAddress host, int port) throws IOException
Das Objekt der Klasse InetAddress umfasst den Rechnernamen und seine IP-
Adresse, d.h. eine Auflösung durch den Domain Name Server ist nicht mehr
notwendig.

211
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

• Information über eine Socket

public InetAddress getInetAddress();


liefert als Ergebnis den Namen und IP-Adresse des entfernten Rechners, zu
dem die Socket-Verbindung existiert.

public int getPort();


liefert als Ergebnis die Nummer des Ports, mit dem die Socket-Verbindung
am entfernten Rechner assoziiert ist.

public int getLocalPort();


liefert als Ergebnis die Nummer des Ports, mit dem die Socket-Verbindung
am lokalen Rechner assoziiert ist.
• Ein-/Ausgabe

public InputStream getInputStream() throws IOException;


liefert den InputStream, von dem Daten gelesen werden können. Er
unterstützt die Methode read zum Lesen der Daten. InputStream ist ein
Basis-Strom, der mit Hilfe von SubClassing spezialisiert werden kann.

public OutputStream getOutputStream() throws IOException;


liefert den OutputStream, in dem Daten geschrieben werden können. Er
unterstützt die Methode write zum Schreiben der Daten. OutputStream ist
ein Basis-Strom, der mit Hilfe von SubClassing spezialisiert werden kann.
Die beiden Methoden stehen natürlich auch auf Server-Seite einer Socket-
Verbindung zur Verfügung.

Server-Seite einer Socket

• Constructor
public ServerSocket(int port)
throws IOException, BindException
erzeugt eine Socket auf Server-Seite und assoziiert sie mit dem Port. Falls
die Socket nicht an den angegebenen Port gebunden werden kann, wird
BindException ausgelöst. Es existieren noch weitere Konstruktoren, z.B.
public ServerSocket(int port, int queueLength)
throws IOException, BindException

212
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

Die Länge der mit dem Port verbundenen Warteschlange wird durch den
Parameter queueLength angegeben.

• Einrichten/Schließen einer Verbindung

public Socket accept() throws IOException


diese Methode blockiert und wartet auf Verbindungswünsche von Clients.

public void close() throws IOException


• Ein-/Ausgabe

public InputStream getInputStream() throws IOException;


liefert den InputStream, von dem Daten gelesen werden können.

public OutputStream getOutputStream() throws IOException;


liefert den OutputStream, in dem Daten geschrieben werden können.

6.5.6 Beispiel - Generische Client/Server Klassen


Das Beispiel zeigt eine allgemeine Client/Server-Anwendung, wobei der
Ausgangspunkt eine generische ClientServer Klasse ist, aus der konkrete Services
abgeleitet werden können.

• ClientServer Klasse
import [Link].*;
import [Link].*;

213
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

public class ClientServer extends Thread {


protected InputStream iStream;
protected OutputStream oStream;
protected String readFromSocket(Socket sock) throws
IOException {
iStream = [Link]();
String str = "";
char c;
while ( (c = (char) [Link]()) != ’\n’)
str = str + c;
return str;
}
protected void writeToSocket(Socket sock, String str)
throws IOException {
oStream = [Link]();
if ([Link]([Link]() - 1) != ’\n’) str = str +
’\n’;
for (int k = 0; k < [Link](); k++)
[Link]([Link](k));
}
}
• EchoServer Klasse
Der EchoServer sendet den String einer Client Anfrage wieder zurück.
import [Link].*;
import [Link].*;

214
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

public class EchoServer extends ClientServer {


private ServerSocket port;
private Socket socket;
public EchoServer (int portNum, int nBackLog) {
try { port = new ServerSocket(portNum, nBackLog);
} catch (IOException e) { [Link](); }
}
public void run() {
try {
[Link]("Echo server at "
+ [Link]() + " waiting for
connections ");
while (true) {
socket = [Link]();
[Link]("Accepted a connection from
" + [Link]() );
provideService(socket);
[Link]();
[Link]("Closed the connection\n");
}
} catch (IOException e) { [Link](); }
}
protected void provideService (Socket socket) {
String str = "";
try {
writeToSocket(socket, "Hello, how may I help you
?\n");
do {
str = readFromSocket(socket);
if ([Link]().equals("goodby"))
writeToSocket(socket, "Goodbye\"n);
else
writeToSocket(socket, "You said ’" + str +
"’\n");
} while (![Link]().equals("goodbye") );
} catch (IOException e) { [Link](); }
}
public static void main (String args[]) {
EchoServer server = new EchoServer(10001, 3);
[Link]();
}
}
• EchoClient Klasse

215
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

import [Link].*;
import [Link].*;

216
Schlichter, TU München 6.5. NETZWERKPROGRAMMIERUNG

public class EchoClient extends ClientServer {


protected Socket socket;
public EchoClient (String url, int port) {
try { port = new Socket(url, port);
[Link]("Client: connected to " + url +
":" + port);
} catch (IOException e) { [Link]();
[Link](1); }
}
public void run() {
try {
requestService(socket);
[Link]();
[Link]("Client: connection closed");
} catch (IOException e) {
[Link]([Link]());
[Link](); }
}
protected void requestService (Socket socket) throws
IOException {
String servStr = readFromSocket(socket);
[Link]("Server: " + servStr);
[Link]("Client: type a line or ’goodbye’ to
quit");
if ([Link](0, 5).equals("Hello")) {
String userStr ="";
do {
userStr = readFromKeyboard();
writeToSocket(socket, userStr + "\n");
servStr = readFromSocket(socket);
[Link]("Server: " + servStr);
} while (![Link]().equals("goodbye"));
}
}
protected String readFromKeyboard() throws IOException {
BufferedReader input = new BufferedReader(new
InputStreamReader([Link]));
[Link]("Input: ");
String line = [Link]();
return line;
}
public static void main (String args[]) {
EchoClient client = new EchoClient("[Link]",
10001);
[Link]();
}
} 217
Kapitel 7

Dateisysteme

Dateisysteme 1 dienen der dauerhaften Speicherung von Programmen und


Daten. Zum Einsatz kommen magnetische und optische Medien, die im
Gegensatz zum Arbeitsspeicher auch nach dem Ausschalten der Rechenanlage
den Datenerhalt sicherstellen. Beispiele von externen Speichermedien sind
Festplatten, Magnetbänder, CD-ROM (wiederbeschreibbar), USB-Sticks und
DVDs. Der schlechten Zugriffszeit externer Speichersysteme (im Vergleich zum
Arbeitsspeicher) steht eine vergleichsweise hohe Kapazität und ein sehr gutes
Preis-Leistungsverhältnis gegenüber. Zentrale Aufgabe des Dateisystems ist es
die besonderen Eigenschaften externer Speichermedien optimal umzusetzen und
Applikationen einen effizienten Zugriff auf die persistent gespeicherten Daten zu
ermöglichen. Es gelten folgende grundlegende Forderungen
a) Speicherung großer Informationsmengen (Video)
b) kein Datenverlust auch bei Prozess- / Systemabsturz
c) nebenläufiger Zugriff durch mehrere Prozesse
Neben Dateisystemen gibt es Datenbanksysteme, die aus einer Menge von
Daten und den zugehörigen Programmen zum Zugriff auf die Daten sowie zur
Kontrolle der Konsistenz bestehen. Der Zugriff auf die Daten erfolgt immer über
Operationen des Datenbanksystems (z.B. auf der Basis von SQL), und nicht direkt
durch die einzelnen Applikationen.

7.1 Fragestellungen
Dieser Abschnitt beschäftigt sich mit den Mechanismen eines Rechensystems zur
dauerhaften (persistenten) Speicherung von Programmen und Daten:
1
[nehmer2001, S 253]

218
Schlichter, TU München 7.2. CHARAKTERISTIKA VON DATEISYSTEMEN

• Charakteristika von Dateisystemen.

• Schichtenmodell eines Dateisystems.

7.2 Charakteristika von Dateisystemen


Jedes Dateisystem unterstützt 2 grundlegende Abstraktionen:

Datei: Behälter für die persistente Speicherung jeglicher Information.


Information können Daten, der Code ausführbarer Programme, aber auch
kontinuierliche Daten wie Videoströme sein. Das Dateisystem bietet
besondere Zugriffsfunktionen an, die der Zugriffscharakteristik externer
Speicher Rechnung tragen.

Verzeichnisse: spezielle Dateien zur Strukturierung externer Speichermedien.

• blockorientierter Datentransfer zwischen externem Speicher und Arbeitsspei-


cher. Aufgrund der hohen Zugriffszeiten bei externen Speichermedien ist ein
kleines Lese- und Schreibgranulat nicht sinnvoll. Daher bilden sogenannte
Blöcke die kleinste Übertragungseinheit.
Typische Blockgrößen: 512 Byte - 4 KByte.
Der Zugriff auf das 1. Byte eines Blocks auf der Festplatte hängt von der
Positioniergeschwindigkeit ab (im Mittel mehrere Millisekunden), während die
Zugriffszeit auf die restlichen Bytes von der Umdrehungsgeschwindigkeit der
Platte abhängt. Zu große Blöcke resultieren in wachsender Information, die
vom Prozess primär nicht angefordert wurde.

• Charakteristika der Dateinutzung (empirisch ermittelt):


a) Dateien sind meist klein (wenige KBytes).
b) Dateien werden häufiger gelesen, seltener geschrieben und noch seltener
gelöscht.
c) vornehmlich sequentieller Zugriff.
d) Dateien werden selten von mehreren Programmen oder Personen
gleichzeitig benutzt.
Datei-Zugriffsoperation werden oft gemäß dieser Charakteristika optimiert. Für
Multimedia verändert sich die Nutzungscharakteristik.

219
Schlichter, TU München 7.3. DATEIEN

große Dateien (mehrere GByte).


gleichmäßige Zugriffsgeschwindigkeit (um Ruckeln zu vermeiden).
notwendige Übertragungsbandbreite. Zum Beispiel ist bei einer unkompri-
mierten Videoaufzeichnung im Format 1024*768 bei 3 Byte pro Pixel und
50 Bildern pro Sekunde eine Übertragungskapazität von 112,5MByte pro
Sekunde notwendig (Datei hat bereits nach einer Minute eine Größe von
6,5 GByte).

7.3 Dateien
Dateien bilden in einem Dateisystem die Behälter für die dauerhafte Speicherung
beliebiger Information. Dabei nutzen nicht nur Benutzerprogramme, sondern auch
die Systemsoftware greift in vielen Fällen auf Dateien zurück. Beispielsweise
wird auch die Auslagerung von Seiten des virtuellen Adressraums über das Datei-
system auf einer sogenannten Auslagerungsdatei (swap Datei) vorgenommen.

• in den meisten Systemen wird eine Datei als eine Folge von Bytes aufgefasst.
Eine Datei beginnt mit dem Byte 0 und endet in Abhängigkeit von ihrer Länge
n mit dem Byte n-1.

• Dateinamen
in manchen Dateisystemen haben Dateinamen die Form "[Link]".
Beispiele für extension: .c, .java, .html, .gif, .pdf, .tex,
.doc, .zip, ....
In einigen Betriebssystemen werden die Datei-Extension sematisch interpretiert
und veranlassen ein bestimmtes Verhalten, z.B. ein Doppel-Click auf eine
".doc"-Datei startet unter Windows die Anwendung Microsoft Word. In
Unix sind Datei-Extensions nur Konventionen. Das Mac Betriebssystem nutzt
keine Extensions, um Applikationen zu triggern; dort wird eine zusätzliche
Ressource-Datei genutzt.

• Dateiaufbau
Die interne Struktur einer Datei hängt von der jeweiligen Nutzung und
Zielsetzung ab, z.B. ASCII Datei besteht aus Zeilen, die mit CR, LF
abgeschlossen sind. MS-DOS verwendet eine Kombination von CR und LF.
Beispiel einer Archivdatei

220
Schlichter, TU München 7.3. DATEIEN

Modulname

Header Datum

Owner
Objekt Modul
Zugriffsrechte
Header
Länge
Objekt Modul

Header

Objekt Modul

• Operationen
Dateisysteme unterstützen die folgenden grundlegenden Systemaufrufe:

open
Öffnen einer Datei; Ergebnis ist ein Dateideskriptor, über den in
nachfolgenden Systemaufrufen auf die Datei zugegriffen werden kann.
Aufruf nach Posix-Standard
int open (
const char *filename,
int flags,
mode_t mode)
flags spezifiziert die Zugriffsart, z.B. lesend, schreibend, erzeugend,
anhängend (append); mode spezifiziert die Zugriffsrechte für neu erzeugte
Dateien. In Windows NT/2000 wird der Systembefehl CreateFile zum Öffnen
einer Datei bzw. zum Erzeugen einer neuen Datei verwendet. Analog zu open
wird als Ergebnis ein Dateideskriptor zurückgegeben (Datentyp Handle). Die
Anzahl der Dateideskriptoren ist beschränkt.

close
Schließen einer Datei; Aufrufparameter ist ein Dateideskriptor. Bei
Terminierung des Prozesses werden alle offenen Dateien automatisch
geschlossen.

221
Schlichter, TU München 7.3. DATEIEN

int read (int fd, char *puffer, int max)


int write (int fd, char *puffer, int n)
max gibt die Anzahl der Bytes an, die ohne Pufferüberlauf gelesen werden
können; read liefert als Ergebnis die Anzahl der erfolgreich gelesenen Bytes.
Daneben gibt es noch weitere Operationen, z.B. Positionieren des Dateizeigers
auf eine bestimmte Position in der Datei (lseek oder SetFilePointer bei
Win32).

– Dateipuffer
Zugriffe auf Dateien erfolgen über einen Dateideskriptor und einen
Dateipuffer.

Dateipuffer
Datei
Deskriptor Dateizeiger

Puffer

Pufferposition

Ortsinformation

Externer Speicher Datei

Die für den lesenden und schreibenden Zugriff notwendigen Informationen


werden in einer eigenen Datenstruktur (Dateipuffer) gespeichert, die
jedem geöffneten Dateideskriptor zugeordnet wird. Diese Datenstruktur
enthält neben der Ortsinformation, die Aufschluss über den physischen
Aufenthaltsort der Datei auf einem externen Speichermedien gibt, einen
Puffer zur Zwischenspeicherung von Daten. Der Puffer beinhaltet eine Kopie
eines bestimmten Dateiausschnitts. Die Position dieser Kopie innerhalb der
Datei speichert der Zeiger Pufferposition. Der Dateizeiger spezifiziert die
aktuelle Lese-/Schreibposition.

222
Schlichter, TU München 7.4. MEMORY-MAPPED DATEIEN

7.4 Memory-Mapped Dateien


Eine Datei oder Teile davon werden in den virtuellen Adressraum eines Prozesses
eingeblendet. Das Dateisystem bestimmt einen hinreichend großen Bereich im
virtuellen Adressraum für den Dateiausschnitt, z.B. zwischen Laufzeitkeller und
Halde. Für diesen Teilbereich müssen entsprechende Seitentabellendeskriptoren
initialisiert werden. Nutzung von "Prefetching", um bereits im Voraus Dateiblöcke
in Seiten zu laden.

1
1
2 1 2 3
3 4
4
4
3

Festplatte

virtueller Speicher des physischer


Prozesses A Arbeitsspeicher

• Lese- und Schreiboperationen, sowohl sequentiell als auch wahlfrei, erfolgen


über virtuelle Adressen. Es werden keine File read/write Operationen mehr
ausgeführt.

• Einblendung immer nur Vielfacher ganzer Blöcke einer Datei.

• veränderte Blöcke werden meist aus Effizienzgründen zu einem späteren


Zeitpunkt zurückgeschrieben. Auf jeden Fall werden die veränderten Blöcke
beim Schließen der Datei auf den externen Speicher zurückgeschrieben.

• gemeinsame Nutzung einer Datei durch mehrere Prozesse möglich. Die


gemeinsame Datei wird jeweils in die Adressräume der beteiligten Prozesse
geladen. Im physischen Arbeitsspeicher befindet sich die Datei mit ihren
Dateiblöcken nur einmal. Die Änderung der Datei durch einen Prozess ist somit
auch für die anderen Prozesse sichtbar.

• Beispiel

– Beispiel der Win32-Programmierschnittstelle:

223
Schlichter, TU München 7.5. VERZEICHNISSE

Handle fh, fmh;


fh = CreateFile(filename, generic_read, .....);
len = GetFileSize(fh, ...);
fmh = CreateFileMapping(fh, Page_readonly, ...);
addr = MapViewOfFile(fmh, File_map_read, ...);
sprintf(addr, "Information für memory-mapped Datei");
fh ist der Datei-Handle auf die geöffnete Datei. Mit Hilfe von
MapViewOfFile wird eine Sicht auf die Datei im virtuellen Adressraum er-
stellt. Der Rückgabewert addr speichert die Anfangsadresse der Datei im
virtuellen Adressraum. In der Regel wählt das Dateisystem den virtuellen
Adressbereich aus.
– Beispiel Unix Solaris
Systemaufruf mmap() spezifiziert eine Datei als memory-mapped Datei;
Datei wird in den virtuellen Adressraum des Prozesses geladen.
bei Aufruf des Datei-Systemaufrufs open; Datei wird als memory-
mapped Datei in den Betriebssystembereich des virtuellen Adressraums
geladen. read/write-Systemaufrufe werden auf dieser memory-mapped Datei
ausgeführt. Unabhängig davon wie eine Datei geöffnet wird, behandelt
Solaris jede Datei als memory-mapped Datei.

7.5 Verzeichnisse
Verzeichnisse (engl. directories) erlauben eine hierarchische Strukturierung des
externen Speichers.

• baumartige Verzeichnisstruktur mit links zwischen Unterbäumen.


• Pfadnamen zur Spezifikation von Dateien und Verzeichnissen. Der vollständige
und eindeutige Namen einer Datei oder eines Verzeichnisses entsteht durch eine
Aneinanderreihung aller Verzeichnisnamen beginnend beim Wurzelverzeich-
nis; Unterscheidung zwischen absoluten und relativen Dateinamen.
• typische Operationen: create, delete, opendir, closedir, readdir, rename, link,
unlink.
• Mögliche Realisierung von Verzeichnissen
als lineare Liste von Dateinamen. Sehr leicht zu realisieren, jedoch
Operationen wie die Erzeugung einer neuen Datei sind aufwändig, da die
gesamte lineare Liste des Verzeichnisses zunächst durchsucht werden muss,
um festzustellen, ob es einen Namenskonflikt gibt. Die Suche nach einer
Datei erfordert linearen Aufwand.

224
Schlichter, TU München 7.6. SCHICHTENMODELL

als Hashtabelle für die Dateinamen. auftretende Hash-Kollisionen müssen


behandelt werden. Falls sich die Anzahl der Dateien im Verzeichnis erhöht,
muss möglicherweise die Hashtabelle erweitert werden.

7.6 Schichtenmodell
Ein Dateisystem kann logisch in 3 Schichten unterteilt werden, die zunehmend
höhere Abstraktionen für die Speicherung persistenter Daten anbieten.

Dateiverwaltung

Blockorientiertes Dateisystem

Datenträgerorganisation

7.6.1 Datenträgerorganisation
Unterteilung des gesamten Datenträgers in Blöcke, die von 0 an aufsteigend
durchnummeriert sind. Das auf MS-DOS aufbauende Dateisystem FAT (Windows
95) verwendet lediglich maximal 16 Bit für eine Blocknummer. Bei einer ur-
sprünglichen Blockgröße von 512 Byte können damit externe Speicher mit bis
zu 32 MByte Speicherkapazität angesprochen werden. Zusammenfassung von
Blöcken zu Clustern (32 KByte), um bis zu 2 GByte große Datenträger zu ad-
dressieren; Cluster sind die kleinste Zuteilungseinheit ⇒ interne Fragmentierung.

• Verwaltung freier und defekter Blöcke.

Defekte
0 0 0 1 0 0 0 0
Blöcke

Block 0 Block 1 Block 2 Block 3 Block 4 Block 5

Freie
0 1 1 0 0 1 0 0
Blöcke

225
Schlichter, TU München 7.6. SCHICHTENMODELL

Eine gängige Realisierung der Listen für freie und defekte Blöcke besteht in
zusammenhängenden Bitvektoren, die auf dem Datenträger selbst gespeichert
werden. Diese Realisierung erlaubt den gleichzeitigen Test von 16, 32 oder 64
Bitpositionen mit Hilfe von Logikoperatoren des Prozessors.

• Blockstruktur

Super- Defekte
Freie Blöcke Block 0 Block 1 Block n
block Blöcke

Der Superblock verwaltet alle essentiellen Informationen über den Datenträge-


raufbau, z.B. eine Magic Nummer für den Typ des Dateisystems, Anzahl der
Blöcke. Aus Sicherheitsgründen wird der Superblock mehrfach, verteilt über
den gesamten Datenträger, repliziert.

7.6.2 Blockorientiertes Dateisystem


Aufteilung des vorhandenen Speicherplatzes eines logisch durchnummerierten
Datenträgers auf mehrere Dateien.

• Dateien besitzen interne Namen.

• keine hierarchische Verzeichnisstruktur. Es existieren keine hierarchischen


Verzeichnisstrukturen, d.h. alle Dateien sind in einer flachen Struktur
unmittelbar über den internen Dateinamen ansprechbar.

• jede Datei besteht aus einer Menge von Blöcken, die relativ zum Dateianfang
nummeriert sind. Die Blöcke können entweder zusammenhängend oder verteilt
über den Datenträger zugeteilt werden. Im ersten Fall kann dies zu externer
Fragmentierung führen. Die interne Fragmentierung hängt von der Blockgröße
ab. Dateien werden immer in Vielfachen von Blöcken belegt.

• wesentliche Operationen:
Erzeugen und Löschen von Dateien
Öffnen und Schließen von Dateien
Lesen und Schreiben von Blöcken

226
Schlichter, TU München 7.6. SCHICHTENMODELL

7.6.3 Dateiverwaltung
Bereitstellung von Dateien und Verzeichnissen; Dateien werden über Namen
identifiziert. Unix verwendet Dateideskriptoren (sogenannte i-nodes), die alle
relevanten Dateiattribute einschließlich einer Indexstruktur für die Lokalisierung
der einzelnen Dateiblöcke enthalten. Die Position der ersten 10 Blöcke (bei
einigen Implementierungen auch 12 Blöcke) einer Datei werden direkt im
Deskriptor gespeichert.

I-Node Schutzbits
Link Count
uid
gid
Größe

Adressen der
ersten 10 Blöcke
(manchmal auch 12 Blöcke)

einfach indirekt
zweifach indirekt
dreifach indirekt

Jeder Datei, auch jedem Verzeichnis ist genau ein i-node zugeordnet. i-node
Nummern werden sequentiell vergeben. Sie sind in einem speziellen Block, dem
Superblock, auf der Festplatte zusammengefasst. i-node Nummer werden nach
der Löschung der zugehörigen Datei wiederverwendet.

• Windows NTFS
Grundeinheit ist ein volume, das nur aus einer Sorte Daten besteht:
Dateien, die durchnummeriert sind.
jede Datei hat eine 64-Bit Nummer, bestehend aus 48 Bit Dateinummer und
16 Bit Sequenznummer. Die Sequenznummer wird nach jedem Löschen
der zur Dateinummer gehörenden Datei inkrementiert, so dass man
zwischen der Referenz zu einer gelöschten Datei und einer aktuellen Datei
unterscheiden kann.
Jedes volume hat eine zentrale Tabelle, die Master File Table (MFT), in der alle
Dateien verzeichnet sind.

227
Schlichter, TU München 7.6. SCHICHTENMODELL

7.6.4 Virtuelles Dateisystem


Moderne Betriebssysteme unterstützen neben dem lokale Dateisystem auch
entfernte Dateisysteme.
Integration auf Nutzerebene mittels eines virtuellen Dateisystems (VFS). Auf
diese Weise wird ermöglicht, dass der Nutzer zwischen den verschiedenen
Dateisystemtypen nahtlos navigieren kann.
bekannter Vertreter: Network File System (NFS). NFS ist ein von Sun
entwickeltes Protokoll zum Zugriff auf entfernte Dateien. Der Nutzer kann
auf entfernte Dateien zugreifen wie auf lokale gespeicherte Dateien, d.h. es
ist kein FTP notwendig. Als Kommunikation wird ein RPC verwendet.

Dateisystem
Schnittstelle

Schnittstelle virtuelles
Dateisystem

Lokales entferntes
Dateisystem Dateisystem

• die oberste Schicht stellt die allgemeinen Zugriffsoperationen wie open, read,
write und close bereit.
• die VFS Schicht ermöglicht die eindeutige Repräsentation einer Datei
über Netzwerkgrenzen hinweg. Die VFS Schicht trennt die generischen
Zugriffsoperationen von den aktuellen Implementierungen. Dateien werden mit
Hilfe eines Deskriptors, dem vnode, netzwerkweit eindeutig charakterisiert.
Für das lokale Dateisystem werden vnodes auf den entsprechenden inode
abgebildet. Falls der vnode auf eine entfernte Datei verweist, wird eine
Zugriffsoperation auf entsprechende Kommunikationsnachrichten (z.B. durch
den NFS-Client auf der Basis des NFS Protokolls) abgebildet.

228
Kapitel 8

Ein-/Ausgabe

Eine der Hauptaufgaben eines Betriebssystems ist es, alle Ein-/Ausgabegeräte


eines Rechensystems zu überwachen und steuern.

8.1 Klassifikation von E/A-Geräten


Unterscheidung zwischen
blockorientierten Geräten: speichert Information in Blöcken fester Größe
(z.B. Festplatte). Die Information zwischen BS und Gerät werden immer in
ganzen Blöcken transferiert, und nicht einzelne Bytes.
zeichenorientierten Geräten: erzeugt und akzeptiert Zeichenströme, ohne auf
Blockstruktur zu achten (z.B. Maus, Tastatur, Netzwerkkarte). Nicht alle
Geräte passen in dieses Schema. Uhren besitzen weder Blockorientierung
noch erzeugen sie Zeichenströme; sie lösen in wohdefinierten Zeitintervallen
Unterbrechungen aus.
Eine andere Unterteilung bezieht sich auf Geräte mit
wahlfreiem Zugriff: Zugriff über Adressinformation (z.B. Festplatte).
seriellem Datentransfer: Zugriff ohne Adressinformation (z.B. Magnetband).

• Ziele für E/A-Software im Betriebssystem


Geräteunabhängigkeit. Es sollte möglich sein, Programmen zu schreiben,
die mit Dateien auf einer Festplatte, CD-/DVD-Laufwerk und USB-Stick
arbeiten, ohne dass zuvor das Programm für den jeweiligen Gerätetyp
geändert werden muss.

229
Schlichter, TU München 8.2. SCHICHTEN EINES E/A-SYSTEMS

einheitliches Benennungsschema für die Geräte. Der Name sollte aus einer
Zeichenkette oder Nummer bestehen, und nicht von der Art des Gerätes
abhängen.

8.2 Schichten eines E/A-Systems


Ein E/A-System eines BS ist typischerweise in mehrere Schichten unterteilt:

Benutzerprozess Benutzer Modus

geräteunabhängige BS-Software System Modus

Gerätetreiber
Betriebssystem

Unterbrechungsroutinen

Controller

Hardware
Gerät

• Unterbrechungsroutinen: Handhabung der Rückmeldungen vom Geräte-


Controller, z.B. nach Beendigung eines Druckauftrags. Die Rückmeldung er-
zeugt eine Unterbrechung, die von der zugehörigen Unterbrechungsroutine be-
handelt wird. Der gerade laufende Prozess wird unterbrochen und sein Zustand
wird gerettet. Der Prozess, der auf die Rückmeldung des E/A-Gerätes wartet,
wird entblockiert.

• Gerätetreiber: Ausführung der geräteabhängigen Steuersoftware; zuständig für


alle Geräte eines Gerätetyps. Der Code der Gerätetreiber wird vom Hersteller
des Geräts programmiert und mit dem Gerät zusammen ausgeliefert. I.a. sind
für jedes Betriebssystem eigene Treiber notwendig. Der Gerätetreiber greift
über die Controller auf die Geräte zu.

• Geräteunabhängige Software: belegen eines Geräts, puffern von Information.

• Ablauf einer E/A-Anforderung

230
Schlichter, TU München 8.2. SCHICHTEN EINES E/A-SYSTEMS

E/A Request Benutzerprozess E/A Ende, Daten


(read) verfügbar

Systemaufruf
Übertrage Daten in Prozess-
Kann ja BS-Kern Adressraum, melde
Request erledigt
Geräteunabhängige Ergebniscode (Erfolg oder
werden
BS Software Fehlercode)
nein

Send Request zu
BS-Kern
Gerätetreiber
Geräteunabhängige
Blockiere Prozess, falls
BS Software
notwendig

Reserviere Puffer, Bestimme E/A Request,


Sende Kommandos an Gerätetreiber signalisiere E/A-Ende an
Controller BS-Kern

Controller Speichere Daten in Puffer des


Kommandos Gerätetreibers, signalisiere
die Blockierung des Treibers
aufzuheben

Unterbrechung

Steuere Gerät, führe Gerätecontroller


E/A Ende,
Datentransfer durch,
Erzeuge Unterbrechung
unterbreche bei E/A Ende

1. Der Benutzerprozess initiiert den blockierenden Systemaufruf read mit


einem Dateideskriptor als Parameter.
2. Der BS-Kern überprüft die Korrektheit der Parameter. Falls die gewünschten
Daten bereits im Cache des BS vorhanden sind, werden die Daten umgehend
ausgeliefert.
3. Andernfalls muss eine physische E/A durchgeführt werden. Der Prozess aus
der rechnend-Liste entfernt und zur Liste "wartend-auf-EA" hinzugefügt. Der
BS-Kern sendet einen Request an den Gerätetreiber.
4. Der Gerätetreiber reserviert einen Pufferspeicher für die zu empfangenden
Daten, disponiert die E/A und sendet die entsprechenden Kommandos an
den Gerätecontroller (Besetzen der Kontrollregister).
5. Der Gerätecontroller betreibt das Gerät und führt den Datentransfer durch.

231
Schlichter, TU München 8.3. GERÄTEVERWALTUNG

6. Der Gerätetreiber entweder pollt den Controller bzgl. des Zustandes der
Requestdurchführung. Falls der E/A-Request über einen DMA-Controller
erfolgt, wird gewartet bis bei E/A-Ende durch den DMA-Controller eine
Unterbrechung generiert wird.
7. Die Unterbrechungsbehandlung speichert die Unterbrechungsdaten und
signalisiert, die Blockierung des Gerätetreibers aufzuheben.
8. Der Gerätetreiber identifiziert den E/A-Request, der beendet wurde,
bestimmt den Request Status und meldet die Beendigung an den BS-Kern.
9. Der BS-Kern transferriert die Daten und den Returncode in den Adressraum
des Benutzerprozesses, hebt die Blockierung des Prozesses auf und reiht ihn
in die Liste der rechenwilligen Prozesse ein.
10. Wenn der Scheduler dem Prozess die CPU zuordnet, wird der Prozess mit
der Beendigung des Systemaufrufs fortgesetzt.

8.3 Geräteverwaltung
Eine Hauptaufgabe des BS ist die einheitliche Darstellung der unterschiedlichen
E/A-Geräte und Treiber.
Zuordnung von logischen Kanälen zu physischen Geräten.

E/A-System xxTreiber

create() xxcreate()
open() xxopen()
Anwendung Controller
close() xxclose()
Gerät
read() xxread()
Logischer write() xxwrite()
Kanal ioctl() xxioctl()

logische
Kanalnummer Treibertabelle

create open close read write ioctl


0
1 xxcreate xxopen xxclose xxread xxwrite xxioctl
2

8.3.1 Gerätetreiber
Treiber sind gerätetyp-spezifisch und sie schaffen die Verbindung zwischen
Anwenderprozessen und den Geräten bzw. deren Controller. Gelegentlich können

232
Schlichter, TU München 8.3. GERÄTEVERWALTUNG

dieselben Treiber für verschiedene Varianten von Geräteklassen eingesetzt


werden. Damit der Treiber Zugriff auf die Hardware und auf die Register des
Controllers haben kann, muss es ein Teil des BS-Kerns sein. Treiber machen keine
Systemaufrufe, jedoch dürfen sie auf bestimmte BS-Dienste zugreifen.

Kommunikation über
Bussystem Kontroller
Prozessor mit System
Signale, Daten
Programmausführung
Befehle, Daten Gerät
(BS mit Treiber,
Anwendung) Register
Zustände, Signale, Daten

Aufgaben eines Treibers

Treiber bedienen die Hardware zur Gerätesteuerung (Controller), um


Gerätezustände abzufragen
Befehle an das Gerät zu übermitteln,
Daten von/zum Gerät zu übermitteln.
Aufgaben eines Treibers sind

• definiert das Gerät gegenüber dem BS.

• definiert die gerätespezifische Datenbasis.

• initialisiert den Controller und das Gerät beim Systemstart.

• wandelt allgemeine E/A-Anforderungen in gerätespezifische Befehle um.

• aktiviert das Gerät.

• antwortet auf Hardwaresignale des Geräts bzw. des Controllers.

• meldet Geräte- und Controllerfehler.

• empfängt/sendet Daten und Zustandsinformation vom/zum Gerät.

• verarbeitet mehrere E/A-Anforderungen gleichzeitig oder überlappt (Multi-


threading).

• puffert Daten bei Ein- und Ausgabe.

233
Schlichter, TU München 8.3. GERÄTEVERWALTUNG

8.3.2 Geräteunabhängige E/A


Die Realisierung abstrakter Geräte und die Definition einer generischen
Gerätearchitektur ist charakteristisch für viele Betriebssysteme. Ein Aspekt ist die
Bereitstellung einer einheitlichen Schnittstelle zwischen Gerätetreiber und dem
Rest des BS.
⇒ vereinfacht die Programmierung und Einbindung neuer Treiber-Software.
Treiber unterstützen zwar vom Gerätetyp unterschiedliche Funktionen und
Signale, jedoch eine speziell auf einen Treiber zugeschnittene Schnittstelle
würde den Programmieraufwand und damit die Fehleranfälligkeit erhöhen.

Namensgebung von E/A-Geräten

Nutzung von symbolischen Namen für Geräte.


geräteunabhängiger Teil des BS bildet symbolische Namen auf die entspre-
chenden Treiber ab.

• Einbettung der E/A in Unix


in Unix erfolgt der Zugriff auf praktisch jedes E/A-Gerät über Funktionen des
Dateisystems. Vor dem eigentlichen Zugriff auf ein Gerät muss dieses analog
zu einer Datei geöffnet werden.

– in vielen Unix Systemen werden alle Geräte unter dem Teilbaum /dev
verwaltet.
– der Dateiname charakterisiert den jeweiligen Typ des E/A-Geräts.

/dev/ttya: physische serielle Schnittstelle

/dev/ptty01 ...: abstrakte serielle Schnittstellen

/dev/fd0 ...: Diskettenstationen

/dev/sd0 ...: Festplatten (sd steht für SCSI Disk)

/dev/le0 ...: Netzkarten


– /dev/sd0 spezifiziert genau einen I-Node einer Spezialdatei. I-Node enthält:
Hauptgerätenummer (major device number): Festlegung des
Gerätetreibers.

234
Schlichter, TU München 8.3. GERÄTEVERWALTUNG

Nebengerätenummer (minor device number): Parameter an Treiber zur


Festlegung des konkreten Geräts, von dem gelesen, bzw. auf das
geschrieben wird.
Alle Geräte besitzen eine Haupt- und eine Nebengerätenummer; alle Treiber
werden durch die Hauptgerätenummer ausgewählt.

Standardisierte E/A-Funktionen

Die E/A-Programmierschnittstelle wird meist als Teil einer Systembibliothek


(z.B. in C/C++) bereitgestellt. Typische generische E/A-Funktionen sind:

• open(): eröffnet einen logischen Kanal zu einem Gerät und liefert einen
Identifikationswert (Deskriptor, Handle) für die anschließende Nutzung. Beim
Dateisystem wird anstelle des Geräts eine einzelne Datei angesprochen.

• close(): ein vorher geöffneter Kanal wird geschlossen. Die zugehörige


Systemdatenstruktur wird freigegeben.

• read(): liest eine Anzahl von Byte (als Bytestrom) vom Gerät ein.

• write(): gibt eine Anzahl von Byte an das Gerät aus.

• ioctl(): dient dazu, die Betriebsart des Geräts zu ändern. Bei einer seriellen
Schnittstelle kann dies z.B. die Übertragungsrate sein.

Wie bereits erwähnt, werden diese generischen Funktionen durch das Betriebssy-
stem auf Funktionen des relevanten Treibers abgebildet.

Pufferung

Eine direkte Durchreichung der Ein-/Ausgabedaten zwischen dem Benutzerpro-


zess und dem Gerät ist zwar möglich, jedoch erlaubt die Zwischenpufferung der
Daten eine Entkopplung der Abläufe des Benutzerprozesses und des Gerätes

235
Schlichter, TU München 8.3. GERÄTEVERWALTUNG

Prozess Prozess Prozess Prozess

BS

Gerät Gerät Gerät Gerät

ohne einfach doppelt zirkulär

Falls keine Pufferung erfolgt, muss sichergestellt werden, dass der von der E/A
betroffene Teil des virtuellen Adressraums des Prozesses nicht ausgelagert wird,
ansonsten kann es passieren, dass das Gerät die E/A nicht ausführen kann, da der
benutzerseitige Puffer gerade auf die Festplatte ausgelagert wurde.

• einfach: auf Puffer wird wechselseitig über BS von Benutzerprozess und Gerät
zugegriffen. Bei der Eingabe füllt das Gerät zunächst den Puffer, anschließend
liest der Prozess die Daten. Während der Bearbeitung des Datenblocks durch
den Benutzerprozess kann das Gerät bereits den nächsten Datenblock in den
Puffer transferieren. Beim Schreiben können die Daten schnell in den Puffer
transferiert werden, womit der Benutzerprozess nach kurzer Zeit weiterarbeiten
kann.

• doppelt: Benutzerprozess und Gerät können parallel arbeiten. Während der


Benutzerprozess den ersten Puffer leert, kann das Gerät bereits den 2. Puffer
befüllen.

• zirkulär: Koordination der Zugriffe von Benutzerprozess und Gerät, um ge-


genseitiges Überschreiben zu vermeiden. Dies ist insbesondere problematisch,
wenn eine Komponente sehr viel schneller Daten in den Puffer schreibt, als sie
die andere Komponenten daraus lesen kann.

• Wiederholte Pufferung
Pufferung ist ein weitverbreitete Technik; jedoch bei häufiger Pufferung ist
mehrfaches Kopieren der Daten notwendig, darunter leidet die Geschwindigkeit
des Gesamtsystems. Falls das Schichtenreferenzmodell der Rechnernetze

236
Schlichter, TU München 8.3. GERÄTEVERWALTUNG

betrachtet wird, kann es sein, dass noch zusätzliche Pufferungen mit


physikalischem Kopieren zwischen den Schichten erfolgt.

Benutzer Prozess
Adressraum

BS-Kern
Adressraum

Netzwerk
Controller

Spooling

Spooling ermöglicht die einfache Verwendung exklusiv nutzbarer Geräte im


Mehrprogrammbetrieb, z.B. Drucker. Prozesse greifen nicht direkt auf das Gerät
zu, sondern geben den Auftrag an den Spoolerdämon; nur der Spoolerdämon
interagiert direkt mit dem Gerät über den Gerätetreiber.

Benutzerprozesse

P1 Systemprozess

Funktionsaufrufe E/A-System
für Gerät Treiber
Spooler
Pn
Dämon

Spooling Controller
Verzeichnis Gerät

Aufträge der Benutzerprozesse werden im Spooling Verzeichnis gespeichert,


bevor sie der Spoolerdämon dann ausführt. Die Koordination der Zugriffe auf die
exklusive Ressource über Semaphore ist deshalb nicht notwendig.

237
Schlichter, TU München 8.4. RAID

8.4 RAID
Erhöhung der Plattenkapazität durch Zusammenschluss von mehreren kleinen
Festplatten zu einer großen virtuellen Platte. Dadurch ergeben sich eine höhere
Geschwindigkeit und eine bessere Zuverlässigkeit.
⇒ RAID = redundant array of inexpensive disks. Früher waren RAIDS
vor allem aus billigen Festplatten zusammengesetzt, um auf diese Weise
kostengünstige Platten zu erhalten. Heute stehen die höhere Zuverlässigkeit
und die hohen Transferraten im Vordergrund; deshalb wird für das "I" statt
"inexpensive" oft "independet" verwendet.
Für das BS sieht RAID wie eine einzelne Festplatte aus.
keine Änderung an Anwendungssoftware notwendig, um ein RAID-System
nutzen zu können.

• üblicher Plattencontroller wird durch einen RAID Controller ersetzt.

• Daten werden über die Platten verteilt, was eine parallele Verarbeitung
ermöglicht.

• höhere Zuverlässigkeit durch Redundanz.

• Unterscheidung zwischen unterschiedlichen Varianten


RAID Level 0 bis RAID Level 6. Diese Unterscheidung ist nicht als
eine Hierarchie von Varianten zu sehen. Alle 6 Formen sind relativ
unterschiedlich.

• RAID Level 0
Der gesamte Speicherbereich der virtuellen Festplatte wird in gleich große
Abschnitte ("strips"), z.B. 1 Block oder 1 Sektor. Die Strips werden nach dem
Round-Robin Strategie auf die physischen Platten verteilt;
Datenpuffer umfasst mehr als einen Strip ⇒ Verteilung auf mehrere Platten.
In diesem Fall zerlegt der RAID Controller den Schreibbefehl in einzelne
Kommandos, einen für jede betroffene Platte. Die Befehle für jeden Platte
werden dann parallel ausgeführt. Damit haben wir parallele Ein-/Ausgabe,
ohne dass die Anwendungssoftware etwas davon mitbekommt.

238
Schlichter, TU München 8.4. RAID

Strip 0 Strip 1 Strip 2 Strip 3


Strip 4 Strip 5 Strip 6 Strip 7
Strip 8 Strip 9 Strip 10 Strip 11

RAID Level 0 arbeitet am besten mit großen Anfragen, d.h. Anfrage,


die mehrere Strips umfassen. Es arbeitet eher schlecht für Abfragen, die
jeweils nur einen Strip betreffen. Die Zuverlässigkeit ist abhängig von den
Zuverlässigkeiten der einzelnen Festplatten; es gibt keine Redundanz; RAID 0
bietet eine schlechtere Zuverlässigkeit als eine einzelne große teuere Festplatte.

• RAID Level 1
Es werden alle Platten verdoppelt. Im Beispiel existieren 2 Hauptplatten und 2
Backup-Platten.
Bei einem Schreibvorgang wird jeder Strip doppelt geschrieben.
Bei einem Lesevorgang können beide Platten genutzt werden.
Sehr gute Ausfallsicherheit.
Während die Schreibgeschwindigkeit nicht besser gegenüber einer einzelnen
Platte ist, erhöht sich die Lesegeschwindigkeit durch die parallele Nutzung von
Haupt- und Backup-Platten.

Strip 0 Strip 1 Strip 0 Strip 1


Strip 2 Strip 3 Strip 2 Strip 3
Strip 4 Strip 5 Strip 4 Strip 5

Spiegelplatten

• RAID Level 2
Striping erfolgt auf Bitebene mit zusätzlichen Parity-Platten. Beispielsweise
wird jedes Byte in 4-Bit Stücke unterteilt, zusätzlich wird ein 3-Bit Hamming
Code generiert. Dadurch lassen sich Bitfehler nicht nur erkennen, sondern auch
korrigieren.
Alle Platten arbeiten synchron.

239
Schlichter, TU München 8.5. DISK SCHEDULING

Sehr gute Ausfallsicherheit, mit weniger Platten als bei RAID Level 1.

Bit 0 Bit 1 Bit 2 Bit 3 P0 P1 P2

Paritybits

Thinking Machines unterstützt 32 Bit Datenworte und fügt 6 Parity Bits


hinzu, um ein 38 Bit Hamming Wort zu erhalten. Diese werden dann auf
38 synchron laufende Festplatten verteilt. Die Hamming-Prüfsumme wird vom
RAID-Controller errechnet bzw. bei gelesenen Daten überprüft.

• Die restlichen Varianten RAID Level 3 - 6 können im Tanenbaum nachgelesen


werden. Kombinationen von RAID Level sind möglich, z.B. RAID 0+1. Hier
die Festplatten werden gespiegelt. Jeweils auf den Hauptplatten und den
Spiegelplatten werden die Daten durch Stripes gespeichert. Dadurch ergibt
sich sowohl ein Performanz- als auch ein Zuverlässigkeitsgewinn. Es gibt auch
RAID 1+0: in diesem Fall werden die Platten paarweise verdoppelt, d.h. jedes
Strip wird auf einer Hauptplatte und der zugehörigen Spiegelplatte gespeichert.

8.5 Disk Scheduling


Zugriffszeit für Transfer von Daten von/zu Festplatte setzt sich zusammen aus
Suchzeit des Lese-/Schreibkopfes. Dies ist die Zeit, bis der Arm über dem
entsprechenden Zylinder steht, der den gewünschten Sektor enthält (seek
time).
Rotationsverzögerung. Dies ist die Zeit, bis sich der entsprechende Sektor
unter den Kopf dreht (rotational latency).
Dauer der Datenübertragung. Die Transferzeit wird durch die benötigte
Rotationszeit bestimmt, um die geforderte Anzahl an Byte auszulesen. Die
Disk-Bandbreite ist die Gesamtzahl der übertragenen Bytes geteilt durch die
Zeit zwischen der Initiierung des Requests bis zur Beendigung.
Bei den meisten Platten dominiert die Suchzeit gegenüber den anderen Zeiten,
weshalb die Reduzierung der Suchzeit die Systemgeschwindigkeit erheblich
verbessern kann. Viele Plattentreiber verwalten eine Tabelle, die über die
Zylindernummer indiziert wird und in der alle noch auszuführenden Anfragen

240
Schlichter, TU München 8.5. DISK SCHEDULING

für jeden Zylinder in einer verketteten Liste abgespeichert sind. Falls die Liste
der offenen E/A-Requests jeweils nur einen Auftrag enthält, verhalten sich alle
Algorithmen wie FCFS.

• FCFS Scheduling
Die E/A-Requests werden in der Reihenfolge ihres Eintreffens abgearbeitet
(First Come-First Served). Angenommen die E/A-Requests betreffen Blöcke
der Zylinder
98, 183, 37, 122, 14, 124, 65, 67. "Der Arm stehe zu Beginn beim Zylinder
53."

0 14 37 53 65 67 98 122 124 183 200

Problem dieses Verfahrens ist, dass der Arm je nach E/A-Request sehr viel
bewegt werden muss, so dass viel Suchzeit notwendig ist. Für dieses Beispiel
sind insgesamt 640 Zylinderbewegungen notwendig.

• SSTF Scheduling
Beim SSTF-Verfahren (Shortest Seek Time First) wird als nächstes der
E/A-Request bearbeitet, der am nächsten zur aktuellen Position ist. Die
Ausgangsliste
98, 183, 37, 122, 14, 124, 65, 67 wird umsortiert zur Bearbeitungsreihen-
folge
65, 67, 37, 14, 98, 122, 124, 183. Der Arm stehe zu Beginn beim Zylinder
53.

241
Schlichter, TU München 8.5. DISK SCHEDULING

0 14 37 53 65 67 98 122 124 183

Dieses Verfahren ist vergleichbar mit der Strategie Shortest-Job-First bei der
Rechnerkernvergabe. In dem Beispiel sind nur mehr 236 Zylinderbewegungen
notwendig.
Es kann jedoch zum Verhungern von E/A-Requestes kommen, wenn neue E/A-
Aufträge eintreffen, deren Zylinderpositionen näher an den gerade aktuellen
Positionen liegt. Angenommen die Abarbeitungsfolge enthält die Reihenfolge
14 und anschließend 183. Während der Bearbeitung von 14 trifft ein neuer
Auftrag, der näher bei 14 liegt, dann wird dieser zunächst behandelt.
Währenddessen trifft wieder ein Auftrag, der näher bei 14 liegt, dann wird
dieser wieder der 183 vorgezogen. Der Algorithmus bewegt sich also von 14
weg und wieder zurück, ohne jedoch bis zu 183 zu gelangen ⇒ vergleichbares
Problem bei Aufzügen in Hochhäusern.
• SCAN Scheduling
Der SCAN-Algorithmus bearbeitet die E/A Requests zunächst in eine Richtung
bis zum Plattenende, und anschließend zurück zum anderen Plattenende. Die
Ausgangsliste
98, 183, 37, 122, 14, 124, 65, 67 wird umsortiert zur Bearbeitungsreihen-
folge
37, 14, 65, 67, 98, 122, 124, 183. Der Arm stehe zu Beginn beim Zylinder
53 und es wird angenommen, dass er sich in Richtung Zylinder 0 bewegt.

0 14 37 53 65 67 98 122 124 183

242
Schlichter, TU München 8.6. MULTIMEDIA SYSTEMS

Dieses Verfahren wird gelegentlich auch Aufzugalgorithmus genannt. Es


reduziert die Anzahl der Zylinderbewegungen auf 208. Trifft ein neuer E/A-
Request ein, der sich auf dem aktuellen Weg des Arms befindet, wird er an
entsprechender Stelle bearbeitet. Andernfalls muss die Bearbeitung warten, bis
sich der Arm das Plattenende erreicht hat und sich nun in die andere Richtung
zurückbewegt.

8.6 Multimedia Systems


Multimedia umfasst eine Vielzahl, heute populärer Applikationen
Audio und Video Clips (z.B. MP3 und MPEG Dateien).
Live Webcasts. Beispielsweise werden oft Großereignisse, wie z.B. die
Eröffnungsfeier zu den Olympischen Spielen in Peking, als Live Stream über
das Internet übertragen.
Mögliche Endgeräte für den Empfang von Multimedia Daten
Desktop PCs oder mobile Endgeräte, wie PDAs, Smartphones.

8.6.1 Zustellung von Mediendaten


Multimedia Daten können in einem normalen Dateisystem gespeichert werden.
Für die Auslieferung gelten jedoch spezielle Zeitbedingungen, z.B.
Auslieferung von Videodaten gemäß einer Rate von 24 - 30 Frames/Sekunde.
Nur auf diese Weise kann sichergestellt werden, dass das menschliche Auge
den Filmablauf als gleichmäßig und normal sieht. Langsamere Frameraten
werden vom Menschen als abgehackt interpretiert.
Unterscheidung zwischen

• lokales Playback. Die Mediendaten werden vom Server herunter geladen und
im lokalen Dateisystem gespeichert. Von dort werden sie dann abgespielt, z.B.
Laden und Abspielen eines Films oder MP3-Datei auf dem Laptop.

• Streaming
Zustellung der Mediendaten von einem Server über ein Netzwerk zum Client.
Der Client beinhaltet die Abspielsoftware. Er kann ein PC oder ein mobiles
Endgerät sein. Unterscheidung zwischen

– progressives Download. Der Client beginnt mit dem Abspielen der


Mediendaten bereits während der Download noch im Gange ist. Das

243
Schlichter, TU München 8.6. MULTIMEDIA SYSTEMS

Abspielen beginnt, nachdem ein gewisser Anteil der Daten empfangen


wurde. Die Mediendaten werden in einer Datei auf dem Client gespeichert.
– Real-time Streaming. Die Mediendaten werden über das Netzwerk dem
Client zugestellt, ohne sie jedoch auf dem Client zu speichern.
Live Streaming. Die Mediendaten werden von einer Veranstaltung
aufgenommen und sofort an die Empfänger weitergegeben. Ein Vor- oder
Zurückspulen wie bei einer Aufzeichnung ist nicht möglich.
On-Demand Streaming. Zustellung von Aufzeichnungen. Random
Zugriff möglich.

Beispiele von Streaming Produkten: RealPlayer, Apple Quicktime, Windows


Media Player. Diese Produkte umfassen sowohl den client Mediaplayer zum
Abspielen als auch eine Serverkomponent zum Streamen der Mediendaten.

8.6.2 Eigenschaften von Multimedia Systemen


Multimedia Daten können sehr groß sein. Z.B. sind für die Speicherung eines
100 Minuten MPEG-1 Videos ca 1,125 GByte notwendig. 100 Minuten HDTV
erfordern ca 15 GByte.
deshalb Komprimierung der Daten
⇒ ausreichende Rechenleistung für die Dekompression und Anzeige der
Mediendaten unter Einhaltung der Zeitbedingungen. Dies erfordert, dass den
Prozessen, die die Mediendaten dekomprimieren und anzeigen, ausreichende
CPU-Zyklen zugeordnet werden. Beispielweise können hierbei die CPU-
Zuteilungsstrategien "Earliest Deadline First (EDF)" und "Rate Monotonic
Scheduling".

Disk Scheduling

Für den Zugriff auf Mediendaten gelten die beiden Randbedingungen


Zeitbedingungen und hohe Datenrate. Da Festplatten relativ niedrige Übertra-
gungsraten und hohe Latenzzeiten haben, sind Zugriffsverfahren bei mehreren
ausstehenden Aufträgen notwendig, die einerseits die Zeitbedingungen erfül-
len und andererseits hohe Datenraten ermöglichen.
Kombination von SCAN Scheduling mit EDF ("Earliest-Deadline-First"). EDF
sortiert die ausstehenden Auträge gemäß der Zeitpunkte, wann sie abgeschlossen
sein müssen (Deadline).

• Aufträge werden entsprechend ihrer Deadline geordnet (EDF).

244
Schlichter, TU München 8.6. MULTIMEDIA SYSTEMS

• Aufträge mit derselben Deadline werden entsprechend SCAN Reihenfolge


abgearbeitet.

• Aufträge mit ähnlichen Deadlines können entsprechend der SCAN Reihenfolge


umsortiert werden, solange die Zeitbedingungen noch eingehalten werden.

• Einteilung der Aufträge in Zeitbereiche (z.B. 100 ms)

Zeit

0
Auftrag Deadline Zylinder A
A 150 25 D
B 201 112
C 399 95
D 94 31 I
J
E 295 185 F C
100 H
F 78 85 B
G 165 150
H 125 101
I 300 85 G
J 210 90
E
199

Zur ersten Gruppe (0-100ms) gehören die Aufträge D und F, zur zweiten
Gruppe (101-200ms) die Aufträge A, G und H, zur 3. Gruppe (201-300ms)
die Aufträge B, E und J sowie zur letzten Gruppe (301-400ms) die Aufträge C
und I.

245
Kapitel 9

Sicherheit in Rechensystemen

In Rechensystemen, die mehreren Benutzern zugänglich sind, ist eine Kontrolle


des Zugriffs auf das Rechensystem selbst, dessen Dienstleistungen und Datenbe-
stände erforderlich.

9.1 Fragestellungen
Dieser Abschnitt behandelt die Sicherheitsproblematik in zentralen Rechensyste-
men. Dazu werden verschiedene Schutzmechanismen auf Betriebssystemebene
vorgestellt.

• Zugriffsschutz in Rechensystemen.

• Schutzmatrix, insbesondere Zugriffskontrolllisten und Capability-Listen.

• Mobiler Code.

Die verschiedenen Aspekte der Sicherheit in Rechensystemen werden nur


einführend, und nicht erschöpfend behandelt. Für eine detaillierte Behandlung der
Sicherheitsproblematik sei der Leser auf entsprechende Lehrveranstaltungen oder
die Literatur verwiesen.

9.2 Motivation
Was versteht man unter Sicherheit im Bezug auf Rechensysteme?

246
Schlichter, TU München 9.2. MOTIVATION

Jemand: Unterscheidung von Personen und Gruppen von Personen

davon abhalten: durch technische und organisatorische Maßnahmen

einige: Begrenzung durch unser Vorstellungsvermögen

unerwünschte Dinge zu tun:


1) nicht autorisiert Daten lesen (Geheimhaltung, Vertraulichkeit),
2) nicht autorisiert Daten schreiben (Integrität),
3) unter "falscher Flagge" arbeiten (Authentizität),
4) nicht autorisiert Ressourcen verbrauchen (Verfügbarkeit),
usw.

zu tun.

• Unterscheidung zwischen Angriffen von

innen. "Der Angreifer ist in das Rechensystem bereits eingeloggt und ver-
schafft sich illegalen Zugriff auf Ressourcen oder Berechtigungen, z.B.
Systemadministrator-Rechte. Mögliche Angriffstechniken sind Trojanische
Pferde, Login-Attrappen, die Nutzung von Hintertüren in einem Software-
system ("trap door"), Phishing zum Abgreifen von Passwörtern oder die
Ausnutzung eines künstlich herbeigeführten Pufferüberlaufs."

außen. "Durch die Vernetzung von Rechnern finden verstärkt auch Angriffe
von entfernten Rechnern über ein Rechnernetz (z.B. das Internet) statt.
Beispiele für mögliche Angriffstechniken sind sogenannte "war-dialer"
(Ausprobieren von Telefonnummern und Passwörtern) oder die Verbreitung
von Viren."
• Beispiel: Login-Attrappe
Nutzung von Login-Attrappen in Rechnerumgebungen, wo Rechner von
mehreren Benutzern verwendet werden, um geschützte Benutzerpasswörter zu
erfassen (z.B. in Informatikhalle der Informatik-Fakultät).

– Angreifer startet ein Benutzerprogramm, das am Bildschirm einen Login-


Screen simuliert. Der Angreifer gibt, ohne sich auszuloggen den Rechner

247
Schlichter, TU München 9.2. MOTIVATION

frei. Da am Bildschirm der Login-Screen angezeigt wird, ist ein nachfolgen-


der Benutzer der Meinung, dass der Rechner verfügbar ist (es sitzt ja niemand
davor und der vorhergehende Benutzer habe durch Ausloggen seine Sitzung
beendet, da der wohlbekannte Login-Screen angezeigt wird).
– Der ahnungslose Benutzer tippt Benutzername und sein privates Passwort.
Angreiferprogramm speichert Benutzername und Passwort in einer
Datei.
Angreiferprogramm terminiert das aktuelle Shell-Programm ("kill"
Systemaufruf) ⇒ Login-Sitzung des Angreifers wird beendet und
regulärer Login-Screen wird angezeigt.
Der ahnungslose Benutzer nimmt an, dass er sich beim ersten Eintippen
seines Namens oder seines Passwortes vertippt hat und gibt die beiden Daten
erneut ein. Der Angreifer kann auf diese Weise die Passwörter der anderen
Benutzer erfassen.
– Abhilfe: Login-Sequenz wird durch Tastensequenz gestartet, die von einem
Benutzerprogramm nicht erfasst werden kann, z.B. CTRL-ALT-DEL bei
Windows 2000. Falls ein Benutzer diese Tastensequenz eingibt, wird der
aktuelle Benutzer automatisch ausgeloggt und das Login-Programm durch
das Betriebssystem gestartet. Es gibt keinen Weg, um dieses Verhalten des
Betriebssystems zu umgehen.

• Beispiel: Virus
Ein Virus ist ein Programm, dessen Code an ein anderes Programm anfügt ist
und sich auf diese Weise reproduziert. 1 Zusätzlich kann ein Virus noch andere
Funktionen aufrufen, z.B. Löschen von Dateien, Senden von Nachrichten etc.
Oft ist die Reproduktion des Virus und die Ausführung der Virusfunktion zeitlich
getrennt, d.h. die Virusfunktion wird erst nach Eintreten eines bestimmten
Datums getriggert. Dadurch wird erreicht, dass sich ein Virus relativ unbemerkt
ausbreiten kann (z.B. über das Internet), ohne dass die Benutzer bereits
frühzeitig merken, dass ihr Rechner mit dem Virus infiziert ist.
Virus schläft bis infiziertes Programm ausgeführt wird.
Start des infizierten Programms führt zur Virusreproduktion.
Ausführung der Virusfunktion ist u.U. mit einem zeitlichen Datum
versehen.
mögliche Virustypen sind
1
[Tanenbaum2001, S 617]

248
Schlichter, TU München 9.2. MOTIVATION

– Boot Sector Virus. BIOS liest beim Start des Rechners den Master Boot
Record (MBR) und führt ihn aus. Ein Boot Sector Virus trägt sich im MBR
ein und wird damit bei Rechnerstart jeweils ausgeführt. Der ursprüngliche
MBR Inhalt wird oft auf einen anderen Platz der Festplatte kopiert und
von Virus automatisch aufgerufen, um den Rechnerstart zu ermöglichen.
Nach dem Start speichert sich der Virus oft im Speicherbereich des
Unterbrechungsvektors, um nach jedem Systemaufruf wieder die Kontrolle
zu erhalten.
– Macro Virus. Programme wie Word oder Excel erlauben dem Benutzer
das Schreiben von Macroprogrammen (Visual Basic). Beispielsweise kann
ein Angreifer für ein Word-Dokument ein Macro schreiben, das mit der
Open File Funktion verbunden ist. Integriert in das Macro ist der Virus
des Angreifers. Da Macros i.a. alle Systemfunktionen des Betriebssystems
aufrufen dürfen, hat der Virus Zugriff auf die volle Funktionalität. Die
Verbreitung erfolgt durch Versenden des Dokuments, z.B. als Email
Attachment. Öffnen des Dokuments führt zur Ausführung des Macros und
damit des Virus.
– Ausführbares Programm als Virus. Das Virusprogramm sucht nach seinem
Aufruf nach geeigneten ausführbaren Programmen (z.B. "exe Dateien") im
gesamten Dateiverzeichnis und infiziert diese mit dem Virus; beispielsweise
durch Überschreiben des Binärprogramms mit dem Virusprogramm. Die
Länge der Datei wird dadurch verändert (kann genutzt werden durch
Antivirenprogramme, um den Virus zu erkennen).
– Verbreitung von Viren
Früher diente der Austausch von Datenträgern (z.B. Floppy Disk), jetzt das
Internet
als Attachment zu Emails
Lesen des Adressbuchs und automatische Generierung von Emails
mit Virus Attachment an alle Adressbucheinträge (z.B. von Microsoft
Outlook). Dabei wird oft das Subject-Feld so besetzt, dass der Empfänger
das Gefühl hat, er empfange eine persönliche Email von einem
Bekannten.

• Beispiel: Pufferüberlauf
Durch einen künstlich herbeigeführten Pufferüberlauf kann ein Angreifer die
Ausführung seines eigenen Programms veranlassen und oft auch noch die
Systemadministrator-Berechtigung (root) erlangen. 2
2
[Tanenbaum2001, S 610]

249
Schlichter, TU München 9.2. MOTIVATION

– Hintergrund
Die meisten C-Compiler und Laufzeitsysteme überprüfen nicht die Einhal-
tung der Feldgrenzen. Da viele aktuelle Betriebssysteme auf der Basis von C
realisiert wurden, ist diese Problematik von großer Bedeutung.
int i;
char c[256];
i = 12000;
c[i] = 0;
Die Codesequenz ist zwar falsch. Das Laufzeitsystem führt jedoch keine
Überprüfung durch; der Fehler bleibt unentdeckt. In den meisten Fällen
führt dieser Fehler über kurz oder lang jedoch zu einem Programmabsturz
(oft ein Nullpointer). Ein Angreifer kann diese Eigenschaft nutzen, um
Teile des Laufzeitkellers zu überschreiben. Ein Beispiel wäre, das Feld
c für die Speicherung des Pfadnamen einer Datei vorzusehen. Da das
Betriebssystem nur maximal 256 Zeichen pro Pfadenamen unterstützt, ist
für den Programmierer die Länge von c ausreichend. Ein Angreifer kann nun
einen Datei-Pfadnamen angeben, der erheblich länger als 256 ist.
∗ String Library in C
Implementierung der Unix Funktion gets (get string from stdin)
keine Möglichkeit zur Spezifikation der Anzahl der zu lesenden
Zeichen
char *gets(char *dest) {
int c = getc();
char *p = dest;
while (c != EOF && c != ’\n’) {
*p++ = c; c = getc();
}
*p = ’\0’;
return dest;
}
◦ ähnliche Probleme auch bei anderen Unix Funktionen
strcpy: kopiert einen String beliebiger Länge
scanf, fscanf, sscanf: mit %s Konvertierungsspezifikation.
wobei scanf("...", liste der Variablen) gilt.
◦ Angreifbarer Buffer Code
void echo() {
char buf[4]; /* sehr klein */
gets(buf);
puts(buf);
}

250
Schlichter, TU München 9.2. MOTIVATION

int main() {
printf("Type a string:");
echo();
return 0;
}
unix> bufdemo
Type a string: 123
123
unix> bufdemo
Type a string: 12345
Segmentation Fault

Keller von main

Rückkehradresse Information
für UP Aufruf
[3] [2] [1] [0] buf
Keller von echo

– Veränderung der Rücksprungadresse

Keller Variable Variable Variable


Hauptprogramm Hauptprogramm Hauptprogramm
SP
Rückkehradresse Rückkehradresse
lokale Variable lokale Variable
von A von A
Feld C C Feld C C
SP SP

Programm Programm Programm

Ablauf nach Aufruf der


nach Pufferüberlauf
Hauptprogramm Prozedur A

Durch sorgfältiges Analysieren und Berechnen des Speicherlayouts kann


der Angreifer bei Pufferüberlauf die Rückspungadresse der aufgerufenen
Prozedur überschreiben. Der Angreifer überschreibt den Laufzeitkeller von

251
Schlichter, TU München 9.3. SCHUTZMECHANISMEN

A einschließlich des Feldes C und der Rücksprungadresse. Die neue


Rücksprungadresse zeigt an den Anfang des Puffers c, an deren Stelle
das vom Angreifer gewünschte ausführbare Programm steht. Der Angreifer
überschreibt als nicht nur die Rücksprungadresse, sondern trägt auch sein
Angriffsprogramm in den Keller des Hostprogramms ein. Beispielsweise
beinhaltet die Zuweisung an das Feld c nicht den Dateinamen, sondern einen
ausführbaren binären Programmcode.
"Anstelle des auf 255 Zeichen beschränkten Dateinamen wird in Feld c
ein längerer Programmcode eingetragen, der auch die Rücksprungadresse
überschreibt."
∗ Falls das attackierte Programm mit root-Berechtigung (setuid root in
Unix) abläuft, läuft das aufgerufene Programm im Puffer auch mit root-
Berechtigung.
Angreifer kann seiner aufrufenden Shell root-Berechtigung verleihen.
Dadurch erwirbt der Angreifer Superuser Rechte für seine eigenen
Programme und hat damit Zugang auf das gesamte Betriebssystem.

– Gegenmaßnahmen
Unterscheidung
sichere Programmierung. Durch sorgfältige Programmierung, bei der ins-
besondere alle Eingabewerte geprüft und Bereichsgrenzen kontrolliert,
kann man verhindern, Ziel von Buffer Overflow Angriffen zu werden.
Maßnahmen zur Übersetzungszeit. Ein StackGuard Tool fügt ein
spezielles Kontrollzeichen direkt hinter die Rücksprungadresse auf dem
Stack ein. Zusätzlich wird automatisch Code hinzugefügt, der vor dem
Rücksprung überprüft, ob das Kontrollzeichen verändert wurde.
Maßnahmen zur Laufzeit. Das Java Laufzeitsystem überprüft zur
Laufzeit die Einhaltung der Bereichsgrenzen automatisch.

9.3 Schutzmechanismen
Schutz von gespeicherter Information vor Diebstahl, unerwünschter Manipulation
und Verletzung der Vertraulichkeit ist ein zentrales Anliegen in allen Mehrbenut-
zersystemen. 3 Der Schutz sollte jedoch so organisiert werden, dass dadurch der
gewollte Austausch sowie die gemeinsame Nutzung von Programmen und Daten
zwischen den beteiligten Nutzern nicht unnötig eingeschränkt werden. Die Forde-
rung ist ein flexibles Schutzkonzept, das an die Anwendungsumgebung angepasst
werden kann.
3
[Nehmer2001, S 293]

252
Schlichter, TU München 9.3. SCHUTZMECHANISMEN

9.3.1 Anforderungen
Für einen Schutzmechanismus gelten die folgenden Anforderungen
• alle Objekte eines Systems müssen eindeutig und fälschungssicher identifiziert
werden. Insbesondere muss auch der Aufrufer eines Dienstes eindeutig
und fälschungssicher identifiziert werden. Dies ist gerade für Client-Server
Beziehungen von großer Bedeutung, z.B. die eindeutige Identifizierung des
Client bei Ecommerce Anwendungen.
• externer Benutzer eines Systems muss eindeutig und fälschungssicher identifi-
ziert werden ⇒ Authentifizierung. Die Zuordnung zu einem Benutzerprozess
muss fälschungssicher sein.
• Zugriff auf Objekte sollte nur über zugehörige Objektverwaltung geschehen.
• Zugriff auf Objekte nur, wenn Zugreifer die nötige Rechte hat.
• Rechte müssen fälschungssicher gespeichert werden; Weitergabe von Rechten
darf nur kontrolliert erfolgen.
• Prinzip der minimalen Rechte. Jedem Programm oder Benutzer sollen für die
Objekte nur die Rechte eingeräumt werden, die für die momentane Arbeit
zwingend erforderlich sind. Beispielsweise werden unnötige Ports geschlossen.
• grundlegenden Schutzmechanismen sollen ohne großen Aufwand überprüft
werden können. Dies bedeutet, dass am besten ein einheitliches Schutzkonzept
für alle zu schützenden Objekte verwendet wird, und dass die Implementierung
zentral in einem möglichst kleinen Baustein, einem Schutzkern im Betriebssy-
stem, erfolgt.

9.3.2 Ebenen des Zugriffschutzes


4
Man unterscheidet die folgenden Ebenen des Zugriffsschutzes.

Maschinenschutz: Kontrolle des physischen Zugangs zum Rechensystem.


"Beim direkten Zugang erfolgt die Kontrolle typisch durch organisatorische
und bauliche Maßnahmen (siehe LRZ, wo Zugang über die Brücke ermöglicht
wird.). Bei Zugang zu einem Rechner über ein Kommunikationsnetz sind
spezielle Hardware- und Software-Schutzeinrichtungen vorzusehen, z.B.
Benutzer meldet seinen Zugangswunsch an und Rechner ruft auf einer vorher
definierten Nummer zurück (unter der der Benutzer erreichbar ist)."
4
[Siegert1991, S 155]

253
Schlichter, TU München 9.3. SCHUTZMECHANISMEN

Zugangskontrolle: Kontrolle des logischen Zugangs zum Rechensystem, d.h.


Ausführung von Aufträgen im Rechensystem. Hier spielt die Authentifizie-
rung des Benutzers eine wichtige Rolle, z.B. Passwörter oder biometrische
Eigenschaften, um den Benutzer eindeutig zu identifizieren. Im Rechensy-
stem sind Verfahren notwendig, um die Korrektheit der angegebenen Identität
zu überprüfen (z.B. Passwort-Datei).

Berechtigungskontrolle: Kontrolle des Benutzerzugriffs auf einzelne Daten-


bestände und die Ausführung einzelner Dienste.

Systemschutz: Gewährleistung der Integrität der Schutzmechanismen. Hier


muss sichergestellt werden, dass die Schutzmechanismen in Hardware und
Software durch Angreifer nicht modifiziert werden können, um ein Umgehen
und Aushebeln des Schutzes durchzuführen.

9.3.3 Schutzmatrix
Das Konzept der Schutzmatrix wurde von B. Lampson eingeführt. Es verknüpft
Schutzdomänen mit den zu schützenden Objekten.

• Schutzdomänen
Definition: Eine Schutzdomäne ist eine Menge von (Objekt, Rechte) Paaren.
"Jedes Paar spezifiziert ein Objekt und eine Menge von Operationen, die auf
diesem Objekt ausgeführt werden dürfen. Meist entspricht eine Schutzdomäne
einem Benutzer, d.h. sie gibt an, was dieser Benutzer tun darf. Negative Rechte,
d.h. das was er nicht tun darf, werden nicht explizit angegeben."

Domäne 1 Domäne 2

Datei1[RWX]
Datei1[R]
Printer1[W]
Datei4[R]
Datei2[RW] Datei3[RW]
Floppy1[R]

R = read, W = write, X = execute

254
Schlichter, TU München 9.3. SCHUTZMECHANISMEN

Das Beispiel zeigt mehrere Objekte mit Ihren Rechten und ihre Zuordnung
zu den Domänen. Gleiche Objekte (im Beispiel Datei1) können mit
unterschiedlichen Rechten unterschiedlichen Domänen zugeordnet werden.

– Verknüpfung eines Prozesses mit einer Schutzdomäne. "Dadurch wird der


Handlungsspielraum des Prozesses bei seiner Ausführung eingeschränkt.
Die Zuordnung einer Schutzdomäne zu jedem Prozess geschieht in einer
allen Zugriffsversuchen vorangeschalteten Authentisierung. Insbesondere
wird die hinter einem Prozess stehende Identität geprüft, z.B. die Identität
des Benutzers oder die eines Servers."
– zu jedem Zeitpunkt wird ein Prozess in einer Schutzdomäne ausgeführt.
Ein Prozess kann während seiner Ausführung die Schutzdomäne wechseln.
Dadurch können Prozesse während ihres Lebenszyklus auf unterschiedliche
Objekte mit unterschiedlichen Rechten zugreifen.
Beispiel Unix: bei Ausführung eines Systemaufrufs wechselt der Prozess
vom Benutzermodus in den Systemmodus ("kernel mode") ⇒ entspricht
einem Wechsel der Schutzdomäne. Im Systemmodus kann der Prozess
auf die geschützten Ressourcen des Systems zugreifen.
– Das Paar (Prozess P, Schutzdomäne D) wird als Subjekt bezeichnet.
"Subjekte sind im Kontext einer Schutzdomäne agierende Prozesse."
Der Zugriffswunsch eines Subjektes S auf ein Objekt o ist definiert als
(D, o, a), wobei D die Schutzdomäne und a die Zugriffsart ist.
– Matrix-Datenstruktur
Konzeptuell verwendet ein Betriebssystem eine Matrix-Datenstruktur, um
die Zuordnung Objekt-Schutzdomäne zu verfolgen.

Objekt

Datei1 Datei2 Datei3 Datei4 Printer1 Floppy1


Domäne
1 read read write read write write

read write
2 read write read write read
execute

Jedes Matrixelement spezifiziert die Zugriffsarten, die in einer Schutzdomäne


auf das zugehörige Objekt erlaubt sind. Der Domänenwechsel selbst kann mit
Hilfe des Matrixmodells realisiert werden. Zum Beispiel können als Objekte
zusätzlich die Schutzdomänen mit aufgenommen werden. Falls ein Wechsel
von einer Domäne 1 in eine Domäne 2 erlaubt sein soll, wird in die Zeile

255
Schlichter, TU München 9.3. SCHUTZMECHANISMEN

der Domäne 1 in der Spalte für Objekt Domäne 2 die Zugriffsart "enter"
eingetragen.

• Schutzmonitor
Jeder Zugriff (D, o, a) eines Subjektes S wird mit Hilfe eines Schutzmonitors
überprüft. Der Schutzmonitor prüft anhand seiner intern gespeicherten Schutz-
matrix, ob in der Zeile von D ein Zugriffsrecht a für das Objekt o existiert. Bei
positivem Ausgang wird der Zugriff zugelassen, andernfalls wird ein Schutz-
alarm ausgelöst und der Zugriff unterdrückt. Der Schutzmonitor läuft meist in
einem geschützten Teil des Betriebssystems ab (z.B. Betriebssystemkern).

Objekte
Schutz-
Prozess o1
domäne
(D,o1,a) Schutzmonitor
D P Schutz o2
matrix
o3
Subjekt Betriebssystem - Systemmodus
Benutzermodus

– der Schutzmonitor ist vertrauenswürdig.


– Subjekte können in keinem Fall auf Objekte unter Umgehung des
Schutzmonitors zugreifen.
– neue Prozesse müssen sich gegenüber dem Schutzmonitor authentifizieren.
"Anonyme Prozesse, die noch ohne Schutzdomäne sind, übergeben dem
Schutzmonitor Namen und Passwort des Benutzers, in dessen Auftrag sie
handeln. Erkennt der Schutzmonitor die Identität an, veranlasst er den
Betriebssystemkern einen Verweis auf die zugeordnete Schutzdomäne im
Prozesskontrollblock zu speichern; der Prozess kann nun auf die erlaubten
Objekte zugreifen."

• Schutzmatrix ist typischerweise sehr groß und dünn besetzt ⇒ eine


direkte Implementierung ist deshalb nicht sinnvoll. "Deshalb ist man dazu
übergegangen die Schutzmatrix entweder spaltenweise oder zeilenweise zu
speichern, um den Speicheraufwand zu reduzieren. Leere Matrixelemente
werden nicht gespeichert."
• Zugriffskontrollliste
Zugriffskontrolllisten ("Access Control List", ACL) realisieren die spaltenwei-
se Speicherung der Schutzmatrix.

256
Schlichter, TU München 9.3. SCHUTZMECHANISMEN

jedes Objekt o besitzt seine Zugriffskontrollliste.


Element einer Zugriffskontrollliste (ACL-Element) besteht aus Paar
(Prozess, Zugriffsarten). Anstelle des Prozesses können als Komponenten
in einem ACL-Element auch Schutzdomänen verwendet werden. Die
Verwendung von Schutzdomänen erleichtert die Zusammenfassung von
Benutzern zu einer Gruppe, die die gleichen Zugriffsrechte besitzen. Jedes
ACL-Element repräsentiert ein Kontrollrecht für das Objekt o.

Prozess Benutzer Benutzer


A B C Modus

Datei D1 A: RW; B: R ACL


System
Datei D2 A: R; B: RW; C: R
Modus
Datei D3 B: RWX; C: RX

Neben den allgemeinen Rechten wie read, write und execute können auch
objekt-spezifische Zugriffsarten in die Zugriffskontrollliste des Objektes einge-
tragen werden. Für einen Prozess (Subjekt) sind nur diejenigen Zugriffsarten
auf das Objekt erlaubt, die in der zugehörigen ACL eingetragen sind. Manche
Schutzsysteme unterstützen auch Wildcards für die Prozessspezifikation, d.h.
ein ACL-Element (*, R) bedeutet, dass beliebige Prozesse das Leserecht auf
das Objekt besitzen.

• Capability-Liste
Capability-Listen ("Zugriffsausweislisten") realisieren die zeilenweise Speiche-
rung der Schutzmatrix.
jeder Prozess besitzt eine Menge von Capabilities, die die erlaubten
Zugriffe auf Objekte repräsentieren.
Element einer Capability-Liste besteht aus Paar (Objekt, Zugriffsarten). Ein
Capability gibt dessen Besitzer gewisse Zugriffsrechte für das Objekt.

257
Schlichter, TU München 9.3. SCHUTZMECHANISMEN

Prozess Benutzer Benutzer


A B C Modus

D1: R
D1: RW D2: R
D2: RW System
D2: R D3: RX
D3: RWX Modus

Capability-
Liste

– Capabilities müssen geschützt werden, um Modifikationen durch den Prozess


selbst zu verhindern. Alternativen sind
Speicherung im geschützten Bereich des Betriebssystems.
Capabilities sind zwar im Benutzermodus dem Prozess zugeordnet; sie
sind jedoch verschlüsselt. "Der Prozess kann bei einem Objektzugriff
dem Schutzmonitor sein zugehöriges Capability vorzeigen, jedoch
dieses Capability nicht selbst verändern. Eine Änderung darf nur vom
Schutzmonitor vorgenommen werden. Diese Alternative ist besonders
für verteilte Systeme geeignet. Beispielsweise schickt ein Client
zusammen mit seiner Dienstanforderung auch das zugehörige Capability
an den Server. Das Capability muss sicher übertragen werden (z.B.
verschlüsselt), damit ein heimliches Kopieren und missbräuchliche
Nutzung durch andere Prozesse verhindert werden kann."
– Capabilities können zeitlich begrenzt werden. Auch könnte mit einem
Capability ein Kontofeld verbunden sein. Bei jeder Verwendung des
Capability wird das Kontofeld reduziert. Ein Objektzugriff ist nur möglich,
wenn der Kontostand ausreichend ist. Damit kann ein Capability nur für eine
begrenzte Anzahl von Zugriffen beschränkt werden.
• Zusammenfassung: Zugriffskontrolllisten und Capability-Listen haben in
gewisser Weise komplementäre Eigenschaften
ACLs erlauben das selektive Zurücknehmen von Rechten. Für Capabilities
ist dies eher schwierig, da die Capabilities verteilt den einzelnen Prozessen
zugeordnet sind, und auch zwischen Prozessen weitergegeben werden
können.
Capabilities können weitergegeben werden. Bei der Weitergabe kann der
Prozess die Zugriffsrechte einschränken.

258
Schlichter, TU München 9.3. SCHUTZMECHANISMEN

9.3.4 Authentifizierung
Authentifizierung eines Nutzers erfolgt meist über Login-Name und dem
zugehörigen Passwort. Ein häufig benutzter Ansatz besteht darin, dass das
ursprüngliche Passwort mit einem Streuwert ("salt value") kombiniert wird, und
daraus ein Hash Code generiert wird.
Generierung eines Hash Code aus dem Passwort und einem Streuwert fester
Länge. Der Streuwert ist eine Zufallszahl oder der Zeitpunkt, an dem das
Passwort erzeugt wurde. Aus Passwort und Streuwert wird ein Hash Code
fester Länge generiert. Die Hash Code Generierung wird gezielt verlangsamt,
um Attacken durch automatisch gesteuerte Versuche entgegenzutreten. Unix
Systeme nutzen oft eine MD5 basierte Hash Funktion mit einem Streuwert
von bis zu 48 Bits; Ergebnis ist ein 128-bit Hashwert.
Ein sehr sicheres Verfahren wurde für OpenBSD entswickelt. Die Hash Funktion
basiert auf dem Blowfish symmetrischen Verschlüsselungs Verfahren. Passwörter
können eine Länge bis zu 55 Zeichen haben, der Streuwert umfasst 128 Bit; es
entsteht ein Hash Code von 192 Bit.

Eintragen Passwort
User ID Streuwert Hash Code
Passwort
Langsame Hash
Funktion
Streuwert

Passwort Datei
Überprüfen Passwort

Passwort
User ID Streuwert Hash Code
Streuwert
User ID

Langsame Hash
Funktion

Vergleich

Ziele des Streuwerts

• Duplikate von Passwörter sollen in der Passwort Datei nicht erkennbar sein.
Auch wenn zwei Benutzer das gleiche Passwort wählen, entsteht aufgrund des
unterschiedlichen Streuwerts ein unterschiedlicher Hash Code.

259
Schlichter, TU München 9.4. MOBILER CODE

• Erhöht den Aufwand für offline Attacken auf die Passwort Datei. Hier wird der
Fall berücksichtigt, dass ein Angreifer eine Kopie der Passwort Datei erhält.
Durch einen Streuwert mit b-bits erhöht sich der Aufwand um den Faktor
2b. Neben dem Ausprobieren möglicher Passwörter muss der Angreifer auch
jeweils die möglichen Streuwerte durchspielen.
• nicht erkennbar, ob eine Person dasselbe Passwort auf 2 oder mehreren
Systemen nutzt.

9.4 Mobiler Code


Das Internet führt zunehmend zu einer Verbreitung von mobilem Code. Beispiele
sind
Web Seiten mit Applets
Postscript Dateien
mobile Software-Agenten (z.B. in Ecommerce Anwendungen).
Ausführung von heruntergeladenem Code birgt Risiken in sich. Beispielsweise
kann ein Applet bösartigen Code enthalten, das auf Ressourcen der lokalen Um-
gebung zugreift und sie unberechtigterweise modifiziert oder löscht. Methoden
(anhand von Applets), um mit dieser Problematik umzugehen:

9.4.1 Sandboxing
Ausführung des Applets wird auf einen bestimmten virtuellen Adressbereich
beschränkt.
Für eine Sandbox sind die high-order Bits aller Adressen gleich, d.h.
angenommen für einen 32 Bit Adressraum werden 256 Sandboxes auf 16
MByte Grenzen eingerichtet
⇒ für alle Adressen innerhalb einer Sandbox sind die oberen 8 Bits
identisch.

• jedes Applet erhält zwei Sandboxes: eine Code-Sandbox, eine Daten-Sandbox.


Die Code-Sandbox darf durch das Applet nicht verändert werden, um die
Gefahr durch einen sich selbst-modifizierenden Code zu eliminieren.
• nach dem Laden wird Applet-Code überprüft, ob er Befehle enthält, die ein Ver-
lassen der Sandbox verursachen. Es werden insbesondere Sprungbefehle (JMP)
und Systemaufrufe (CALL) untersucht. Sprungbefehle, deren Sprungziele erst
zur Laufzeit bestimmt werden, können erst vor deren Ausführung analysiert
werden.

260
Schlichter, TU München 9.4. MOBILER CODE

• ein Applet, das die Sandbox-Grenzen verletzt, wird zurückgewiesen.

9.4.2 Interpretation
Applet wird als Byte-Code geladen. Jeder Befehl wird vor seiner Ausführung von
der Java Virtual Machine (JVM) analysiert.

• jeder Systembefehl wird abgefangen und untersucht. Wie die einzelnen


Systembefehle behandelt werden, hängt von der eingestellten Sicherheits-
Policy ab.
für vertrauenswürdige Applets (z.B. geladen von lokaler Festplatte) werden
Systembefehle ausgeführt.
nicht vertrauenswürdige Applets (z.B. geladen über Internet) werden
innerhalb einer Sandbox ausgeführt.

9.4.3 Signed Code


Es werden nur Applets von vertrauenswürdigen Quellen geladen und ausgeführt.
Applets anderer Quellen werden abgelehnt. Der Applet-Code wird mit einer digi-
talen Unterschrift versehen, um zu garantieren, dass der Code der vertrauenswür-
digen Quelle nicht verändert wurde.

• digitale Unterschrift basiert auf public-key Verfahren.


• Erzeugung der Unterschrift durch vertrauenswürdige Quelle
Hashfunktion erzeugt von Applet-Code eine 128/160 bit Zahl.
erzeugte Hashzahl wird mit privatem Schlüssel der Quelle verschlüsselt.
digitale Unterschrift wird mit Applet-Code verschickt.
• Überprüfung der Unterschrift
Browser führt auf Applet-Code Hashfunktion aus und berechnet selbst
Hashzahl.
Browser entschlüsselt Unterschrift mit öffentlichem Schlüssel der vertau-
enswürdige Quelle.
berechnete Hashzahl und Hashzahl in Unterschrift müssen übereinstimmen.

Falls die beiden Hashzahlen nicht übereinstimmen, wird die Ausführung des
Applets abgelehnt.

261
Kapitel 10

Entwurf von Betriebssystemen

Der Entwurf eines BS erfordert ein ingenieurmäßiges Vorgehen. Es gibt


jedoch keine wohl-definierten Vorgehensweisen, sondern nur Erfahrungen von
Entwicklern bzw. Nutzern.

10.1 Einführung
Die Ziele von Betriebssystemen können sich zwischen verschiedenen Systemen
unterscheiden, für Server-Systeme, für Laptops, für Smartphones oder für
eingebettete Systeme.

10.1.1 Hauptaspekte
Man kann die folgenden 4 Hauptaspekte unterscheiden

• Definierte Abstraktion: Jede dieser Abstraktionen wird durch konkrete


Datenstrukturen instanziiert, z.B. Prozess, Datei, Semaphore
z.B. Thread, Prozess, Datei
Weitere Abstraktionen beziehen sich auf Synchronisation, Signale, Speicher-
modell oder die Ein-/Ausgabe.

• Bereitstellen einfacher Operationen:


Operationen zum Manipulieren der zur Abstraktion gehörigen Datenstruk-
turen. Beispielsweise können Nutzer Dateien lesen oder schreiben.
Ansprechbar über Systemaufrufe. Die primitiven Operationen werden
durch Systemaufrufe realisiert.

262
Schlichter, TU München 10.1. EINFÜHRUNG

• Sicherstellen der Abgrenzung: Da verschiedene Nutzer gleichzeitig auf einem


Rechner aktiv sein können, muss das Betriebssystem einen Mechanismus
bereitstellen, der diese Benutzer voneinander abgrenzt. Andererseits möchten
Nutzer Daten und Ressourcen gemeinsam nutzen.
Eingrenzung von Fehlern durch Abgrenzung von Prozessen. Prozesse
dienen zur Gruppierung von Ressourcen aus Schutzgründen
Zentrales Ziel ist, dass Nutzer nur autorisierte Operationen auf autorisierten
Daten ausführen können. Ein weiterer Punkt ist die Eingrenzung von Fehlern;
der Absturz eines Nutzerprozesses soll nicht zum Absturz des gesamten
Systems führen.

• Verwalten der Hardware.

10.1.2 Probleme
Hardware hat sich gemäß des Moore‘schen Gesetzes kontinuierlich verbessert;
Betriebssysteme haben zwar mehr Funktionalität, jedoch bzgl. Verfügbarkeit sind
sie teilweise schlechter als die alten Systeme. Unix wurde in den 70er Jahren,
Windows in den 80er Jahren entwickelt.

• Betriebssysteme sind sehr komplex. Windows 2000 bestand aus 29 Millionen


Codezeilen und wurde von ca. 1400 Entwicklern realisiert. Windows XP hatte
ca. 40 Millionen Codezeilen und Windows Vista bereits mehr als 50 Millionen
Codezeilen. Für Windows 7 wird dagegen eine Reduktion angenommen.

• Betriebssysteme müssen mit Parallelität umgehen. Parallelität von unterschied-


lichen Komponenten, z.B. E/A-Geräte, führt zu Race-Conditions und Verklem-
mungen.

• Betriebssysteme müssen mit feindlichen Nutzern umgehen. Benutzer können


das System beeinflussen oder Daten stehlen. Dabei kann der Angriff lokal oder
über das Netz erfolgen.

• Nutzer möchten Daten mit anderen Nutzern gemeinsam nutzen. Einerseits


sollen die Benutzer voreinander geschützt werden, andererseits möchten sie
Daten gemeinsam nutzen. Das Betriebsystem muss einen Kompromiss finden,
der die gemeinsame Nutzung von Ressourcen erlaubt, jedoch böswillige Nutzer
ausgrenzt.

• Betriebssysteme existieren eine lange Zeit. Unix wurde bereits in den 70er
Jahren, Windows in den 80er Jahren entwickelt. Entwickler müssen deshalb

263
Schlichter, TU München 10.2. SCHNITTSTELLENENTWURF

Betriebssysteme so flexibel gestalten, so dass auch neuere Technologien und


Konzepte berücksichtigt werden können. Ein Betriebssystem muss erweitert
werden können.

• Entwickler wissen oft nicht vorab, wie ihre Systeme genutzt werden. Unix
wurde zunächst für Minicomputer entwickelt; später wurde es auch als Server-
BS und als Desktop-BS genutzt.

• Betriebssysteme sind portabel für unterschiedliche Hardware entworfen.

• Kompatibilität mit älteren Betriebssystem Versionen. Symptome, die hier eine


Rolle spielen, sind Beschränkungen bzgl Dateinamen. Oft verhindert die
erforderliche Kompatibilität eine radikale Verbesserung eines BS.

10.2 Schnittstellenentwurf
Ein BS bietet eine Reihe von Diensten, die von Benutzerprozessen in Anspruch
genommen werden können.
Bereitstellen der Dienste über Schnittstellen.

10.2.1 Leitlinien für den Entwurf


Es existieren eine Reihe von Prinzipien und Empfehlungen

• Einfachheit. Eine einfache Schnittstelle ist leichter zu verstehen und damit


fehlerfrei zu implementieren. Es gilt nach Exupery: Perfektion ist nicht erreicht,
wenn man nichts mehr hinzufügen kann, sondern wenn man nichts mehr
entfernen kann.

• Vollständigkeit. Umfang an bereitgestellten Mechanismen: was würde passie-


ren, wenn man ein Feature weglassen würde..
Bereitstellen, was man benötigt und nicht mehr.
Minimum an Mechanismen. Jeder Dienst sollte eine genau festgelegte
Funktionalität haben, und nur diese erfüllen. Es sollte nach Möglichkeit
vermieden werden, unterschiedliche Mechanismen für die gleiche Funktio-
nalität zu verwenden, z.B. für das Speichern von Information.
• Effizienz. dem Anwendungsprogrammierer sollte intuitiv klar, wie viel ein
Systemaufruf kostet (Erwartungshaltung der Programmierer), z.B. erwarten
Unix Programmierer dass ein lseek-Aufruf billiger als ein read-Aufruf ist.

264
Schlichter, TU München 10.2. SCHNITTSTELLENENTWURF

Nutzergruppen von BS

• Endbenutzer
Nutzung von Anwendungen ⇒ grafische Oberfläche des BS
• Programmierer
Nutzung der Systemaufrufschnittstelle des BS
• Systemadmin
Aufruf von Systemdiensten

10.2.2 Paradigmen der Systemaufrufschnittstelle


Für die Einbindung der Systemaufrufe in Nutzerprogramme kann man zwischen
den Ausführungs- und den Datenparadigmen unterscheiden.

Algorithmischer Ansatz

basiert auf der Idee, dass ein Programm eine bestimmte Funktion erfüllen soll, die
es im Voraus oder durch Parameter kennt.

• Basislogik ist im Code festgelegt


• Gelegentliche Systemaufrufe, um
Benutzereingaben zu erhalten
BS-Dienste in Anspruch zu nehmen

Beispiel
main () {
int ...;
init();
do_something();

read(...); /* Systemaufruf */
do_something_else();

write(...); /* Systemaufruf */
continue();
exit(0);
}

265
Schlichter, TU München 10.2. SCHNITTSTELLENENTWURF

Ereignis-basierter Ansatz

nach einer Initialisierung warten Programme dieses Ansatzes auf Ereignisse des
Betriebssystems

• Anwendungen reagieren auf Ereignisse

• Ereignisse werden durch BS erfasst und der Anwendung zugestellt

• Ereignisse sind z.B.


Tastendruck
Mausbewegung
Beim ereignis-basierten Ansatz stellt das Betriebssystem zwar ebenfalls
Dienste bereit, jedoch werden diese durch die Rolle als Koordinator und als
Generator von Ereignissen überdeckt.

Beispiel
main () {
mess_t msg;
init();
while (get_message(&msg)) {
case 1: ...;
case 2: ...;
case 3: ...;
......
}
}

Datenparadigma

Wie werden Systemstrukturen und Geräte im Betriebssystem gegenüber dem


Programmierer präsentiert?

Beispiel Unix

• "Alles" ist eine Datei

• Vereinheitlichung von Dateien, E/A-Geräte und Pipes

266
Schlichter, TU München 10.2. SCHNITTSTELLENENTWURF

• Zugriff über Dateioperationen


fd1 = open("file1", O_RDWR)
fd2 = open("/dev/tty", O_RDWR)
Nach dem Öffnen der Datei bzw. des Gerätes gibt es keinen Unterschied mehr,
abgesehen davon, dass auf einem Terminal kein Positionierungen möglich sind.

Beispiel Windows 2000

• "Alles" ist ein Objekt. Das Datenparadigma "Alles" ist ein Objekt ist
allgemeiner als jenes von Unix. Wenn ein Prozess ein gültiges Handle für
eine Datei, einen Prozess, ein Semaphor, eine Mailbox erhalten hat, kann er
Operationen darauf ausführen.

Systemaufrufschnittstelle

Entscheidung bzgl. der Bereitstellung unterschiedlicher Varianten von Systemauf-


rufen
Z.B. Lese-Systemaufruf: read_file, read_process, read_tty, . . . Soll für jede
dieser Variante ein eigener Systemaufruf an der Schnittstelle bereitgestellt
werden. Dies führt zu einer sehr unübersichtlichen Systemaufrufschnittstelle.

• Besser: nur Bereitstellung des allgemeinen Falls


Z.B. Lese-Systemaufruf: read
Restliche Varianten über Bibliotheksfunktionen auf den allgemeinen
Systemaufruf abbilden
• Sichtbarkeit von Systemaufrufen
Trennung von Systemaufrufen und Bibliotheksaufrufen
⇒ Ermöglicht übersichtliche Darstellung der vorhandenen Systemaufrufe
Unix hat eine wohl definierte Liste von Systemaufrufen, die jedem Program-
mierer zugänglich ist. Daraus ist für einen Programmierer ersichtlich, welche
Aufrufe teuer (Kernaufrufe) und welche günstig (Abarbeitung im Benutzerad-
dressraum) sind. Windows API stellt mehr als 13000 Aufrufe bereits, wobei
keine Differenzierung zwischen System- und Bibliotheksaufruf erfolgt.

267
Schlichter, TU München 10.3. WEITERE IMPLEMENTIERUNGSASPEKTE

10.3 Weitere Implementierungsaspekte


Neben den Diensten und deren Bereitstellung über die Systemaufrufschnittstelle
stellen die folgenden Implementierungsaspekte eine wichtige Rolle beim Entwurf
von Betriebssystemen.

10.3.1 Architektur
Ein etablierter und erprobter Architekturansatz sind geschichtete Systeme. Eng
verbunden mit dem Thread Management ist das Prozess Management und die
Interprozesskommunikation.

Systemaufrufbehandlung

Dateisystem 1 ... Dateisystem m

Virtueller Speicher (Paging)

Treiber 1 ... Treiber n

Threads, Thread Scheduling, Thread Synchronisation

Unterbrechungsbehandlung, Dispatcher, MMU

Abstraktion der Hardware (z.B. HAL von Windows)

Ein anderer Ansatz sind Client-Server Systeme mit einem Mikrokern und
ausgelagerten Serverprozessen. Dies erlaubt einen modularen, flexiblen Entwurf.

10.3.2 Mechanismen vs. Policies


Trennung von Mechanismen und Policies. Legt man die Mechanismen in das BS
und überlässt die Policy den Benutzerprozessen (bzw Systemprozessen), kann
das BS unverändert bleiben, auch wenn die Notwendigkeit besteht, die Policy zu
ändern.

• Beispiel: BS unterstützt Prioritätenbasierten Scheduler

268
Schlichter, TU München 10.3. WEITERE IMPLEMENTIERUNGSASPEKTE

Mechanismus: Feld gemäß absteigender Priorität sortiert; Scheduler durchsucht


Feld beginnend von der höchsten Priorität
Policy: Festlegen der Prioritäten

• Beispiel: BS unterstützt Paging für Arbeitsspeicher


Mechanismus: Verwaltung der Seiten-Kacheltabelle, MMU-Management,
Funktionen zum Transport der Seiten zwischen Festplatte und Arbeitsspeicher
Policy: welche Seiten werden ausgelagert bei Seitenfehler

10.3.3 Namensräume
Die meisten langlebigen Datenstrukturen eines BS haben einen Namen oder einen
Bezeichner zugeordnet, z.B. Login-Namen, Dateinamen, Gerätenamen, Prozess-
ID etc. Namen werden auf 2 Ebenen vergeben
extern: Namen, welche Menschen verwenden (z.B. Dateiname)
intern: Namen, welche das System verwendet (z.B. inode Nummer)
In einem guten Entwurf wird darüber nachgedacht,
wie viele Namensräume benötigt werden,
Welche Syntax sie haben,
Ob absolute und relative Namen existieren.
Directories bilden externe Namen auf interne Namen ab.
Externer Name: /usr/ast/books/mos2/Chap-12

Directory: /usr/ast/books/mos2 Inode - Tabelle


..
7
Chap-10 114 6
5
Chap-11 38
4
3
Chap-12 2
2
1

Interner Name: 2

269
Schlichter, TU München 10.3. WEITERE IMPLEMENTIERUNGSASPEKTE

10.3.4 Statische - Dynamische Datenstrukturen


Statische Strukturen sind einfacher und schneller, jedoch weniger flexibel als
dynamische Strukturen

• Beispiel Prozesstabelle:
Statisch: feste Prozesstabelle mit 256 Einträgen.
Dynamisch: Prozesstabelle als verkettete Liste.
Schnelle Suche in statischer Prozesstabelle. Falls ein 257. Prozess erzeugt
wird, ist der Aufruf nicht erfolgreich, da zu einem Zeitpunkt nur 256 Prozesse
existieren können.

• Statische Tabellen sind vernünftig


Wenn die Zahl der Einträge sehr gut vorausgesagt werden kann.
Weiterhin muss genügend großer Speicher vorhanden sein, damit ausreichend
Speicher für die Tabelle bereitgestellt werden kann. Auch bei Prozess-
Scheduling spielt Statik vs. Dynamik eine Rolle. Beispielsweise kann bei
Echtzeitsystemen das Scheduling von Prozessen gut vorausgesagt werden (z.B.
Multimediaprozessen). Bei interaktiven Prozessen ist dies i.a. nicht möglich.

10.3.5 Verbergen der Hardware


Die unterste Schicht, die Hardware Abstraction Schicht (z.B. HAL von Windows)
versucht Hardware-spezifische Eigenschaften zu verbergen

• Abfrage der Arbeitsspeichergröße zum Bootzeitpunkt


Speicherung in einer Variablen
CPU-abhängige bedingte Übersetzung. Generiert BS-Code abhängig von der
Besetzung der Variablen.
#include "config.h"
init()
{
#if (CPU == PENTIUM) /* Pentium initialization here */
#endif
#if (CPU == ULTRASPARC) /* ULTRASPARC initialization here
*/ #endif
... }

270
Schlichter, TU München 10.3. WEITERE IMPLEMENTIERUNGSASPEKTE

• Hardware-Architekturen unterstützen
unterschiedliche WortlängenCPU-abhängige bedingte Übersetzung. Generiert
BS-Code abhängig von der unterstützten Wortlänge.
#include "config.h"
{
#if (WORD_LENGTH == 32) typedef int Register; #endif
#if (WORD_LENGTH == 64) typedef long Register; #endif
Register R0, R1, ...;
In der Datei config.h werden die entsprechenden Variablen CPU und
Word_LENGTH abhängig von der jeweiligen Rechnerarchitektur geeignet
besetzt. Bei der Übersetzung des BS-Codes muss nur die geeignete config.h
Datei verwendet werden.

10.3.6 Speicherplatz vs. Laufzeit


Bei der Realisierung von Algorithmen besteht ein Abwägen zwischen Speicher-
platz und Laufzeit
Nutzung von Prozeduren ⇒ Aufwand für Prozeduraufruf
Nutzung von Makros ⇒ direkte Einbindung; kein Prozeduraufruf

• Beispiel: Prozedur, um die Bits mit Wert 1 in einem Byte zu zählen.


#define BYTE_SIZE 8 /* a byte contains 8 bits*/
int bit_count (int byte) {
int i, count=0;
for (i=0; i<BYTE_SIZE; i++) if((byte >> i) &1) count++;
return(count);
}
Die for-Schleife vergleicht jedes einzelne Bit, ob es eine 1 ist, indem es
den Bytewert um jeweils die entsprechende Stelle nach rechts schiebt. Eine
Prozedur hat mehrere Ineffizienzquellen:
bei Prozeduraufruf muss jeweils Kellerspeicher angelegt werden.
Schleifen sind aufwändig.

• Beispiel: Macro, um die Bits mit Wert 1 in einem Byte zu zählen.


Shiften des Arguments, Ausmaskieren aller Bits außer dem niederwertigen
Bit, Aufaddieren der 8 Terme
#define bit_count(b) (b&1) + ((b>>1)&1) + ((b>>2)&1) +
((b>>3)&1) + ((b>>4)&1) + ((b>>5)&1) + ((b>>6)&1) +
((b>>7)&1)

271
Schlichter, TU München 10.4. TRENDS BEIM ENTWURF VON BETRIEBSSYSTEMEN

Wenn das Macro im Code aufgerufen wird, erscheint sum=bit_count(byte); dies


sieht identisch wie ein Prozeduraufruf aus.

• Beispiel: Macro, um die Bits mit Wert 1 in einem Byte zu zählen.


Wert des Bytes ist Index in eine Tabelle mit 256 Einträge
Eintrag gibt die Anzahl der Bits von Wert 1 an
char bits[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1, ...};
#define bit_count(b) (int) bits[b];
Wenn das Macro im Code aufgerufen wird, erscheint sum=bit_count(byte); dies
sieht identisch wie ein Prozeduraufruf aus. In diesem Fall ist keine Berechnung
notwendig, sondern es erfolgt nur ein Nachsehen in der Tabelle.

10.4 Trends beim Entwurf von Betriebssystemen


Bedingt durch den vielfältigen Einsatz der Rechner sind die jeweiligen Trends von
unterschiedlicher Bedeutung

• BS mit großem Adressraum


Übergang von 32 Bit zu 64 Bit-Adressräumen
Adressraum von 2 * 1019 Bytes
Dies erfordert andere Ansätze zur Verwaltung des virtuellen Speichers;
herkömmliche Seitentabellen skalieren nicht gut für diese Größe. Dateien
könnten effektiv im virtuellen Speicher gehalten werden

• Netze werden die Grundlage für BS


Zugriff auf Web ist vollständig und nahtlos in BS integriert

• Bessere Unterstützung von parallelen und verteilten Systemen. Bisher erfolgt


die Unterstützung meist auf der Ebene von Middleware, d.h. nicht im
Betriebssystem selbst.

• BS für batteriebetriebene Computer (PDAs, Smart Phone, etc.)


Energiemanagement; Adaption von BS und Anwendungen je nach
Energieversorgung
Trend hin zu "Green Computing".

272
Schlichter, TU München 10.4. TRENDS BEIM ENTWURF VON BETRIEBSSYSTEMEN

• BS für eingebettete Systeme


Die Bezeichnung "Eingebettetes System" bezieht sich auf die Nutzung von
Computer Hardware und Software in einem Produkt. Unterscheidung nach
Anwendungsdomäne
Automobil, z.B. Zündung, Motorkontrolle, Bremssystem
Consumer Elektronik, z.B. Set-top Box, Küchengeräte, Kamera,
Smartphone
Medizinbereich, z.B. Dialysegerät, Infusionspumpe
Bürobereich, z.B. Faxgerät, Drucker
industrielle Nutzung, z.B. Roboter und Kontrollsysteme für Produktion

– Eingebettete Systeme sind eng gekoppelt mit dem Produkt, wobei die
Anforderungen sehr variieren können
Größe des Produkts, in das es eingebettet ist. Dies hat oft Konsequenzen
bzgl der Kosten des Systems oder erfordert oft unterschiedliche
Optimierungsansätze.
Lebensdauer. Manche Produkte haben eine sehr lange Lebensdauer, so
dass bzgl Aktualisierung bzgl. des BS nachgedacht werden muss. Andere
Produkte haben eine so kurze Lebensdauer, so dass ein Update zu
aufwändig ist.
Nutzungsumgebung. Welchen Umwelteinflüssen ist das eingebettete
System ausgesetzt, z.B. Strahlung, Vibration, Hitze, Luftfeuchtigkeit.
Realzeitverhalten.
– Es wurden eine Vielzahl von speziellen Betriebssystemen für eingebettete
Systeme realisiert
∗ für mobile Endgeräte: Symbian OS, Windows CE oder Android (URL:
[Link] von Google.
Android Systemarchitektur basiert auf Linux Kernel (Treiber,
Speicher-/Prozessmanagement); darauf existieren Bibliotheken (z.B.
für Graphik), eine Laufzeitumgebung und ein Anwendungsframework.
Das ganze Anwendungsframework ist geschrieben in Java. Alle An-
wendungen benutzen dieses Framework, egal ob sie von Google inte-
griert sind, oder von einem externen Entwickler geschrieben wurden.
Komponenten des Frameworks sind der Window Manager, Activity
Manager, der den Lebenszyklus der Anwendung kontrolliert.
∗ TinyOS
für drahtlose Sensornetze: TinyOS (URL: [Link] ent-
wickelt von der UC Berkeley

273
Schlichter, TU München 10.4. TRENDS BEIM ENTWURF VON BETRIEBSSYSTEMEN

zentraler Teil des BS ist sehr klein, ca. 400 Bytes Code und
Datenspeicher

Internet

Sensor Sensor
Relay Relay

Sensor
Relay

Host - PC Basis Sensor


Station

Sensor
Relay Sensor

◦ TinyOS hat keinen BS-Kern und keinen Speicherschutzmechanismus.


◦ komponenten-basierter Ansatz und ereignis-basiertes Ausführungsmo-
dell. Gleichzeitig stellt es auch eine Entwicklungsumgebung und Pro-
grammierplattform speziell für Hardwaresysteme mit knappen Ressour-
cen in Bezug auf Speicher, Rechenleistung und Energieverwendung dar,
welche autonom und sicher über Zeiträume von Monaten oder Jahren
zuverlässig funktionieren müssen.
geschichtete Anordnung der Komponenten; zwischen Komponenten be-
stehen Aufrufbeziehungen; elementare Komponenten kapseln Hardware
Komponenten (z.B. Timer).
Anwendungen werden durch Verknüpfung von Komponenten realisiert.
2 Arten von Komponenten: a) Module = implementieren Funktionen,
und b) Konfigurationen = beschreiben die Verknüpfung von Kompo-
nenten.
eine Komponente implementiert eine oder mehrere "tasks". Diese sind
vergleichbar mit Threads in üblichen BS; Innerhalb einer Komponente
sind tasks atomar, d.h. nach ihrem Start werden sie bis zum Ende
ausgeführt (kein Unterbrechung durch eine andere Task derselben
Komponente, z.B. aufgrund einer abgelaufenen Zeitscheibe). Die
Ausführung von Tasks kann jedoch durch Ereignisse unterbrochen
werden. Eine Task hat 3 Phasen: a) ein Aufrufer sendet ein Kommando
zu einem Modul, b) Modul führt die zugehörige Task aus, und c) der
Modul signalisiert das Ende der Task an den Aufrufer (Ereignis).

274
Schlichter, TU München 10.4. TRENDS BEIM ENTWURF VON BETRIEBSSYSTEMEN

TinyOS Scheduler realisiert die Ausführungsreihenfolge der tasks (z.B.


auf FIFO Basis).

275
Kapitel 11

Zusammenfassung

Diese Vorlesung beschäftigte sich mit den technischen Aspekten von Rechensy-
stemen. Es gab eine Einführung in Betriebssysteme und systemnahe Programmie-
rung. Insbesondere wurden folgende Aspekte behandelt:

• Modellierung von Prozessen, z.B. Petrinetze, sowie die Synchronisation von


Prozessen beim Zugriff auf gemeinsame Ressourcen.

• Verwaltung von Prozessen und deren Zuteilung an die CPU, um sie


auszuführen.

• Verwaltung des Arbeitsspeichers aus der Sicht des Betriebssystems (virtuelle


Speicherverwaltung, Seitenadressierung).

• persistente Speicherung von Information in Dateien.

• Prozesskommunikation in lokalen und verteilten Systemen.

• Verwaltung der Geräte.

• Sicherheit in Rechensystemen.

Der Entwurf und die Implementierung von Betriebssystemen ist komplex und
aufwändig. Wichtige Aspekte sind
definierte Abstraktionen, z.B. Prozesse, Threads, Adressraum
Definition von Schnittstellen zur Bereitstellung von Operationen, z.B.
Operation zur Synchronisation, persistente Speicherung von Information
Schnittstelle sollte einfach, vollständig und effizient sein.
Sicherstellen der Abgrenzung, z.B. Isolieren von Fehlern. Falls ein Benutzer-
prozess abstürzt, sollte es möglich den Rest des Systems fortzusetzen.

276
Schlichter, TU München

Verwalten der Hardware, z.B. Geräteverwaltung.


Festlegung der Paradigmen, z.B. Ausführungsparadigma, Systemaufruf-
schnittstelle, Speicherplatz vs. Laufzeit.

277

Das könnte Ihnen auch gefallen