Individuelles Projekt Konzeption eines Betriebssystem ... Inhalt 1 Einleitung 1 2 Grundlagen 3 ......

60
Fakultät II – Informatik, Wirtschafts- und Rechtswissenschaften Department für Informatik Individuelles Projekt Konzeption eines Betriebssystem-Programmierpraktikums auf Grundlage von iPosix vorgelegt von Mark Phlippen Gutachter: Prof. Dr.-Ing. Oliver Theel Dipl.-Inform. Christian Storm 31. August 2010

Transcript of Individuelles Projekt Konzeption eines Betriebssystem ... Inhalt 1 Einleitung 1 2 Grundlagen 3 ......

Fakultät II – Informatik, Wirtschafts- und RechtswissenschaftenDepartment für Informatik

Individuelles Projekt

Konzeption einesBetriebssystem-Programmierpraktikums auf

Grundlage von iPosix

vorgelegt von

Mark Phlippen

Gutachter:

Prof. Dr.-Ing. Oliver TheelDipl.-Inform. Christian Storm

31. August 2010

I

Zusammenfassung

Betriebssysteme sind ein wichtiges Forschungsgebiet der Informatik und eine wichtige Software-Komponente in jedem Rechner. Die Ziele in der Forschung sind es hierbei, insbesondere die Sicher-heit und Zuverlässigkeit der Systeme zu verbessern und die Mensch-Maschine-Kommunikation zuerleichtern. Daher bietet ein Programmierpraktikum für Betriebssysteme eine gute Gelegenheit, denStudierenden die bekannten theoretischen Konzepte zur Realisierung eines Betriebssystems in derPraxis näher zu bringen und das Verständnis für die betriebssysteminternen Abläufe zu fördern. Da-bei ist es von großer Wichtigkeit, die Abhängigkeiten, die die einzelnen Betriebssystemkomponentenuntereinander haben, zu beachten und in der Praxis zu realisieren, um einen reibungslosen Ablauf zuermöglichen. Das bereits vorhandene Betriebssystemepraktikum der Abteilung Systemsoftware undverteilte Systeme an der Carl von Ossietzky Universität vermittelt diese Dinge an die Studierendendurch das Lehrbetriebssystem OS/161 der Harvard University auf einer MIPS-Architektur auf Basisder Sprache C. In dieser Arbeit wird dieses Praktikum neu konzipiert, um es auf das modernere Lehr-betriebssystem iPosix auf der Intel x86-Architektur auf Basis der objektorientierten Sprache C++ zuübertragen. Diese Neukonzeption geschieht im Hinblick auf die sich wandelnden Bedingungen im In-formatikstudium und -alltag, in dem objektorientierte Programmiersprachen wie C++ immer größereVerbreitung finden und die Intel x86-Architektur insbesondere bei Heimrechnern sehr verbreitet ist.iPosix wurde 2009 im Rahmen einer Abschlussarbeit in der Abteilung Systemsoftware und verteilteSysteme entwickelt, um den Ansprüchen der Modernisierung zu genügen und darauf basiert dieseArbeit.

II

III

Inhalt

1 Einleitung 1

2 Grundlagen 32.1 Das Betriebssystempraktikum mit OS/161 . . . . . . . . . . . . . . . . . . . . . . . 32.2 iPosix - Ein objektorientierter Kern in C++ . . . . . . . . . . . . . . . . . . . . . . 3

3 Inhalte des Praktikums 53.1 Vorbedingungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.2 Einführung in C++ und die Intel x86-Architektur . . . . . . . . . . . . . . . . . . . 73.3 Einführung in iPosix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.4 Systemaufrufe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.5 Prozesszustandsmodell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.6 Synchronisation von Prozessen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.7 Schedulerstrategien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.8 Das Projekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

4 Begleitende Übung 154.1 Grundlegende Entscheidungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154.2 Aufbau einer Übung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174.3 Eine Lösung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

5 Fazit 31

Anhang 33

Glossar 41

Abkürzungen 47

Abbildungen 48

Literatur 50

Index 53

IV Inhalt

1

1 Einleitung

Im Rahmen dieser Arbeit werden viele Fachbegriffe verwendet, die im Betriebssystemekontext un-vermeidbar sind. Eine Erläuterung dieser Begriffe befindet sich im Glossar, das dieser Arbeit angefügtist. Ein Begriff, der im Glossar erläutert wird, ist mit dem Sympol ↑ gekennzeichnet.

Das Thema dieser Arbeit ist ein Musterentwurf für ein Programmierpraktikum mit ↑Betriebssystemenauf Basis des iPosix-Lehrbetriebssystems in C++.In diesem Praktikum soll den Studierenden vermittelt werden, wie grundsätzlich ein Betriebssystemaufgebaut ist und wie die einzelnen Komponenten, welche die Studierenden in vorangegangenen Ver-anstaltungen kennengelernt haben, ineinander greifen und sich gegenseitig beeinflussen können. Des-weiteren sollen die Studierenden lernen, ein vorhandenes Betriebssystem selbstständig zu erweiternund zu modifizieren, um den gestellten Anforderungen zu genügen. Die Basis hierfür bildet der imSommersemester 2009 im Rahmen eines individuellen Projektes in der Abteilung „Systemsoftwareund verteilte Systeme“ entwickelte iPosix-↑Kern [MT09]. Darauf aufbauend sollen den Studierendenschrittweise Aufgaben gestellt werden, die nach und nach den Betriebssystem-Kern in Funktionalitätund Komplexität erweitern. So sollen beispielsweise zunächst einfache ↑Systemaufraufe (siehe in Ab-schnitt 3), sogenannte Systemcalls, implementiert werden, um damit schließlich ↑Synchronisationskonzepte(siehe in Abschnitt 3) wie das ↑Mutex-Konzept oder das ↑Semaphor-Konzept einbinden zu können.Durch diese schrittweise Erweiterung wird berücksichtigt, dass die in den Aufgaben entwickeltenKomponenten hierarchisch aufeinander aufbauen und die Studierenden schließlich auf ein kleinesAbschlussprojekt vorbereiten.In der Vergangenheit wurde für dieses Praktikum das Lehrbetriebssystem OS/161 verwendet. Dieseseignet sich jedoch nicht so gut, da die Arbeit damit gewisse Schwierigkeiten mit sich bringt, welchebei iPosix nicht auftreten. Zum Einen ist OS/161 für die wenig verbreitete MIPS-Architektur entwi-ckelt, die den meisten Studierenden lediglich in der Theorie bekannt ist und zum Anderen basiertOS/161 auf der Sprache C, welche viele der heute üblichen Konzepte, wie objektorientierte Program-mierung, nicht unterstützt. Das Betriebssystem iPosix hingegen ist für die besonders bei Heimrech-nern verbreitete Intel x86-Architektur mit C++ entwickelt.Die Veranstaltung ist als ein Modul der Praktischen Informatik mit 6 Kreditpunkten nach ECTS-Standard konzipiert.

Die Gliederung dieser Arbeit entspricht der empfohlenen Reihenfolge bei der Bearbeitung des Prakti-kums. In Abschnitt 2 werden kurz die Grundlagen dieser Arbeit aufgeführt und die Vor- und Nachteileder Alternativen gegenübergstellt. Der Abschnitt 3 befasst sich dann mit den eigentlichen Inhalten desPraktikums in der Reihenfolge, in der sie von den Studierenden bearbeitet werden sollten. Der grund-legende Aufbau der jeweiligen Übungszettel, sowie ein exemplarische Musterlösung bilden Abschnitt4. Darauf folgt das abschließende Fazit.

2 Einleitung

3

2 Grundlagen

Diese Arbeit basiert vor Allem auf zwei Grundlagen. Zum Einen auf den Erfahrungen, die ich selbstim Betriebssystemepraktikum mit dem Lehrbetriebssystem OS/161 der Harvard University [Sys] ge-macht habe, zum Anderen auf dem Lehrbetriebssystem iPosix von Eike Möhlmann und Janko Tim-mermann der Abteilung Systemsoftware und verteilte Systeme an der Carl von Ossietzky UniversitätOldenburg [MT09]. Im Folgenden werden diese beiden Systeme kurz vor- und gegenübergestellt.

2.1 Das Betriebssystempraktikum mit OS/161

Im Rahmen meines Studiums habe ich an dem Betriebssystempraktikum auf Basis von OS/161 teil-genommen. OS/161 ist ein von der Harvard University entwickeltes Betriebssystem [Sys], welchesin der Lehre eingesetzt werden kann, um Studierenden die Möglichkeit zu bieten, aufbauend auf ei-nem sehr einfachen Basiskern, Erfahrungen im Programmieren auf Betriebssystemebene zu sammeln.Der Kern ist C geschrieben und das System ist für die MIPS-Architektur konzipiert. Es ist sehr gutgeeignet, um grundlegende Betriebssystemstrukturen zu vermitteln und den Studierenden die Mög-lichkeit zu bieten, damit zu experimentieren. Allerdings steht dem der Nachteil gegenüber, dass imAllgemeinen kaum MIPS-Architekturen zur Verfügung stehen und man somit auf Simulatoren an-gewiesen ist. Dies hat insbesondere zur Folge, dass gerade in der Anfangszeit des Praktikums vielZeit damit aufgewendet wird, die nötige Werkzeugumgebung zu installieren, welches sich als sehrfehleranfällig und teilweise frustrierend herausgestellt hat. Es muss dann besonders viel Zeit auf-gewendet werden, etwaige Fehler selbst zu identifizieren und zu beheben, wenn die Dokumentationdieser Werkzeuge nicht mit den tatsächlichen Gegebenheiten übereinstimmt. Ein weiterer Kritikpunktan OS/161 ist die mangelnde Modularität. Zwar wurde stets versucht, den Kern modular aufzubauen,so dass das Hinzufügen und Entfernen von Funktionalitäten zwar gut unterstützt ist, man jedoch oftan die Grenzen der Modularität stößt. Dies hat zur Folge, dass das Hinzufügen oder Entfernen vonbestimmten Teilen unnötig erschwert wird. Das liegt unter anderem daran, dass bestimmte grundle-gende ↑Assemblerroutinen auf das (Nicht-)Vorhandensein gewisser Komponenten angewiesen sind.Sollen eben diese Komponenten verändert oder ersetzt werden, so müssen zunächst die Assembler-routinen modifiziert werden. Dies führt unter Umständen zu Veränderungen in anderen abhängigenKomponenten, die dann ebenfalls angepasst werden müssen. Außerdem scheint in Zeiten von objekt-orientierten Sprachen wie Java oder C++ bzw. C# die Programmierung in C eher altertümlich und istfür den Praxisgebrauch weniger geeignet, da oft in der Lehre an Universitäten eben diese objektori-entierten Sprachen verwendet werden. Daher ist aus Gründen der Einfachheit ein Lehrbetriebssystemauf Basis einer objektorientierten Sprache gewünscht.

2.2 iPosix - Ein objektorientierter Kern in C++

iPosix ist ein Lehrbetriebssystem der Abteilung Systemsoftware und verteilte Systeme an der Carlvon Ossietzky Universität Oldenburg und wurde in C++ verfasst [MT09]. Es zeichnet sich vor Allemdadurch aus, dass hier die Möglichkeiten der objektorientierten Programmierung voll ausgeschöpftwurden, und somit das Hinzufügen und Entfernen von Komponenten deutlich leichter fällt. Dadurchkönnen sich die Studierenden auf die Kernaufgaben der Betriebssystemprogrammierung konzentrie-ren. Es muss weniger Zeit für Arbeiten in Anspruch genommen werden, die dafür sorgen, dass das

4 Grundlagen

System auf der Zielarchitektur läuft. Die Basisarchitektur für iPosix ist die gerade bei Heimrechnernoft verwendete x86-Architektur. Dadurch ist es sehr leicht möglich, iPosix auf real existierenden Sys-temen zu installieren und damit zu arbeiten. Ein Simulator ist nicht unbedingt notwendig, steht jedochzur Verfügung. Zudem ist iPosix so konzipiert, dass ein Umstieg auf x86-64 Architekturen mit ver-gleichweise geringem Aufwand möglich ist. Diese Aspekte sprechen für iPosix, da den Studierendendie Möglichkeit gegeben wir, die ihnen bekannten Konzepte der objektorientierten Programmierungvoll ausnutzen zu können. Dadurch wird die Einarbeitungszeit in die Basis des Systems reduziert,da nicht erst langwierig nachvollzogen werden muss, wie bestimmte Komponenten realisiert wurden,die mit objektorientierten Ansätzen wesentlich einfacher und effizienter realisiert werden können.Aufgrund dieser Gegenüberstellung spricht sehr viel dafür, den iPosix-Kern als Basis für die Ausar-beitung eines Betriebssystempraktiums zu verwenden.

5

3 Inhalte des Praktikums

Der folgende Abschnitt befasst sich mit den Einzelheiten eines möglichen Praktikums unter Verwen-dung von iPosix.In diesem Kapitel werden im Detail sämtliche Aufgaben erklärt und beschrieben, sowie die Reihen-folge, in der die Bearbeitung der Aufgaben sinnvoll ist. Die jeweilige Aufgabenbeschreibung teiltsich in einen technischen Teil und einen didaktischen Teil. Im ersten Teil wird erläutert, warum diejeweilige Aufgabe aus technischer Sicht an der entsprechenden Stelle sinnvoll ist, um darauf aufbau-end weitere Module hinzufügen zu können und im zweiten Teil wird dies nach didaktischen Kriterienbeurteilt und bewertet. Schließlich folgt eine Einschätzung meinerseits für den Zeitaufwand der je-weiligen Aufgabe. Als Basis dient der nachfolgende Abhängigkeitsgraph, in dem alle vorhandenenund geplanten Komponenten von iPosix abgebildet sind, die im Verlaufe des Praktikums relevantsind.Gelbe Komponenten sind soweit implementieren, dass damit bereits komplexe Aufgaben bearbeitet

Abbildung 3.1: Begleitender Abhängigkeitsgraph

werden können. Pinkfarbene Komponenten verfügen über eine gewisse Basisfunktionalität, so dassdas System als Ganzes lauffähig ist, da die Aufgaben der Komponenten dafür ausreichend erfüllt sind.

6 Inhalte des Praktikums

Zur Erfüllung komplexer Anwendungen müssen diese jedoch erweitert werden. Rote Komponentenfehlen völlig oder existieren lediglich als Platzhalter oder sogenannten Dummy.Es folgt eine kurze Beschreibung der Komponenten:

Systemaufrufe: Systemaufrufe stellen die Schnittstellen zwischen Anwendungsprogrammen undBetriebssystemkern dar. Sie werden meist von ↑Prozessen auf Anwenderebene verwendet, umOperationen ausführen zu können, die Kernrechte benötigen. Dazu zählen beispielsweise Opera-tionen, die den Inhalt des Speichers verändern. iPosix unterstützt bereits eine Reihe von System-aufrufen, andere fehlen allerdings noch (siehe hierzu in Abschnitt 3.4).

Prozesszustände: iPosix kennt derzeit nur die impliziten Prozessustände ready und running. Dasheißt, dass ein Prozess derzeit nur ablaufbereit sein kann oder die CPU zugeteilt bekommen hat.Um komplexere Anwendungen zu ermöglichen, muss das erweitert werden, da diese beiden Zu-stände zum Beispiel für die Bearbeitung von Ein- und Ausgabe-Prozessen (E/A) nicht ausreichen(siehe hierzu in Abschnitt 3.5).

Synchronisation: Die Synchronisation von Prozessen ist dann notwendig, wenn sich zwei oder mehrProzesse koordinieren können sollen. Dies kann der Fall sein, wenn ein Prozess für einen anderenBerechnungen durchführt, oder wenn zwei Prozesse auf dieselbe Festplatte warten. Zwar könnenbei iPosix mehrere Prozesse ausgeführt werden, diese können jedoch noch nicht miteinander kom-munizieren oder in irgendeiner Form aufeinander abgestimmt werden (siehe hierzu in Abschnitt3.6).

Scheduling: Das Scheduling beschreibt die Fähigkeit eines Betriebssystems, mehrere Prozesse zeit-gleich verwalten und nach bestimmten Kriterien ausführen zu können. iPosix unterstützt bereitsmehrere Prozesse, verwendet jedoch noch keine ausgereiften Strategien, die Ablaufreihenfolge derProzesse effizient zu gestalten (siehe hierzu in Abschnitt 3.7).

Virtueller Speicher: Die Speicherverwaltung von iPosix baut auf dem ↑physikalischen Speicherauf. Zwar gibt es bereits einen rudimentären ↑virtuellen Speicher, der jedoch noch über keiner-lei ↑Seitentauschstrategien verfügt und derzeit nur direkt adressierten Speicher verwendet.

Dateisystem: Das Dateisystem von iPosix in der derzeitigen Fassung ist rein virtueller Natur. Dasheißt, dass es keine wirklichen physikalischen Ordner- und Dateistrukturen gibt, auf denen dasSystem arbeitet. Es existiert eine rudimentäre Realiserung des FAT-Dateisystems (siehe [Mic]),welches jedoch noch nicht alle Funktionalitäten beinhaltet.

Anwendungsprogramme: iPosix verfügt zwar über eine Reihe von Anwendungsprogrammen, diejedoch noch keine wirklichen Aufgaben erfüllen und zu Testzwecken bestimmt sind. So existiertzum Beispiel eine ↑Shell, die bei Systemstart gestartet werden kann und nach der Ausgabe von einpaar Textzeilen sich selbst und iPosix wieder beendet. Auch kann derzeit noch nicht zur Laufzeitbestimmt werden, welche Programme starten sollen. Die Benutzung eines Programmes ist der-zeit nur möglich, wenn das Ausführen des Programmes bereits vor Systemstart im Quelltext desBetriebssystems festgelegt wurde.

Insbesondere die letzten drei Punkte können in Kombination oder einzeln als Abschlussprojekt (sieheAbschnitt 3.8) für das Praktikum in Betracht gezogen werden.

3.1 Vorbedingungen 7

3.1 Vorbedingungen

Um an diesem Praktikum mit Erfolg teilnehmen zu können, sollten die Studierenden mit objektori-entierter Programmierung vertraut sein und grundlegende Funktionalitäten eines Betriebssystems inder Theorie verstanden haben und beherrschen. Für den Veranstaltungsplan der Carl von OssietzkyUniversität Oldenburg bedeutet das, dass die Studierenden wenigstens am „Programmierkurs Java“,sowie an „Betriebssysteme 1“ mit Erfolg teilgenommen haben sollten. Die Veranstaltungen „Be-triebssysteme 2“, „Verteilte Betriebssysteme“, sowie „Algorithmen und Programmieren“ und „Algo-rithmen und Datenstrukturen“ sind empfohlen. Der „Programmierkurs Java“ wird benötigt, damit dieStudierenden mit dem Konzept der objektorientierten Programmierung vertraut sind und ein Umstiegauf C++ nicht so schwer fällt, wie das unter Umständen komplette Neuerlernen einer Programmier-sprache.

3.2 Einführung in C++ und die Intel x86-Architektur

Da iPosix auf die Intel x86-Architektur aufbaut, sollen die Studierenden sich im Vorfeld des Prakti-kums oder unmittelbar zu Semesterbeginn zunächst damit vertraut machen. Dies ist besonders wich-tig, wenn sie im späteren Verlauf des Praktikums in maschinennaher Ebene arbeiten müssen, um diegestellten Aufgaben zu erfüllen. Hierfür müssen sie die Architektur ausreichend kennen und verste-hen, wie die Architektur aufgebaut ist. iPosix ist in C++ verfasst und das Beherrschen dieser Spracheist notwendig, um den Quelltext zu verstehen und zu erweitern. Daher sollen sich die Studierenden imAnschluss mit C++ vertraut machen. Dies geschieht zunächst dadurch, dass die Studierenden einengegebenen Quelltext lesen und verstehen sollen, um anschließend selbst einen kleinen ↑Algorithmuszu implementieren.Die geforderten Algorithmen werden in der Schwierigkeitsstufe von einfachen Sortiermechanismenwie ↑Bubblesort angesiedelt sein. Diese sollten die Studierenden grundsätzlich beherrschen, um mög-lichst wenig Zeit damit aufzubringen, die geforderten Algorithmen zu verstehen. Wenn die Studieren-den bereits vorher wissen, wie sich die Algorithmen verhalten sollten, fällt es leichter, diese in einerunter Umständen unbekannten Sprache zu implementieren.

Hintergrund dieser Aufgabe ist es, dass sich die Studierenden an C++ gewöhnen können. So wirdgewährleistet, dass im weiteren Verlauf des Praktikums möglichst wenig Zeit damit aufgewendetwerden muss, sich in C++ zurecht zu finden. So können sich die Studierenden effektiv mit den gege-benen Problemstellungen auf Betriebssystemebene auseinander setzen.Geschätzter Zeitaufwand: Eine Woche

3.3 Einführung in iPosix

Im Vorfeld dieser Aufgabe wird den Studierenden eine Anleitung gegeben, mit der sie den iPosix-Kern samt Simulator auf ihren Rechnern installieren und starten.Den Studierenden werden dann einfache Fragen zum vorhandenen Quelltext des iPosix-Kerns ge-stellt. Diese können sie beantworten, in dem sie sich in die Dokumentation und den Quelltext desKerns einlesen. Dies fördert das Verständnis dafür, welche Aufgabe einzelne Programmklassen oder-routinen erfüllen.Es folgt eine kurze Liste möglicher Fragen:

8 Inhalte des Praktikums

• Was machen die Systemaufrufe (Syscalls) x, y, z?

• Was geschieht bei Systemstart?

• Welche Aufgaben haben die bei Systemstart initialisierten Komponenten und wie heißen sie?

• Kann diese Reihenfolge geändert werden? Begründen Sie.

• Welche Aufgaben haben die Klassen a, b, c?

• Wie wird vom Kern-Modus in den Benutzer-Modus gewechselt - und umgekehrt?

Schließlich soll der Kern des Systems derart erweitert werden, dass er bei Systemstart die ersten↑Primzahlen bis 100 ermittelt, ausgibt und sich anschließend wieder beendet. Damit sollen die Stu-dierenden in die grundlegende Struktur von iPosix eingeführt werden. So lernen sie, an welchenStellen des Quelltextes sie ansetzen können und müssen, um die gewünschten Effekte zu erzielen.

Diese Einführung soll sicherstellen, dass sich die Studierenden mit dem Kern befassen, bevor siebeginnen, willkürlich Änderungen vorzunehmen. Dies ist notwendig, um späteren Verständnispro-blemen vorzubeugen.Geschätzter Zeitaufwand: Eine Woche

3.4 Systemaufrufe

In diesem Übungsabschnitt sollen die Studierenden die noch nicht implementierten Systemaufrufeumsetzen und testen. Dazu sollen sie zunächst die bereits implementierten Systemaufrufe analysieren.Durch die Analyse erlangen sie die Erkenntnis, wie Systemaufrufe aufgebaut sind und funktionieren,um schließlich die Fehlenden zu realisieren. Die Funktionen der fehlenden Systemaufrufe mkdir,rmdir, getcwd, chdir, sync, halt, pipe, dup2 und putenv sind folgende1:

mkdir(path): Erstellt ein neues Verzeichnis, dessen Name mit path übergeben wird.

rmdir(path): Löscht das Verzeichnis path.

getcwd: Gibt das aktuelle Arbeitsverzeichnis zurück.

chdir(path): Wechselt das aktuelle Arbeitsverzeichnis in das mit path übergebene.

sync: Synchronisiert die Puffer mit der Festplatte.

halt: Hält das System an.

pipe(a): Erstellt eine ↑pipe für a.

dup2(a, b): Dupliziert einen Dateihandler a und schreibt ihn an b.

putenv: Setzt eine Umgebungsvariable.

1 Ausdrücke in Klammern geben Parameter an, die an den Systemaufruf übergeben werden müssen.

3.5 Prozesszustandsmodell 9

Diese Systemaufrufe werden im weiteren Verlauf des Praktikums benutzt, um komplexere Anwen-dungen zu realisieren.

Mit der Erfüllung dieser Aufgabe erhalten die Studierenden recht früh Erfolgserlebnisse, da derSchwierigkeitsgrad dieser Aufgabe eher gering einzuschätzen ist. Darüberhinaus sind die System-aufrufe auch ein wichtiger Bestandteil des Betriebssystems, ohne die viele Funktionalitäten nichtgeboten werden können.Geschätzter Zeitaufwand: Zwei Wochen

3.5 Prozesszustandsmodell

Das Prozesszustandsmodell von iPosix besteht in der Grundversion aus den Zuständen running undready, welche jedoch nicht explizit voneinander unterschieden werden. Sie ergeben sich implizit dar-aus, dass zu jedem Zeitpunkt nur ein Prozess einen ↑CPU-Kern besetzen kann. Die Studierendenhaben also die Aufgabe, die vorhandenen Prozesszustände zu dem aus der Veranstaltung „Betriebs-systeme 1“ bekannte Prozesszustandsmodell zu erweitern [The09].Die Realisierung der Prozesszustände inactive, ready, running, sowie blocked und der dazugehörigen

Abbildung 3.2: Prozesszustandsmodell nach Vorlesung BS 1 [The09]

↑Dispatcheroperationen initiate, assign, resign, block, deblock und terminate ist Inhalt dieser Übung.Die Studierenden haben hierbei die Aufgabe, zu bestimmen, an welcher Stelle diese Zustände undOperationen implementiert werden müssen und wo und wie sie angesprochen werden müssen.Dabei sollen die Implementierungen der Prozesszustände folgende Funktionalitäten beinhalten:

inactive: Ein Prozess, der sich im Zustand inactive befindet, existiert de facto nicht. Er belegt kei-nerlei Speicher und bekommt auch keine Prozessorzeit zugesprochen. Dem Scheduler und demDispatcher ist ein Prozess, der inactive ist, nicht bekannt. Dieser Prozess kann durch das Ladenseiner Ausführungsdatei (↑ELF) gestartet werden und wird in den Zustand ready überführt.

ready: Im Zustand ready verweilt ein Prozess und wartet darauf, die CPU zu erhalten. Er ist ablauf-bereit und wartet weder auf ↑Ressourcen noch auf andere Prozesse.

10 Inhalte des Praktikums

running: In diesem Zustand befindet sich zu jedem Zeitpunkt je CPU-Kern genau ein Prozess. Einrunning-Prozess führt seine Operationen durch.

blocked: Im Zustand blocked befinden sich alle Prozesse, die auf bestimmte Ereignisse warten. ImGegensatz zu Prozessen, die in ready warten, können diese Ereignisse unterschiedlicher Natursein. So können Prozesse zum Beispiel auf andere Prozesse warten, oder auf Daten, die von einerFestplatte gelesen werden. Deswegen sind die Prozesse meist in unterschiedlichen Warteschlangeneingereiht, die der Natur des Ereignissen entsprechen, auf das die Prozesse warten.

Die Implementierung der Übergangsfunktionen sollte folgende Kriterien erfüllen:

initiate: Ein Prozess wird initialisiert und gestartet. Die dazugehörige Ausführungsdatei (ELF) wirdgeladen und der Prozess wird dem Zustand ready zugeordnet. Außerdem muss der Prozess undsein Kontext dem System bekannt gemacht werden.

assign Durch den Aufruf von assign wird ein ablaufbereiter Prozess an die CPU übergeben underhält Rechenzeit. Er befindet sich dann im Zustand running und führt die Operationen gemäßseines Programms durch.

resign Mittels resign wird einem Prozess die CPU entzogen. Befindet sich dadurch kein Prozessmehr im running-Zustand, muss im Anschluss assign ausgeführt werden.

block: Mit block kann ein Prozess blockiert werden. Dies ist zum Beispiel notwendig, wenn einProzess auf E/A-Operationen warten muss. Der Prozess wird in den Zustand blocked überführtund es muss auch hier assign ausgeführt werden, da sich sonst kein Prozess mehr in runningbefindet.

unblock: unblock wird meist von dem Ereignis ausgelöst, auf das ein Prozess im blocked-Zustandgewartet hat. Der wartende Prozess wird in den Zustand ready überführt und nimmt nun wiederam Scheduling teil.

terminate: Durch den Aufruf von terminate beendet sich ein laufender Prozess. Der verbrauchteSpeicher wird wieder freigegeben und der Prozess wird aus dem System entfernt. Im Anschlussmuss wieder assign ausgeführt werden, damit die CPU in Benutzung bleibt. Ein Sonderfall vonterminate ist der bereits implementierte Systemaufruf kill. Hier kann terminate für einen ande-ren, nicht laufenden Prozess ausgeführt werden. Daher muss dann auch assign nicht ausgeführtwerden.

Die Implementierung des Prozesszustandsmodells wird benötigt, um im weiteren Verlauf des Prakti-kums Synchronisationskonzepte einfacher entwickeln zu können.

Diese Aufgabe erfordert mehr Interoperabilität zwischen den einzelnen Komponenten und kann durchVerwendung der zuvor implementierten Systemaufrufe gelöst werden. Sie hat zum Ziel, bei den Stu-dierenden das Verständnis für Dispatcher-Operationen im konkreten Kontext eines Betriebssystemeszu fördern. Die Studierenden sollen erkennen, dass auf dieser Basis ein einfaches, aber vollständigesBetriebssystem entwickelt werden kann.Geschätzter Zeitaufwand: Zwei Wochen

3.6 Synchronisation von Prozessen 11

3.6 Synchronisation von Prozessen

Die Studierenden sollen einige bekannte Konzepte zur Synchronisation von Prozessen implementie-ren. Es soll mit zwei einfachen Prozessen die Lösung eines kleinen Erzeuger-Verbraucher-Problems(siehe [STM10]) implementiert werden. Prozess A soll hierbei die Aufgabe des Erzeugers überneh-men, der eine Zeile Text erzeugt. Die Textzeile soll Prozess B auf dem Bildschirm ausgeben. Dabeisollen die beiden Prozesse nicht streng abwechselnd laufen. Die Studierenden haben zunächst dieAufgabe die beiden Prozesse zu implementieren. Im Anschluss sollen sie die Prozesse mit Hilfe desbereits entwickelten Prozesszustandsmodells, insbesondere mittels blocked, und der Systemaufrufederart synchronisieren, dass alle erzeugten Zeilen ausgegeben werden. Hierbei soll kenntlich gemachtwerden, welche Instanz von Prozess A bzw. B die Zeile erzeugt bzw. verbraucht hat.Der zweite Teil der Aufgabe ist die Lösung des ersten Leser-Schreiber-Problem nach [CHP71].

Es gibt in iPosix zwar noch keine Priorisierung von Prozessen, aber es wird deutlich, dass ↑Priorisierungnotwendig sein kann, da es schnell zu Ablaufproblemen, wenn schnellere Prozesse auf langsamerewarten müssen, bzw. wenn hochpriorisierte Prozesse auf solche mit niedrigerer Priorität warten müs-sen. Ein Prozess, der hauptsächlich Berechnungen durchführt, die nur die vergleichsweise schnelleCPU benötigen könnte auf Daten warten, die ein E/A-Prozess beispielsweise von einer relativ langsa-men Festplatte liest. Muss der CPU-Prozess nun lange auf den E/A-Prozess warten, kann das gesamteSystem unter Umständen stark verlangsamt werden, wenn nicht entsprechende Mechanismen existie-ren, die diese Wartezeit sinnvoll ausfüllen.

Die Studierenden können mit diesen Aufgaben erfahren, wie Interprozesskommunikation in der Pra-xis funktioniert und lernen, dass es wichtig ist, darauf zu achten, inwieweit die Prozesse miteinanderagieren. Dies soll das Verständnis für die Implementierung von Synchronisationskonzepten in einemkonkreten Betriebssystem fördern.Geschätzter Zeitaufwand: Zwei Wochen

3.7 Schedulerstrategien

Das Ziel dieser Aufgabe besteht darin, dem Betriebssystem mehrere Methoden zum Scheduling vonProzessen zur Verfügung zu stellen. iPosix benutzt derzeit ein einfaches ↑Round-Robin-Verfahren(RR). Die Studierenden sollen dies um einige weitere Strategien erweitern.Mögliche Strategien sind ↑Highest Priority First (HPF), ↑Shortest Remaining-Time First (SRTF) oder↑First in - First Out (FIFO). Möglich ist es auch, diese Strategien verdrängend zu gestalten, so dassein Prozess, der gerade die CPU hält durch einen anderen verdrängt werden kann, wenn dies notwen-dig ist. Zur Realisierung dessen werden die zuvor entwickelten Systemaufrufe benötigt, sowie dieRealisierung des Prozesszustandmodells, inbesondere der Übergänge assign und resign.Mit Abschluss dieser Aufgabe verfügt das System über Mechanismen zur Unterstützung mehrererAnwendungen, der Kommunikation zwischen Prozessen und mehrere Methoden zum Scheduling.Auch wenn es noch keinen vollständigen virtuellen Speicher mit Seitentausch gibt und das Datei-system virtueller Natur ist und nur wenige Grundfunktionalitäten zur Verfügung stellt, kann das Be-triebssystem in gewissem Rahmen nun komplexere Aufgaben bewältigen.

Dieser Fortschritt soll die Studierenden motivieren, sich nun mit dem Abschlussprojekt des Prak-

12 Inhalte des Praktikums

tikums zu befassen, bei dem sie selbstständig das Betriebssystem erweitern sollen.Geschätzter Zeitaufwand: Zwei Wochen

3.8 Das Projekt

Der zu Beginn eingeführte Abhängigkeitsgraph stellt sich nun in der Form von Abbildung 3.3 dar.Neben den in Abbildung 3.1 eingeführten Farben, stellen grüne Objekte vollständig implementierte

Abbildung 3.3: Abhängigkeistgraph vor Beginn des Projektes

Komponenten dar. Dabei ist das Scheduling noch als gelb markiert, da in der entsprechenden Aufga-be nur eine bestimmte Auswahl an Schedulingstrategien implementiert wurde. Wünschenswert wäreeine dynamische Auswahl der Strategie je nach Bedarf und Systemzustand.Natürlich können bereits erste Anwendungsprogramme ohne das Vorhandensein von virtuellem Spei-cher mit Seitentausch und einem echten Dateisystem entwickelt werden. Diese müssen dann jedochso konzipiert werden, dass sie vollständig im Speicher liegen. Dies ist insbesondere dann schwierig,wenn eine unbekannte Anzahl von größeren Prozessen verwaltet werden muss. Ohne das Vervollstän-digen des Dateisystems sind auch nur stark eingeschränkte E/A-Operationen denkbar.

3.8 Das Projekt 13

Im Anschluss an diese Aufgaben, sollen die Studierenden sich nun ein Abschlussprojekt für das Prak-tikum aussuchen. Einige Möglichkeiten für ein solches Projekt wurden bereits von Eike Möhlmannund Janko Timmermann ausgedacht ([MT09], s.69ff):

Gemeinsame Bibliotheken: Gemeinsame Bibliotheken, also Routinen, die von allen Programmengenutzt werden können, sind bislang in iPosix nicht realisiert. Hierbei muss insbesondere der ELF-Lader erweitert werden, um gemeinsame Bibliotheken an ausführbare Programme zu binden.

Dateisysteme: iPosix verfügt zur Zeit über ein virtuelles Dateisystem und eine rudimentäre Imple-mentierung des FAT-Dateisystems [Mic]. Dies könnte erweitert werden. Es wäre aber auch mög-lich, ein komplett anderes Dateisystem zu realisieren, wie beispielsweise Minix [Hea00] oder ext2[CTT95].

Virtueller Speicher mit Seitentausch Der aktuell von iPosix realisierte virtuelle Speicher unter-stützt keinen Seitentausch. Die von den Prozessen verwendeten Speicherbereiche sind derzeitdirekt addressiert. Somit sind Anwendungen, die mehr Speicher benötigen, als physikalisch zurVerfügung steht, nicht möglich.

Anwendungsprogramme: Wie eingangs in Kapitel 3 erwähnt, gibt es für iPosix derzeit keine kom-plexen Anwendungsprogramme. Hier können sich die Studierenden eine Anwendung ihre Wahlüberlegen, die sie auf iPosix portieren möchten. Als Basisanwendung würde sich für ein solchesProgramm eine Shell anbieten, mit der das Betriebssystem verwaltet werden kann und Programmevom Benutzer zur Laufzeit gestartet werden können. Allerdings sind auch andere Anwendungendenkbar, die evtl. aus anderen Betriebssystemen bekannt sind und auf iPosix übertragen werdenkönnten.

Natürlich kann den Studierenden hier die Möglichkeit eingeräumt werden, sich selbst ein Projektthe-ma zu überlegen. Dabei muss bei Bedarf entschieden werden, ob es dem geplanten Umfang gerechtwird.Gegebenenfalls kann auch überlegt werden, ob zu Beginn des Projektes allen Studierenden dieselbeBetriebssystemversion zur Verfügung gestellt wird, um zu gewährleisten, dass alle Studierenden aufgleicher Grundlage arbeiten können. Dies muss allerdings bei Bedarf entschieden werden, insbeson-dere dann, wenn eine oder mehrere Gruppen mit der Bearbeitung der einzelnen Aufgaben Schwie-rigkeiten hatten und so eventuell die Anforderungen einer oder mehrerer Aufgaben nicht oder nurunzureichend erfüllt haben. Natürlich hätte dies auch zur Folge, dass sich die Studierenden in dieneue Version erst einarbeiten müssten, da sie den entsprechenden Quelltext nicht selbst verfasst hät-ten. Dies muss dann in der Bearbeitungszeit für das Projekt berücksichtigt werden. Aus Gründen derChancengleichheit sollte daher eine Betriebssystemversion zur Verfügung stehen, die allen Studie-renden unbekannt ist und die alle bisherigen Anforderungen erfüllt.Die Bearbeitungszeit des Projektes sollte etwa drei bis vier Wochen betragen.

3.8.1 Abschluss des Praktikums

Der Abschluss des Praktikums wird durch eine Präsentation und Erläuterung des Projektes gebil-det. Hierbei sollen die Studierenden ihre Projekte den Betreuenden präsentieren. Die Präsentationenkönnen je nach Projektart und -fortschritt aus einer Direktvorführung des Betriebssystems mit den

14 Inhalte des Praktikums

integrierten Ergebnissen der Projektarbeit oder einem Folienvortrag bestehen. Eine Kombination bei-der Methoden ist auch möglich. Die Bewertung des Moduls kann sich nach einer Dokumentationrichten, die die Studierenden im Verlaufe der Projektarbeit erstellen, in der deutlich wird, wem dieeinzelnen im Projekt erbrachten Leistungen anzurechnen sind. Im Anschluss an die Projektpräsentati-on kann eine mündliche Prüfung der jeweiligen Gruppe erfolgen. Dies entspricht den Anforderungender Carl von Ossietzky Universität Oldenburg aus [Cara], Anlage 11b, sowie [Carb], §11, Absätze2, 6 und 8. Es sind auch andere Prüfungsformen für dieses Modul denkbar. Dazu müsste jedoch diefachspezifische Anlage der Prüfungsordnung verändert werden.

15

4 Begleitende Übung

4.1 Grundlegende Entscheidungen

Die Übungszettel werden im Zyklus von ein bis zwei Wochen an die Studierenden ausgegeben. Da-zu finden wöchentliche Treffen mit den BetreuerInnen statt. In diesen Treffen werden die Aufgabendes aktuell ausgegeben Übungszettels besprochen, um eventuelle Fragen zu klären. Außerdem wer-den die Lösungen des letzten abgegebenen Zettels besprochen, um etwaige Implementierungsfehleroder -besonderheiten zu besprechen. Auch wenn zu einem Treffen kein neuer Zettel ausgegeben wirdoder keiner abgegeben werden muss, sollte das Treffen dennoch statt finden, um eventuelle Fragenzu klären, die im Verlauf der Arbeit an dem aktuellen Zettel entstanden sind und bei der Ausgabe desentsprechenden Zettels noch nicht bekannt oder klar waren. Die Treffen sollten je nach Bedarf ein biszwei Stunden dauern.Die Bearbeitung der Übungszettel sollte in Kleingruppen von jeweils zwei bis drei Studierendenerfolgen. Diese Gruppierungen ermöglichen gewisse Synergiereffekte unter den Studierenden undverhindern, dass einzelne Studierende mit der Bearbeitung bestimmter Aufgaben oder Aufgabenteileüberfordert werden könnten. Größere Gruppen sollten nicht gebildet werden, da sonst für die ein-zelnen Studierenden zu wenig individuelle Arbeit vorgesehen wäre, so dass der Aufwand für sechsKreditpunkte zu gering wäre. Außerdem steigt bei größeren Gruppen die Gefahr, dass einzelne Stu-dierende versuchen, die Arbeit auf andere zu verteilen und mit möglichst wenig Aufwand das Modulzu bestehen. Desweiteren erzeugen größere Gruppen zu viel Kommunikationsaufwand, um beispiels-weise Absprachen und Arbeitsaufteilungen zu koordinieren. Ein weiterer Aspekt, der für Gruppenvon zwei bis drei Studierenden spricht ist der, dass solche Gruppen laut Prüfungsordnung (s. [Carb])gemeinsam an einer mündlichen Prüfung teilnehmen können. Sollten sich unter den teilnehmendenStudierenden welche befinden, die bereits mit C++ vertraut sind, so sollten diese nach Möglichkeitgleichmäßig auf die Gruppen verteilt werden, so dass keine Gruppe benachteiligt ist.Jeder Übungszettel besteht im Wesentlichen aus vier Teilen:

Teil 0 - Grundinformationen: Vorweg hat jeder Übungszettel einige Überschriften, in denen einigeGrundinformationen zum jeweiligen Zettel zu finden sind.

Modul und Semester: Hier ist der Name des Moduls zu finden, sowie das aktuelle Semester, indem es stattfindet.

Name des/der Betreuenden: Dieses Feld beinhaltet den oder die Namen der Personen, der/diedie Studierenden bei dem Praktikum betreuen.

Übungsblattnummer: Die Übungsblattnummer gibt die Nummer der aktuellen Übung an. Hierwird mit der Nummer 0 begonnen, da sich der erste Übungszettel, also Zettel 0, mit einlei-tenden Inhalten befasst und im eigentlichen Sinne nicht Teil des Lernstoffes des Praktikumsist.

Ausgabedatum: Das Datum der Ausgabe des Zettels an die Studierenden.

Abgabedatum und -uhrzeit: Dies ist der Zeitpunkt, an dem die Ergebnisse der Studierendenzum jeweiligen Übungszettel an den oder die BetreuerInnen ausgehändigt werden müssen.Die Bearbeitungszeit pro Zettel beträgt je nach Umfang und Schwierigkeitsgrad ein bis zweiWochen.

16 Begleitende Übung

Teil 1 - Einleitung: Ein kurzer einleitender Text soll die Studierenden auf die vor ihnen liegen-den Aufgaben vorbereiten. Es wird beschrieben, was die zu behandelnden Probleme sind undwas durch deren Lösung erreicht werden kann. Hinzu kommt stets der Bezug zu einem rea-len Betriebssystem, um das Verständnis für die vor ihnen liegenden Aufgaben, als auch für dieFunktionsweisen von Betriebssystemen, weiter zu fördern. Dieser Bezug stellt sich so dar, dassgezeigt wird, in welchen Bereichen die zu implementierenden Komponenten bei bekannten Be-triebssystemen wie ↑Windows oder ↑Linux Anwendung finden.

Teil 2 - Aufgabenbeschreibung: Bei Zetteln, die aus mehreren Aufgabenblöcken bestehen, wirdhier der zu bearbeitende Aufgabenblock beschrieben. Es wird die Problemstellung erläutert undRanddaten, die zum Lösen der folgenden Aufgaben notwendig sind, zur Verfügung gestellt. BeiÜbungszetteln, die sich nur mit einem Aufgabenblock befassen, wird dies in Teil 1 mit integriert.

Teil 3 - Aufgaben: In diesem Teil werden den Studierenden die konkreten Aufgaben gestellt. Diesereichen von einfachen Fragen bis hin zu komplexen Implementierungsaufgaben. Teilweise kanndas Lösen einer Aufgabe notwendig sein, um die nachfolgenden bearbeiten zu können. Die Num-merierung der einzelnen Fragen ist zettelintern von 1 bis n, um somit schnellere Referenzen zuden einzelnen Teilaufgaben bilden zu können, um somit die Kommunikation zwischen den Stu-dierenden bei der Bearbeitung der Aufgaben und mit Studierenden und BetreuerInnen bei derBesprechung der Aufgaben zu erleichtern.

Diese Einteilung ist so gewählt, damit die Studierenden alle Hintergrundinformationen erhalten, dienotwendig sind, um die gestellten Aufgaben zu bewältigen. Dabei sollen Teil 1 und 2 die Studieren-den motivieren, sich mit den gegebenen Aufgaben zu befassen, indem gezeigt wird, wozu das Lösendieser Aufgaben - auch im Hinblick auf den weiteren Verlauf des Praktikums - notwendig ist.Die Kopfzeile der ersten Seite eines jeden Zettels beinhaltet die Universitäts- und Fakultätszugehörig-keit. Diese Information ist für die Studierenden an sich nicht wichtig, ist allerdings von Bedeutung,wenn die Übungszettel durch das Internet zugreifbar sind und somit auch für Außenstehende ver-fügbar sind. Die Kopfzeilen der nachfolgenden Seiten sind mit dem Namen des Moduls und derÜbungsblattnummer versehen.In den Fußzeilen ist lediglich die Seitenummer der jeweils aktuellen Übungsblattseite zu sehen.Dieses Grunddesign der Übungszettel orientiert sich insbesondere am Design der Übungszettel derAbteilung Systemsoftware und verteilte Systeme des Departments für Informatik, Fakultät II, der Carlvon Ossietzky Universität Oldenburg, kann bei Bedarf jedoch geändert werden.

Bei der Abgabe der Übungen wird empfohlen, ein ↑Versionskontrollsystem wie SVN oder CVS zuverwenden. Dies verhindert zum Einen seitenweise ausgedruckten Programmquelltext, dessen Kon-trolle ohne technische Hilfsmittel sehr aufwendig ist, und zum Anderen stark frequentierte E-Mail-Postfächer bei den Betreuenden. Außerdem vereinfacht dies auch die Zusammenarbeit unter den Stu-dierenden in den Kleingruppen, insbesondere wenn diese räumlich getrennt voneinander arbeiten.Die Kontrolle, ob die Aufgaben zum gesetzten Stichtermin erfüllt wurden, kann darüber erfolgen,dass die Betreuenden lediglich die Versionen herunterladen, die bis zum entsprechenden Stichtermineingestellt worden sind.

4.2 Aufbau einer Übung 17

4.2 Aufbau einer Übung

Im Folgenden wird Übungszettel 0 vorgestellt. Dabei ist zunächst stets ein Ausschnitt aus dem Übungs-zettel zu sehen und im Anschluss daran werden die in diesem Ausschnitt abgebildeten Inhalte erläu-tert. Zur besseren Unterscheidung ist der Inhalt des Übungszettels eingerahmt.Der vollständige Übungszettel 0 befindet sich im Anhang (siehe Kapitel 5). Im digitalen Anhangbefindet sich zudem die Vorlage der Übungszettel für ↑LaTeX.

4.2.1 Einleitung

Betriebssysteme übernehmen einen wichtigen Teil in modernen Rechensystemen. Sie verwal-ten alle anstehenden Aufgaben und moderieren die Kommunikation von Benutzer und Maschine.In diesem Programmierpraktikum sollen Sie Ihre theoretischen Kenntnisse über Betriebssystemein der Praxis anwenden. Sie werden hier lernen, wie ein Betriebssystem im Detail aufgebaut ist,wie die einzelnen Komponenten ineinandergreifen und worauf zu achten ist, wenn man Verände-rungen am System vornehmen möchte. Natürlich wäre es schön, wenn am Abschluss des Prak-tikums ein vollständiges, modernes Betriebssystem das Ergebnis wäre. Leider ist dies jedochim Rahmen der Zeit eines Semesters und des Arbeistaufwandes eines Moduls nicht möglich.Sie werden mit dem im Rahmen einer Abschlussarbeit an der Universität Oldenburg entwickel-ten Lehrbetreibssystem iPosix der Abteilung Systemsoftware und verteilte Systeme arbeiten. Inder Auslieferungsversion beherrscht iPosix lediglich rudimentäre Aufgaben und die meisten ausvergangenen Vorlesungen bekannten Betriebssystemekomponenten sind kaum oder gar nicht im-plementiert. Ihre Aufgabe im kommenden Semester ist es, dieses Betriebssystem zu erweiternund zu vervollständigen.iPosix wurde für die Intel x86-Architektur entwickelt und ist in der Programmiersprache C++geschrieben. Da ein Betriebssystem oft sehr maschinennah arbeiten muss, um seine Aufgabeneffizient lösen zu können, werden Sie sich zunächst mit der Intel x86-Architektur vertraut ma-chen und anschließend ein wenig in C++ eintauchen. In Ihrem vergangenen Studium haben Siebisher kaum oder gar nicht mit C++ gearbeitet. Es handelt sich hierbei zwar bereits um eineobjektorientierte Sprache, so dass sie viele von Java bekannte Konzepte semantisch umsetzenkönnen, jedoch bedient sich C++ oftmals einer anderen Syntax.Daher ist der zweite Teil dieser Einführung in das Praktikum eine Einarbeitung in die Besonder-heiten von C++. Sollten Sie bisher noch nicht objektorientiert programmiert haben, sollten Siesich in dieses Konzept einarbeiten. Sie finden dazu entsprechende Literatur in der Universitätsbi-bliothek.

Erläuterung

Die Übung beginnt mit einer Einleitung in die Thematik, was in diesem Fall eine Einstimmung aufdas gesamte Praktikum darstellt. Die Studierenden werden an das Thema herangeführt und erhalteneine Motivation, warum die Inhalte der Übung für sie und den weiteren Praktikumsverlauf wichtigsind. In diesem Fall heißt das, dass die Studiereden darüber informiert werden, welche Aufgaben sieim Groben erwartet und womit sie in den nächsten Wochen arbeiten werden. Sie haben somit Ge-legenheit, sich auf das Kommende vorzubereiten und in die Thematik einzuarbeiten, gegebenenfallsWissenslücken zu füllen und in der Vergangenheit Gelerntes wieder aufzufrischen. Übungsblatt 0 ist

18 Begleitende Übung

dafür vorgesehen, bereits in der vorlesungsfreien Zeit vor Semesterbeginn ausgegeben zu werden,damit die Studierenden sich selbstständig einarbeiten können und die Zeit während der Vorlesungennicht damit aufgewendet werden muss, die Wissensangleichung unter den Studierenden zu vollziehen,so dass unmittelbar zu Semesterbeginn mit der eigentlichen Arbeit am Betriebssystem iPosix begon-nen werden kann. Die Ergebnisse dieses Übungszettels müssen nicht abgegeben werden, damit diesnicht zum Motivationsblocker für jene Studierenden wird, die sich bereits mit der Thematik „C++“und „x86-Architektur“ befasst haben und damit vertraut sind. Somit haben die Studierenden, die sichnoch mit diesen Themen befassen müssen, die Aufgabe, sich eigenverantwortlich einzuarbeiten.

4.2.2 Aufgabe 1 - Die Intel x86-Architektur

Die Intel x86-Architektur wird den meisten von Ihnen insofern bekannt sein, da sie die Ba-sis für die meisten heutigen Heimrechner bildet. Im Gegensatz zu Ihren bisherigen Arbeiten mitInformationssystemen werden sie in diesem Praktikum teilweise sehr maschinennah program-mieren. Daher ist es wichtig, dass Sie sich zunächst mit der Architektur vertraut machen und ihreEigenarten und Besonderheiten kennenlernen. Die benötigten Informationen finden Sie hier: Linkeinfügen (ArchBeschr.pdf). Die darin referenzierten Quellen sind folgende:

[BC01] Daniel P. Bovet und Marco Cesati: „Understanding the Linux Kernel“

[Int] http:/www.intel.com/design/processor/applnotes/317080.pdf

[Int88] http://pdos.csail.mit.edu.6.828/2005/readings/hardware/8259A.pdf

[Int01] http://bos.asmhackers.net/docs/ata/docs/29860001.pdf

[Int09a] http://www.intel.com/Assets/PDF/manual/253665.pdf

[Int09b] http://www.intel.com/Assets/PDF/manual/253668.pdf

Erläuterung

Nach der Einleitung sollen sich die Studierenden in der ersten Aufgabe mit der Intel x86-Architekturbefassen. Hierzu steht ihnen einen Auszug aus „iPosix - Ein objektorientierter Kernel in C++“ [MT09]zur Verfügung, der die für das Betriebssystemepraktikum relevante Architekturbeschreibung enthält.Der Auszug umfasst das Kapitel 3 „Architekturbeschreibung“. Die in diesem Kapitel referenzeirtenQuellen werden den Studierenden ebenfalls zur Verfügung gestellt, damit sie sich bei Bedarf ein-gehender informieren können. Zu diesem Abschnitt gibt es keine konkrete Aufgabenstellung, außerdem Lesen des Kapitels. Dies ist damit begründet, dass die Studierenden sich eigenverantwortlich indas Thema einarbeiten können und eine Abgabe des Zettels und somit eine schriftliche Überprüfungdes Wissens nicht erfolgt. Allerdings ist dies eine gute Möglichkeit für die Betreuenden, das Gelernteim Ausgabetreffen für Übung 1 abzufragen, indem zum Beispiel einfache Fragen zur Architekturbe-schreibung gestellt werden. Neben den folgenden Fragen sind noch weitere denkbar.

• Welche Funktion hat das Flag-Register?

4.2 Aufbau einer Übung 19

• Wozu dienen Task-State-Segmente?

• Worin unterscheiden sich geschützter und ungeschützter Modus?

• Wie ist eine lineare Adresse aufgebaut?

Eine Diskussion dieser Fragen in der gesamten Gruppe aller teilnehmenden Studierenden hat denVorteil, dass so auch jene Studierenden von dem Wissenstransfer profitieren können, die sich nurunzureichend mit der Übung 0 beschäftigt haben.

4.2.3 Aufgabe 2 - Einführung in C++

Da iPosix in C++ verfasst ist und Sie in Ihrem bisherigen Studium kaum oder gar nicht mitdieser Sprache gearbeitet haben, sollten Sie sich ein wenig mit den Besonderheiten dieser Spra-che vertraut machen. Der nachfolgende C++-Code weist einige der Besonderheiten auf, mit derSie im Verlauf des Praktikums konfrontiert werden. Nachdem Sie den Code nachvollzogen ha-ben, müssen Sie diesen erweitern. Es handelt sich hierbei um einen Sortieralgorithmus, der Ih-nen aus „Algorithmen und Datenstrukturen“, „Algorithmen und Programmieren“ oder aus dem„Programmierkurs Java“ bekannt sein sollte. In der Universitätsbibliothek finden Sie darüber-hinaus eine Reihe von Programmiersprachenlehrbüchern, die sich mit C++ befassen. Natürlichgibt es auch mehrere Einführungen im Internet zu finden, deren Qualität jedoch nicht gesichertist. Sollten Sie also bei der Bearbeitung dieser Aufgabe oder im weiteren Verlauf des Prakti-kums Schwierigkeiten mit C++ bekommen, wird Ihnen empfohlen, sich entsprechende Literaturzu leihen und darin nachzuschlagen oder Ihre Kommilitonen zu fragen. Nach Bearbeitung dieserAufgabe sollten Sie grundsätzlich in der Lage sein, einem Dritten kurz die wichtigsten Elementedieses Programms zu erklären.

/∗Aufgabe 00In d i e s e 125 Z e i l e n wurden so z i e m l i c h a l l e" G e m e i n h e i t e n " der Sprache C++ gepack t , denen S i ei n n e r h a l b von i P o s i x begegnen werden :∗ P r a e p r o z e s s o r :

− Makros− b e d i n g t e K o m p i l i e r u n g− Kons tan ten−D e k l a r a t i o n

∗ Eigene T y p d e f i n i t i o n e n∗ Z e i g e r :

− Z e i g e r a r i t h m e t i k− F u n k t i o n s z e i g e r− A e q u i v a l e n z von Z e i g e r a u s d r u e c k e n

Nachdem S i e den Q u e l l t e x t u e b e r s e t z t , a u s p r o b i e r tund n a c h v o l l z o g e n haben , i m p l e m e n t i e r e n S i e d i e F u n k t i o n" b u b b l e _ s o r t _ n u m b e r s _ p t r " . Den Bubb leSor t−A l g o r i t h m u s s o l l t e nS i e n a t u e r l i c h b e r e i t s kennen , g g f . koennen S i e I h r Wissenaber durch A n a l y s e der F u n k t i o n " b u b b l e _ s o r t _ n u m b e r s _ a r r a y "a u f f r i s c h e n :−)

20 Begleitende Übung

P r a e p r o z e s s o r : g++ −E −DDEBUG −o uebung00 . i uebung00 . cppK o m p i l i e r e n : g++ −S −g −O0 −o uebung00 . s uebung00 . iA s s e m b l i e r e n : g++ −c −o uebung00 . o uebung00 . sL i nk en : g++ −o uebung00 uebung00 . oA u s f u e h r e n : uebung00

∗ /# i n c l u d e < s t d i o . h># i n c l u d e < s t d l i b . h>

# d e f i n e MAX 5

# d e f i n e p r i n t v a l u e ( a , b ) p r i n t f ( " a r r a y : %d | d y n a r r a y : %d \ n " , a , b ) ;

/ / # d e f i n e DEBUG# i f d e f DEBUG# d e f i n e DBGOUT( t e x t ) f p r i n t f ( s t d e r r , ">>DBG( l i n e %d ) : %s \ n " , __LINE__

, t e x t )# e l s e# d e f i n e DBGOUT( t e x t ) do {} whi le ( 0 )# e n d i f

t y p e d e f enum{FALSE = 0 , TRUE = 1} b o o l e a n ;

s t a t i c vo id s t r u c t _ t e s t ( ) {s t r u c t ko o r ds {

i n t x , y ;} p o s i t i o n ;s t r u c t ko o r ds ∗ p t r p o s = &p o s i t i o n ;p t r p o s −>x = 0 ;p o s i t i o n . x = 0 ;(∗ p t r p o s ) . x = 0 ;DBGOUT( " i c h b i n i n d e r f u n k t i o n \ " s t r u c t _ t e s t \ " " ) ;

}

s t a t i c vo id p r i n t _ a r r a y ( i n t f e l d 1 [ ] , i n t f e l d 2 [ ] ) {i n t l oop2 ;i n t ∗p = f e l d 1 ;f o r ( loop2 =0; loop2 <MAX; loop2 ++){

p r i n t v a l u e (∗ p ++ , f e l d 2 [ loop2 ] ) ;}

}

s t a t i c vo id b u b b l e _ s o r t _ n u m b e r s _ a r r a y ( i n t f e l d [ ] ) {i n t o u t e r , i n n e r ;f o r ( o u t e r =1; o u t e r <MAX; o u t e r ++){

f o r ( i n n e r =0; i n n e r <MAX−1; i n n e r ++){i f ( f e l d [ i n n e r ] > f e l d [ i n n e r + 1 ] ) {

i n t buf = f e l d [ i n n e r ] ;f e l d [ i n n e r ] = f e l d [ i n n e r + 1 ] ;

4.2 Aufbau einer Übung 21

f e l d [ i n n e r +1] = buf ;}

}}

}

s t a t i c vo id b u b b l e _ s o r t _ n u m b e r s _ p t r ( i n t ∗ f e l d ) {/ / j e t z t s i n d S i e g e f r a g t !

}

/∗ ∗∗ @param f e l d [ ] Array , aus dem d i e e r s t e n max Elemen te a d d i e r t∗ werden∗ @param max wie v i e l e E l e l e m e t e s o l l e n a d d i e r t werden ?∗ @memo a d d i e r t d i e e r s t e n max Elemen te aus dem Array f e l d [ ]∗ @doc d i e F u n k t i o n add_numbers a d d i e r t aus dem uebergebenem∗ Array f e l d [ ] d i e e r s t e m max Elemen te und g i b t s i e der∗ a u f r u f e n d e n I n s t a n z z u r u e c k∗ /

s t a t i c i n t add_numbers ( i n t f e l d [ ] , i n t max ) {i n t loop3 , r e t v a l = 0 ;

f o r ( loop3 =0; loop3 <max ; loop3 ++){ r e t v a l += f e l d [ loop3 ] ; }re turn r e t v a l ;

}

i n t main ( i n t argc , char ∗ a rgv [ ] ) {i n t loop1 , r a n d w e r t ;i n t n u m b e r s _ a r r [MAX] ;i n t ∗ n u m b e r s _ a r r _ p t r = &n u m b e r s _ a r r [ 0 ] ;

void (∗ s t r u c t _ p t r ) ( ) ;

i n t ∗ n u m b e r s _ p t r = ( i n t ∗ ) malloc (MAX∗ s i z e o f ( i n t ) ) ;

f o r ( loop1 =0; loop1 <MAX; loop1 ++){r a n d w e r t = rand ( )%100;n u m b e r s _ a r r [ loop1 ] = r a n d w e r t ;∗ ( n u m b e r s _ a r r + loop1 ) = r a n d w e r t ;∗ ( n u m b e r s _ a r r _ p t r + loop1 ) = r a n d w e r t ;∗ ( n u m b e r s _ p t r + loop1 ) = r a n d w e r t ;

}p r i n t f ( " A r r ay s ∗ vor ∗ d e r S o r t i e r u n g : \ n " ) ;p r i n t _ a r r a y ( numbers_a r r , n u m b e r s _ p t r ) ;

b u b b l e _ s o r t _ n u m b e r s _ a r r a y ( n u m b e r s _ a r r ) ;b u b b l e _ s o r t _ n u m b e r s _ p t r ( n u m b e r s _ p t r ) ;

p r i n t f ( " \ n A r r ay s ∗ nach ∗ d e r S o r t i e r u n g : \ n " ) ;p r i n t _ a r r a y ( numbers_a r r , n u m b e r s _ p t r ) ;

22 Begleitende Übung

p r i n t f ( " \ n E r g e b n i s : %d \ n " , add_numbers ( numbers_a r r , 3 ) ) ;

s t r u c t _ p t r = s t r u c t _ t e s t ;s t r u c t _ p t r ( ) ;

re turn 0 ;}

Die Funktion add_numbers() ab Zeile 81 ist mit Doxygen kommentiert. Es wird empfohlen,dass Sie in Ihrer Arbeit ebenfalls Doxygen verwenden. Eine Übersicht über Doxygen und einekurze Einführung darin finden Sie auf der Webseite von Doxygen.iPosix ist ebenfalls durchgehend mittels Doxygen kommentiert.

Erläuterung

In dieser Aufgabe ist den Studierenden ein kurzer Abschnitt von C++-Quelltext gegeben, den sie ana-lysieren und modifizieren sollen. Das damit erstellte Programm soll zwei Felder (oder auch Arrays)der Länge MAX mit Zufallszahlen füllen, so dass beide Felder identisch befüllt sind. Im Anschlusssollen diese Felder mit Hilfe des Bubble-Sort-Algorithmus sortiert werden. Die beiden Felder un-terscheiden sich derart, dass das Feld numbers_arr direkt angesprochen wird, während auf das Feldnumbers_ptr mit ↑Zeigern (oder auch Pointer) zugegriffen wird. Nachdem die Felder befüllt sind,werden sie in ihrer aktuellen Ordnung auf dem Bildschirm ausgegeben.Nach der Ausgabe werden die Felder mittels Bubble-Sort sortiert. Dabei ist die Methodebubble_sort_numbers_ptr für die Sortierung des Feldes numbers_ptr noch nicht implementiert. DieImplementierung dessen ist Aufgabe der Studierenden. Im Anschluss daran werden die Felder erneutausgegeben, diesmal jedoch im sortierten Zustand. Daraufhin werden die ersten drei Elemente desFeldes numbers_arr addiert und die Summe ausgegeben, gefolgt von einer Meldung des ↑Debuggers.Der Bubble-Sort-Algorithmus gehört zu den einfachen Sortieralgorithmen und sollte den Studieren-den bereits aus Grundlagenveranstaltungen wie dem „Programmierkurs Java“ bekannt sein. Aus die-sem Grund wird hier dieser Algorithmus verwendet, damit die Studierenden möglichst wenig Arbeitdamit aufbringen müssen, einen neuen Algorithmus zu lernen und zu verstehen. So kann in dieserAufgabe vollkommen auf die Besonderheiten von C++, inbesondere im Vergleich zu Java, eingegan-gen werden. Dies zeigt sich in der Fokussierung auf das Zeiger-Konzept, welches in Java vollkommenunbekannt ist, da bei Java bewusst auf die Verwendung dieses Konzepts verzichtet wurde[Ull06].Der Hinweis, dass die Studierenden in der Lage sein sollten, einem Dritten das Programm zu erklä-ren, soll die Studierenden darauf vorbereiten, dass in der Nachbesprechung des Zettels einige Fragenzum Quelltext gestellt werden könnten. Der Verweis auf die Lehrbücher der Universitätsbibliotheksoll den Studierenden eine Hilfestellung bei der Einarbeitung in C++ bieten.

4.2.4 Aufgabe 3 - Den x86-Assembler verstehen

Bei der Entwicklung eines Betriebssystems ist es oftmals notwendig, dass maschinennaheoder sehr zeitkritische Abschnitte in Assemblersprache implementiert sind. Zwar werden Sieim Verlaufe des Praktikums nur sehr wenig oder gar keinen Assemblercode selbst schreiben

4.3 Eine Lösung 23

müssen, aber da einige Komponenten von iPosix in Assemblercode verfasst sind, sollten Sie denAssembler wenigstens in den Grundzügen verstehen, um diese Komponenten nachvollziehen zukönnen. Legen Sie hierzu Ihren Fokus auf die Funktion add_numbers ab Zeile 88 aus Aufgabe 2.

1) Generieren Sie für vier Optimierungsstufen den Compilers vier verschiedeneAssemblerausgaben jeweils mit dem Flag:

1a) -S -O01b) -S -O11c) -S -O21d) -S -O3

Versuchen Sie zunächst, den generierten Assemblercode der Funktion add_numbers() mit Op-timierungsstufe 0 zu verstehen. Vergleichen Sie dies im Anschluss mit den anderen drei Optimie-rungsstufen. Achten Sie insbesondere darauf, wie die Funktion add_numbers() jeweils optimiertwird, und wie Übergabe- und Rückgabeparameter behandelt werden.Sollten Sie über kein x86-System verfügen, nutzen Sie die Rechner in der ARBI. Achten Siedabei darauf, dass auch hier nicht alle Rechner auf der x86-Architektur aufbauen. Weitere Opti-mierungsoptionen für den g++-Compiler finden Sie in der man-Page zum g++ unter „OptimizingOptions“.

Aufgabe 3 befasst sich mit einigen Optimierungsstufen des C++-Übersetzers (oder auch Compiler).Hierbei sollen die Studierenden das Quellprogramm mit vier verschiedenen Optimierungsstufen über-setzen und anschließend den daraus resultierenden Assemblerquelltext analysieren. Dazu soll dieFunktion add_numbers dienen, da es sich hierbei um eine vergleichsweise simple Funktion handelt,deren Funktionsweise schnell erfasst ist. So können sich die Studierenden vollkommen auf den As-semblerquelltext konzentrieren und müssen nicht erst aufwendig analysieren, was genau die Funktionadd_numbers im Detail macht. Das Verstehen des Assemblers ist notwendig, da gewisse Komponen-ten von iPosix ebenfalls in Assemblersprache implementiert sind.

4.3 Eine Lösung

Dieser Abschnitt beinhaltet einen exemplarischen Lösungsvorschlag für den oben vorgestellten Übungs-zettel 0. Es handelt sich hierbei nicht um die einzig richtige Lösung, da es insbesondere im Bereichder Programmierung viele verschiedene Möglichkeiten gibt, ein Problem korrekt zu lösen.

Aufgabe 1 - Die Intel x86-Architektur

Bei dieser Aufgabe wurden keine konkreten Fragen gestellt. Daher folgen nun die möglichen Ant-worten für die beispielhaft genannten Fragen, welche im Rahmen der wöchentlichen Treffen gestelltwerden können. Weitere Fragen und deren Antworten lassen sich aus [MT09], Kapitel 3, ableiten.

24 Begleitende Übung

Welche Funktion hat das Flag-Register? Das Flag-↑Register beinhaltet diverse Felder zur Einstel-lung und zum Status des Prozessors. Bei iPosix wird das Flag-Register in erster Linie zur Deakti-vierung und Aktivierung von ↑Unterbrechungen (oder auch Interrupts) verwendet.

Wozu dienen Task-State-Segmente? Task-State-Segmente beschreiben den Zustand eines Ausfüh-rungskontextes und werden unter Anderem zum Speichern und Laden des Ausfürhungskontextesbenutzt. So ist eine Steuerung der Verwaltung von Programmen auf Hardware-Ebene möglich.

Worin unterscheiden sich geschützter und ungeschützter Modus? Im ungeschützten Modus ist1 MiB Speicher direkt adressierbar und es kann von allen Programmen darauf zugegriffen wer-den. Im geschützten Modus hingegen werden Paging und Segmentierung unterstützt, so dass aufbis zu 4 GiB Hauptspeicher im 32-bit-Modus zugegriffen werden kann.

Wie ist eine lineare Adresse aufgebaut? Eine lineare Adresse besteht aus drei Teilen. Directorygibt den Offset innerhalb des Seitenverzeichnisses an, Table den Offset innerhalb der Seitenta-belle und Offsett den Offset zur physikalischen Adresse innerhalb der Seite.

Aufgabe 2 - Einführung in C++

Nach dem die im Eingangskommentar des Quelltextes stehenden Instruktionen ausgeführt wurden(Zeilen 22-26), sollte in der Eingabekonsole folgendes stehen1:

Arrays *vor* der Sortierung:array:41 | dynarray:41array:67 | dynarray:67array:34 | dynarray:34array:0 | dynarray:0array:69 | dynarray:69

Arrays *nach* der Sortierung:array:0 | dynarray:41array:34 | dynarray:67array:41 | dynarray:34array:67 | dynarray:0array:69 | dynarray:69

Ergebnis: 75>>DBG(line54): ich bin in der funktion "struct_test"

1 Da es sich um Zufallswerte handelt, können die Zahlen abweichen.

4.3 Eine Lösung 25

Eine Möglichkeit, die Methode bubble_sort_numbers_ptr zu implementieren, ist diese:

76 s t a t i c vo id b u b b l e _ s o r t _ n u m b e r s _ p t r ( i n t ∗ f e l d ) {77 i n t o u t e r , i n n e r ;78 f o r ( o u t e r =1; o u t e r <MAX; o u t e r ++){79 f o r ( i n n e r =0; i n n e r <MAX−1; i n n e r ++){80 i f ( ∗ ( f e l d + i n n e r ) > ∗ ( f e l d + i n n e r + 1 ) ) {81 i n t buf = ∗ ( f e l d + i n n e r ) ;82 ∗ ( f e l d + i n n e r ) = ∗ ( f e l d + i n n e r + 1 ) ;83 ∗ ( f e l d + i n n e r +1) = buf ;84 }85 }86 }87 }

Bei dieser Implementierung werden im Gegensatz zu bubble_sort_numbers_array nicht die Wertedes Feldes verändert und vertauscht, sondern die Zeiger auf die Zellen des Feldes, so dass sich einekorrekte Sortierung des Feldes ergibt. Die Variable inner wird dazu verwendet, um alle Zellen vonfeld zu erreichen und durch outer wird dieser Vorgang MAX-1-mal wiederholt, wobei MAX der Längedes Feldes entspricht (s. Zeile 103-109 im Basisprogramm).In Zeile 80 wird mit Hilfe des Stern-Operators(*) auf die Werte an den Speicheradresse feld+innerund feld+inner+1 zugegriffen und die darin enthaltenen Werte miteinander verglichen. Dies ent-spricht dem Vergleich der Werte von feld[inner] und feld[inner+1] aus der Methodebubble_sort_numbers_array. Ist bei diesem Vergleich der Werte an Adresse feld+inner der Grö-ßere, wird der Wert davon in der Variable buf gesichert (Zeile 81). Danach wird der an Adressefeld+inner+1 gespeicherte Wert auf die Adresse feld+inner kopiert (Zeile 82) und zum Schluss derin buf gesicherte Wert auf die Adresse feld+inner+1 geschrieben (Zeile 83).Die Korrektheit dieser Methode ist auch an der Ausgabe des modifizierten Programms zu erkennen:

Arrays *vor* der Sortierung:array:41 | dynarray:41array:67 | dynarray:67array:34 | dynarray:34array:0 | dynarray:0array:69 | dynarray:69

Arrays *nach* der Sortierung:array:0 | dynarray:0array:34 | dynarray:34array:41 | dynarray:41array:67 | dynarray:67array:69 | dynarray:69

Ergebnis: 75>>DBG(line54): ich bin in der funktion "struct_test"

Die letzte Zeile wird nur dann ausgegeben, wenn wieder die einzelnen Schritte auf dem Übungs-blatt ausgeführt werden. Bei der Standardeinstellung des Übersetzers fehlt diese.Bei der Besprechung dieser Aufgabe können seitens der Betreuenden an die Studierenden Fragen zum

26 Begleitende Übung

Programm gestellt werden. Dadurch kann ermittelt werden, ob die Studierenden verstanden haben,was in dem Quelltext im Detail geschieht. Darüber hinaus helfen diese Fragen den Studierenden, diesich nicht ausreichend mit der Problematik befasst haben, den Quelltext zu verstehen.

Aufgabe 3 - Den x86-Assembler verstehen

Wie zu Aufgabe 1 und 2 können auch hier bei der Besprechung Fragen an die Studierenden ge-stellt werden. Hierbei sollten diese insbesondere die Unterschiede zwischen den Optimierungsstufender Funktion add_numbers betreffen. Die Funktion add_numbers gestaltet sich in den vier Optimie-rungsstufen folgendermaßen2:

-S -O0 Auszug aus der entstandenen Assembler-Datei mit Optimierungsstufe 0:

.stabs "_Z11add_numbersPii:f(0,3)",36,0,89,__Z11add_numbersPii

.stabs "feld:p(11,2)",160,0,89,8

.stabs "max:p(0,3)",160,0,89,12

.def __Z11add_numbersPii; .scl 3; .type 32; .endef__Z11add_numbersPii:.stabn 68,0,89,LM40-__Z11add_numbersPiiLM40:

pushl %ebpmovl %esp, %ebpsubl $8, %esp

LBB19:LBB20:.stabn 68,0,90,LM41-__Z11add_numbersPiiLM41:

movl $0, -8(%ebp).stabn 68,0,91,LM42-__Z11add_numbersPiiLM42:

movl $0, -4(%ebp)L25:

movl -4(%ebp), %eaxcmpl 12(%ebp), %eaxjge L26movl -4(%ebp), %eaxleal 0(,%eax,4), %edxmovl 8(%ebp), %eaxmovl (%edx,%eax), %edxleal -8(%ebp), %eaxaddl %edx, (%eax)leal -4(%ebp), %eaxincl (%eax)

2 Diese Quelltexte können ggfs von einer weiteren Ausführung auf einem anderen Rechner leicht abweichen.

4.3 Eine Lösung 27

jmp L25L26:.stabn 68,0,92,LM43-__Z11add_numbersPiiLM43:

movl -8(%ebp), %eaxLBE20:LBE19:.stabn 68,0,93,LM44-__Z11add_numbersPiiLM44:

leaveret.stabs "loop3:(0,3)",128,0,90,-4.stabs "retval:(0,3)",128,0,90,-8.stabn 192,0,0,LBB20-__Z11add_numbersPii.stabn 224,0,0,LBE20-__Z11add_numbersPii

Lscope5:.stabs "",36,0,0,Lscope5-__Z11add_numbersPii

Der Funktionsaufruf dieses Assemblerquelltextes erfolgt an späterer Stelle mit

LM62:movl $3, 4(%esp)leal -56(%ebp), %eaxmovl %eax, (%esp)call __Z11add_numbersPiimovl %eax, 4(%esp)

Unter dem Bezeichner LM62 werden zunächst die Register für den Funktionausaufruf beladenund schließlich wird mit dem Befehl call die Funktion aufgerufen. Die eigentliche Funktionalitätvon add_numbers befindet sich unter Bezeichner L25. Die übrigen Anweisungen werden dazubenötigt, den Kontext des Hauptprogrammes zu sichern. In der letzten Zeile unter BezeichnerLM62 wird schließlich das Ergebnis in das Register esp zurück geschrieben.

-S -O1 Auszug aus der entstandenen Assembler-Datei mit Optimierungsstufe 1:

.def __Z11add_numbersPii; .scl 3; .type 32; .endef__Z11add_numbersPii:

pushl %ebpmovl %esp, %ebppushl %ebxmovl 8(%ebp), %ebxmovl 12(%ebp), %ecxmovl $0, %eaxmovl $0, %edxcmpl %ecx, %eaxjge L54

L52:

28 Begleitende Übung

addl (%ebx,%edx,4), %eaxincl %edxcmpl %ecx, %edxjl L52

L54:popl %ebxpopl %ebpret

Der Funktionsaufruf dieses Assemblerquelltextes erfolgt an späterer Stelle mit

movl $3, 4(%esp)movl %ebx, (%esp)call __Z11add_numbersPiimovl %eax, 4(%esp)

Hier zeigt sich, dass insbesondere die Ausführung der Funktion wesentlich kompakter ist. DieKernfunktionalität der Methode befindet sich hier zwischen dem Bezeichner L52 und dem Be-zeichner L54. Hier werden die Werte miteinander addiert, der Zähler wird erhöht und mit demWert des Registers ecx verglichen, in dem sich max=3 befindet. Die Befehle um den Funktions-aufruf call sind im Vergleich zur ersten Variante nur leicht abgewandelt.

-S -O2 Ab Optimierungsstufe 2 wird bereits auf die Trennung von Funktion und Funktionsaufrufverzichtet:

L29:movl (%ebx,%eax,4), %esiincl %eaxaddl %esi, %edxcmpl $3, %eaxjl L29movl %edx, 4(%esp)

Auch wenn die Routine bereits stark optimiert ist, kann man die Funktionalität hier noch gut er-kennen. Im Register edx befindet sich das Zwischenergebnis der Addition, Register eax beinhaltetdie Zählvariable, welche in jedem Durchlauf um 1 erhöht wird und mit 3 verglichen wird. Dabereits zur Übersetzungszeit bekannt ist, dass max=3 gilt, wird hier auf das Lesen und Schreibendieser Variable verzichtet und direkt mit der Konstante 3 verglichen. Schließlich wird das Ergebnisin das Register esp zurückgeschrieben.

-S -O3 Auszug aus der entstandenen Assembler-Datei mit Optimierungsstufe 3:

L31:movl (%esi,%eax,4), %ebxincl %eaxaddl %ebx, %edxcmpl $3, %eaxjl L31movl %edx, 4(%esp)

4.3 Eine Lösung 29

Abgesehen von einer leicht veränderten Registerzuweisung und einem anderen Sprungmarkenbe-zeichner gibt es zwischen Stufe 2 und 3 keinen Unterschied.

30 Begleitende Übung

31

5 Fazit

Diese Konzeption eines Betriebssystem-Programmierpraktikums mit iPosix kann dazu verwendetwerden, ein Programmierpraktikum für Betriebssysteme zu planen und durchzuführen. Es wurdenalle relevanten Aufgabengebiete beschrieben und erläutert. Es ist empfohlen, die Reihenfolge der vor-gestellten Aufgaben nicht zu ändern, um so zu verhindern, dass die Studierenden mit Aufgaben kon-frontiert werden, die aufgrund der Querabhängigkeiten anderer Betriebssystemkomponenten, nichtoder nur erschwert erfüllt werden können.Es wurde stets darauf geachtet, dass Abhängigkeiten zwischen den Betriebssystemkomponenten nichtdazu führen, dass die vollständige Lösung einer Aufgabe nicht erst die Lösung einer nachfolgendenAufgabe erfordert. Leider ist dies nicht in allen Fällen gelungen. Dabei handelt es sich in der Regeljedoch um kleinere Probleme. So sollte beispielsweise der Systemaufruf kill nach der Implementie-rung des Prozesszustandmodells angepasst werden, obwohl die Systemaufrufe selbst bereits bear-beitet worden sind. Auf derartige Besonderheiten sollte in der Einführung der jeweiligen Aufgabenhingewiesen werden. Gegebenenfalls kann auch darüber nachgedacht werden, die Korrektur dieserAbhängigkeiten zum Teil der Aufgaben zu machen, um zu gewährleisten, dass die Studierenden dasSystem in einem konsistenten Zustand halten und nicht mit obsoleten Behelfslösungen arbeiten. Diesist insbesondere im Hinblick auf die Abschlussprojekte empfehlenswert, da hier möglichst wenigZeit damit aufgebracht werden sollte, abgehandelte Aufgabenbereiche zu wiederholen, um derartigeLücken zu schließen. Eine Alternative hierzu stellt der Vorschlag in Abschnitt 3.8 dar, zu Beginn derProjektarbeit, allen Studierenden dieselbe Betriebssystemversion zur Vefügung zu stellen.

Insgesamt erfüllt diese Arbeit die Anforderung, das vorhandene Betriebssystem-Programmierpraktikumneu zu konzipieren und zu modernisieren, um den Ansprüchen der sich ändernden Bedingungen derInformatik zu genügen. Die Studierenden können aus dem vergangenen Studium bekannte Konzepteund Verfahren anwenden, um Konzepte aus der Theorie der Betriebssysteme in die Praxis umzuset-zen, um somit das Verständnis für diese Konzepte zu fördern. Im Gegensatz zum bisherigen Praktikumkann dies nun auf einer Architektur geschehen, die den meisten Studierenden zumindest im Gebrauchbekannt ist, da bei vielen Heimrechnern und Laptops diese Architektur genutzt wird. Dazu wird eineProgrammiersprache verwendet, die zumindest semantisch in den meisten Punkten der den meistenStudierenden vertrauteren Sprache Java entspricht.

32 Fazit

33

Anhang

Auf der beiliegenden CD befinden sich folgende Dateien:

Ausarbeitung.pdf Dieses Dokument

dir Uebungen Beinhaltet alle für die Uebung relevanten Dateien.

ArchBeschr.pdf Die Architekturbeschreibung der x86-Architektur nach [MT09].

Uebung0.pdf Übungsblatt 0.

Uebung_Vorlage.pdf Die fertige Vorlage für alle weiteren Übungen.

Uebung_Vorlage.tex Die bearbeitbare Vorlage für die Übungen im LaTeX-Format.

uebung00.cpp Der C++-Quelltext für die Programmieraufgabe in Übung 0.

uebung00_loesung.cpp Der C++-Quelltext für die gelöste Programmieraufgabe in Übung 0.

Auf den nächsten 6 Seiten befindet sich Übungsblatt 0 in der Form, wie er an die Studierenden aus-gegeben werden wird. Hier können auch die bisher nicht abgebildeten Kopf- und Fußzeilen betrachtetwerden.

Universität Oldenburg Fakultät II - Department für Informatik

Betriebssystemepraktikum Semestercand. Inf. Mark Phlippen

Übungsblatt 0Ausgabe: DatumAbgabe: entfällt

Einleitung

Betriebssysteme übernehmen einen wichtigen Teil in modernen Rechensystemen. Sieverwalten alle anstehenden Aufgaben und moderieren die Kommunikation von Benutzerund Maschine.In diesem Programmierpraktikum sollen Sie Ihre theoretischen Kenntnisse überBetriebssysteme in der Praxis anwenden. Sie werden hier lernen, wie ein Betriebssystemim Detail aufgebaut ist, wie die einzelnen Komponenten ineinandergreifen und woraufzu achten ist, wenn man Veränderungen am System vornehmen möchte. Natürlich wärees schön, wenn am Abschluss des Praktikums ein vollständiges, modernesBetriebssystem das Ergebnis wäre. Leider ist dies jedoch im Rahmen der Zeit einesSemesters und des Arbeistaufwandes eines Moduls nicht möglich. Sie werden mit demim Rahmen einer Abschlussarbeit an der Universität Oldenburg entwickeltenLehrbetreibssystem iPosix1 der Abteilung Systemsoftware und verteilte Systemearbeiten. In der Auslieferungsversion beherrscht iPosix lediglich rudimentäre Aufgabenund die meisten aus vergangenen Vorlesungen bekannten Betriebssystemekomponentensind kaum oder gar nicht implementiert. Ihre Aufgabe im kommenden Semester ist es,dieses Betriebssystem zu erweitern und zu vervollständigen.iPosix wurde für die Intel x86-Architektur entwickelt und ist in derProgrammiersprache C++ geschrieben. Da ein Betriebssystem oft sehr maschinennaharbeiten muss, um seine Aufgaben effizient lösen zu können, werden Sie sich zunächstmit der Intel x86-Architektur vertraut machen und anschließend ein wenig in C++eintauchen. In Ihrem vergangenen Studium haben Sie bisher kaum oder gar nicht mitC++ gearbeitet. Es handelt sich hierbei zwar bereits um eine objektorientierte Sprache,so dass sie viele von Java bekannte Konzepte semantisch umsetzen können, jedochbedient sich C++ oftmals einer anderen Syntax.Daher ist der zweite Teil dieser Einführung in das Praktikum eine Einarbeitung in dieBesonderheiten von C++. Sollten Sie bisher noch nicht objektorientiert programmierthaben, sollten Sie sich in dieses Konzept einarbeiten. Sie finden dazu entsprechendeLiteratur in der Universitätsbibliothek.

1 Die Intel x86-Architektur

Die Intel x86-Architektur wird den meisten von Ihnen insofern bekannt sein, da sie dieBasis für die meisten heutigen Heimrechner bildet. Im Gegensatz zu Ihren bisherigen

1Eike Möhlmann und Janko Timmermann, „iPosix - Ein objektorientierter Kernel in C++“, 2009

1

Betriebssystemepraktikum Übungsblatt 0

Arbeiten mit Informationssystemen werden sie in diesem Praktikum teilweise sehrmaschinennah programmieren. Daher ist es wichtig, dass Sie sich zunächst mit derArchitektur vertraut machen und ihre Eigenarten und Besonderheiten kennenlernen.Die benötigten Informationen finden Sie hier: Link einfügen (ArchBeschr.pdf). Diedarin referenzierten Quellen sind folgende:

[BC01] Daniel P. Bovet und Marco Cesati: „Understanding the Linux Kernel“

[Int] http:/www.intel.com/design/processor/applnotes/317080.pdf

[Int88] http://pdos.csail.mit.edu.6.828/2005/readings/hardware/8259A.pdf

[Int01] http://bos.asmhackers.net/docs/ata/docs/29860001.pdf

[Int09a] http://www.intel.com/Assets/PDF/manual/253665.pdf

[Int09b] http://www.intel.com/Assets/PDF/manual/253668.pdf

2 Einführung in C++

Da iPosix in C++ verfasst ist und Sie in Ihrem bisherigen Studium kaum oder gar nichtmit dieser Sprache gearbeitet haben, sollten Sie sich ein wenig mit den Besonderheitendieser Sprache vertraut machen. Der nachfolgende C++-Code weist einige derBesonderheiten auf, mit der Sie im Verlauf des Praktikums konfrontiert werden.Nachdem Sie den Code nachvollzogen haben, müssen Sie diesen erweitern. Es handeltsich hierbei um einen Sortieralgorithmus, der Ihnen aus „Algorithmen undDatenstrukturen“, „Algorithmen und Programmieren“ oder aus dem „ProgrammierkursJava“ bekannt sein sollte. In der Universitätsbibliothek finden Sie darüberhinaus eineReihe von Programmiersprachenlehrbüchern, die sich mit C++ befassen. Natürlich gibtes auch eine mehrere Einführungen im Internet zu finden, deren Qualität jedoch nichtgesichert ist. Sollten Sie also bei der Bearbeitung dieser Aufgabe oder im weiterenVerlauf des Praktikums Schwierigkeiten mit C++ bekommen, wird Ihnen empfohlen,sich entsprechende Literatur zu leihen und darin nachzuschlagen oder IhreKommilitonen zu fragen. Nach Bearbeitung dieser Aufgabe sollten Sie grundsätzlich inder Lage sein, einem Dritten kurz die wichtigsten Elemente dieses Programms zuerklären.

0 /∗1 Aufgabe 002 In d i e s e 125 Ze i l en wurden so z i em l i c h a l l e3 "Gemeinheiten" der Sprache C++ gepackt , denen Sie4 i nnerha l b von iPos i x begegnen werden :5 ∗ Praeprozessor :6 − Makros7 − b ed ing t e Kompilierung8 − Konstanten−Dek lara t ion9 ∗ Eigene Typde f in i t i onen

2

Betriebssystemepraktikum Übungsblatt 0

10 ∗ Zeiger :11 − Ze i g e ra r i t hme t i k12 − Funk t i ons z e i g e r13 − Aequiva lenz von Zeigerausdruecken14

15 Nachdem Sie den Que l l t e x t u e b e r s e t z t , au sp ro b i e r t16 und nachvo l l z ogen haben , implementieren Sie d i e Funktion17 "bubble_sort_numbers_ptr " . Den BubbleSort−Algori thmus s o l l t e n18 Sie na t u e r l i c h b e r e i t s kennen , g g f . koennen Sie Ihr Wissen19 aber durch Analyse der Funktion "bubble_sort_numbers_array"20 au f f r i s c h en :−)21

22 Praeprozessor : g++ −E −DDEBUG −o uebung00 . i uebung00 . cpp23 Kompil ieren : g++ −S −g −O0 −o uebung00 . s uebung00 . i24 Assembl ieren : g++ −c −o uebung00 . o uebung00 . s25 Linken : g++ −o uebung00 uebung00 . o26 Ausfuehren : uebung0027 ∗/28 # include <s td i o . h>29 # include <s t d l i b . h>30

31 # define MAX 532

33 # define pr in tva lu e (a , b ) printf ( " array : %d | dynarray : %d\n" , a , b ) ;34

35 //# de f i n e DEBUG36 # ifde f DEBUG37 # define DBGOUT( text ) fpr intf ( s tde r r , ">>DBG( l i n e %d ) : %s \n" , __LINE__ , text )38 # else39 # define DBGOUT( text ) do {} while (0 )40 # endif41

42 typedef enum{FALSE = 0 , TRUE = 1} boolean ;43

44 stat ic void s t ruc t_te s t ( ){45 struct koords {46 int x , y ;47 } po s i t i o n ;48 struct koords ∗ptrpos = &po s i t i o n ;49 ptrpos−>x = 0 ;50 po s i t i o n . x = 0 ;51 (∗ ptrpos ) . x = 0 ;52 DBGOUT(" i ch bin in der funkt ion \" s t ruc t_te s t \"" ) ;53 }54

55 stat ic void print_array ( int f e l d 1 [ ] , int f e l d 2 [ ] ) {56 int loop2 ;57 int ∗p = f e l d 1 ;58 for ( loop2 =0; loop2<MAX; loop2++){

3

Betriebssystemepraktikum Übungsblatt 0

59 pr in tva lu e (∗p++, f e l d 2 [ loop2 ] ) ;60 }61 }62

63 stat ic void bubble_sort_numbers_array ( int f e l d [ ] ) {64 int outer , inner ;65 for ( outer =1; outer<MAX; outer++){66 for ( inner =0; inner<MAX−1; inner++){67 i f ( f e l d [ inner ] > f e l d [ inner +1]){68 int buf = f e l d [ inner ] ;69 f e l d [ inner ] = f e l d [ inner +1] ;70 f e l d [ inner +1] = buf ;71 }72 }73 }74 }75

76 stat ic void bubble_sort_numbers_ptr ( int ∗ f e l d ){77 // j e t z t s ind Sie g e f r a g t !78 }79

80 /∗∗81 ∗ @param f e l d [ ] Array , aus dem die e r s t en max Elemente add i e r t werden82 ∗ @param max wie v i e l e E le l emete s o l l e n add i e r t werden?83 ∗ @memo add i e r t d i e e r s t en max Elemente aus dem Array f e l d [ ]84 ∗ @doc d ie Funktion add_numbers add i e r t aus dem uebergebenem85 ∗ Array f e l d [ ] d i e erstem max Elemente und g i b t s i e der86 ∗ aufru fenden Ins tanz zurueck87 ∗/88 stat ic int add_numbers ( int f e l d [ ] , int max){89 int loop3 , r e t v a l = 0 ;90 for ( loop3 =0; loop3<max ; loop3++){ r e t v a l+=f e l d [ loop3 ] ; }91 return r e t v a l ;92 }93

94 int main ( int argc , char ∗argv [ ] ) {95 int loop1 , randwert ;96 int numbers_arr [MAX] ;97 int ∗numbers_arr_ptr = &numbers_arr [ 0 ] ;98

99 void (∗ s t ruct_ptr ) ( ) ;100

101 int ∗numbers_ptr = ( int ∗)malloc (MAX∗ s izeof ( int ) ) ;102

103 for ( loop1 =0; loop1<MAX; loop1++){104 randwert = rand ()%100;105 numbers_arr [ loop1 ] = randwert ;106 ∗( numbers_arr + loop1 ) = randwert ;107 ∗( numbers_arr_ptr + loop1 ) = randwert ;

4

Betriebssystemepraktikum Übungsblatt 0

108 ∗( numbers_ptr + loop1 ) = randwert ;109 }110 printf ( "Arrays ∗vor∗ der Sor t i e rung : \ n" ) ;111 print_array ( numbers_arr , numbers_ptr ) ;112

113 bubble_sort_numbers_array ( numbers_arr ) ;114 bubble_sort_numbers_ptr ( numbers_ptr ) ;115

116 printf ( "\n Arrays ∗nach∗ der Sor t i e rung : \ n" ) ;117 print_array ( numbers_arr , numbers_ptr ) ;118

119 printf ( "\n Ergebnis : %d\n" , add_numbers ( numbers_arr , 3 ) ) ;120

121 s t ruct_ptr = s t ruc t_te s t ;122 s t ruct_ptr ( ) ;123

124 return 0 ;125 }

Die Funktion add_numbers() ab Zeile 81 ist mit Doxygen1 kommentiert. Es wirdempfohlen, dass Sie in Ihrer Arbeit ebenfalls Doxygen verwenden. Eine Übersicht überDoxygen und eine kurze Einführung darin finden Sie auf der Webseite von Doxygen.iPosix ist ebenfalls durchgehend mittels Doxygen kommentiert.

3 Den x86-Assembler verstehen

Bei der Entwicklung eines Betriebssystems ist es oftmals notwendig, dassmaschinennahe oder sehr zeitkritische Abschnitte in Assemblersprache implementiertsind. Zwar werden Sie im Verlaufe des Praktikums nur sehr wenig oder gar keinenAssemblercode selbst schreiben müssen, aber da einige Komponenten von iPosix inAssemblercode verfasst sind, sollten Sie den Assembler wenigstens in den Grundzügenverstehen, um diese Komponenten nachvollziehen zu können. Legen Sie hierzu IhrenFokus auf die Funktion add_numbers ab Zeile 88 aus Aufgabe 2.

1) Generieren Sie für vier Optimierungsstufen den Compilers vier verschiedeneAssemblerausgaben jeweils mit dem Flag:

1a) -S -O01b) -S -O11c) -S -O21d) -S -O3

Versuchen Sie zunächst, den generierten Assemblercode der Funktion add_numbers()mit Optimierungsstufe 0 zu verstehen. Vergleichen Sie dies im Anschluss mit den

1siehe http://www.stack.nl/ dimitri/doxygen/index.html

5

Betriebssystemepraktikum Übungsblatt 0

anderen drei Optimierungsstufen. Achten Sie insbesondere darauf, wie die Funktionadd_numbers() jeweils optimiert wird, und wie Übergabe- und Rückgabeparameterbehandelt werden.Sollten Sie über kein x86-System verfügen, nutzen Sie die Rechner in der ARBI. AchtenSie dabei darauf, dass auch hier nicht alle Rechner auf der x86-Architektur aufbauen.Weitere Optimierungsoptionen für den g++-Compiler finden Sie in der man-Page zumg++ unter „Optimizing Options“.

6

40 Anhang

41

Glossar

Nachfolgend sind noch einmal wesentliche Begriffe dieser Arbeit zusammengefasst und erläutert.Eine ausführliche Erklärung findet sich jeweils in den einführenden Abschnitten sowie der jeweilsdarin angegebenen Literatur. Das Symbol ↑ verweist auf einen ebenfalls in diesem Glossar erklärtenBegriff.

Algorithmus Ein Algorithmus (auch Lösungsverfahren) ist eine formale Handlungsvorschrift zurLösung eines Problems oder einer bestimmten Art von Problemen in endlich vielen Schritten. DerBegriff des Algorithmus geht auf den persischen Mathematiker Al-Chwarizmi (780 - 835 oder 850n.Chr.) zurück.

Assembler Der Assembler oder auch Assemblierer stellt eine Zwischenstufe zwischen ↑Hochspracheund ↑Maschinencode dar. Beim Übersetzen eines Programmes wird meist der Quelltext, der ineiner Hochsprache (zB C++) geschrieben ist, in Assemblercode umgewandelt und dieser anschlie-ßend in Maschinensprache.

Betriebssystem Ein Betriebssystem ist eine wichtige Kompononente eines Rechensystems, welchesAufgaben zur Verwaltung sämtlicher ↑Ressourcen übernimmt.

Bibliothek Durch die Bereitstellung von Bibliotheken kann die Systemsoftware den ↑Prozessen ver-schieden Routinen und Datenstrukturen zur Verfügung stellen, damit diese nicht in den Prozessenselbst implementiert werden müssen.

Binärsystem Das Binärsystem ist ein Zahlensystem auf der Basis 2. Zur Darstellung werden dieZiffern 0 und 1 verwendet. So ist beispielsweise Die Binärrepräsentation der Zahl 42 = 101010.Dies entspricht von rechts nach links: 0*1 + 1*2 + 0*4 + 1*8 + 0*16 + 1*32.

Bubble-Sort-Algorithmus Der Bubble-Sort-↑Algorithmus ist eine Methode, eine Reihe von unsor-tierten, aber sortierbaren Objekten in eine bestimmte Ordnung zu bringen. Dieser Algorithmusvergleicht stets ein bestimmtes Objekt k mit seinem nachfolgenden Nachbarn k+1 und vertauschtdiese, falls k > k+1. Danach fährt der Algorithmus mit dem nächsten Objekt fort und terminiert,wenn bei einem kompletten Durchlauf durch das zu sortierende Feld keine Änderung vorgenom-men wurde.

CPU-Kern Der Kern einer CPU ist der Teil, in dem sämtliche Berechnungen zur Ausführung eines↑Prozesses durchgeführt werden. Im Gegensatz dazu steht der ↑Kern des ↑Betriebssystems.

Dateisystem Ein Dateisystem beschreibt die Methode, wie ein ↑Betriebssystem Dateien (und Ord-ner) verwaltet. Mit dem Dateisystem wird auch der Zugriff auf Dateien (und Ordner) geregelt.

Debugger Ein Debugger ist ein Programm, dass verwendet wird, um Fehler in Programmquellda-teien zu identifizieren und zu beseitigen. Sie werden insbesondere dann eingesetzt, wenn bei derEntwicklung von Programmen Fehler auftreten, die sich schwer rekonstruieren lassen.

Dezimalsystem Das Dezimalsystem ist ein Zahlensystem auf der Basis 10. Es handelt sich dabei umdas in der Sprache und Mathematik gebräuchlichste Zahlensystem und verwendet die Ziffern 0, 1,2, 3, 4, 5, 6, 7, 8 und 9.

42 Glossar

Dispatcher Der Dispatcher stellt eine Komponente eines ↑Betriebssystems dar, die dafür zuständigist, die Prozesse in die verschiedenen Prozesszustände zu überführen.

ELF Dateien im Executable and Linking-Format (ELF) sind ausführbare Dateien unter Unix-ähnlichen↑Betriebssystemen, wie beispielsweise ↑Linux.

Erzeuger-Verbraucher-Problem Das Erzeuger-Verbraucher-Problem beschreibt die Problematik,dass gewisse ↑Prozesse Dinge benötigen, die erst durch andere ↑Prozesse zur Verfügung gestelltwerden können. So ist zum Beispiel ein ↑Prozess ein Erzeuger, wenn er Zeilen erstellt, die voneinem Verbraucher, zum Beispiel einem Drucker, ausgegeben werden. Dabei können nicht mehrZeilen verbraucht werden, als erzeugt wurden.

First-In-First-Out Die Kurzzeit-Scheduling-Strategie First-In-First-Out (FIFO) wird auch als First-Come-First-Served (FCFS) bezeichnet. Dabei wird ein ↑Prozess an die ready-Warteschlange zumZeitpunkt seiner Ankunft angehängt.

GibiByte Ein GibiByte (GiB) ist ein Wert im ↑Binärsystem entspricht 230=1.073.471.824 Byte. Dasin der Umgangssprache gebräuchlichere GigaByte (GB) ist ein Wert des ↑Dezimalsystems undentspricht nur 109=1.000.000.000 Byte, wird jedoch oft in der Bedeutung für GibiByte verwendet.

Hauptspeicher Der Hauptspeicher oder auch Arbeitspeicher, kurz RAM, genannt, ist der Speicher,in dem sich die zur Ausführung eines Prozess benötigten Werte befinden. Er ist in der Regel kleinerund schneller als der Hintergrundspeicher, wie beispielsweise Festplatten.

Highest-Priority-First Bei Highest-Priority-First teilt der ↑Scheduler einem ↑Prozess nach seinerPriorität ein. Die ↑Priorisierung kann dynamsich während der Laufzeit verändert werden oderunveränderlich beim Start eines Prozesses festgelegt werden. Durch die Priorisierung wird dieReihenfloge in der ready-Warteschlange bestimmt.

Hochsprache Eine Hochsprache ist eine Programmiersprache, die der natürlichen Sprache recht na-he kommt. Beispiele für Hochsprachen sind C, C++, C# oder Java.

Kern Der Kern wird auch als Kernel bezeichnet. Es handelt sich dabei um den Bereich des↑Betriebssystems, in dem sicherheitskritische Abläufe stattfinden. Ein sicherheitskritischer Ab-schnitt bezeichnet hierbei einen Teil des Systems, der für den fehlerfreien Ablauf des Systemswichtig ist. Auf diese Bereiche können Benutzerprozesse in der Regel nicht direkt zugreifen.

LaTeX LaTeX beschreibt ein Softwarepaket, um das Textsatzprogramm TeX zu verwenden. Es han-delt sich dabei um eine Möglichkeit, rechnergestützt, hochwertige Publikationen und einfacheTextdokumente zu erstellen.

Leser-Schreiber-Problem Das Leser-Schreiber-Problem beschreibt die Problematik, dass gewisseDinge, zum Beispiel Dateien, sowohl gelesen, als auch geschrieben (verändert) werden können.Dabei gibt es zwei ↑Prozess-Klassen. Leser haben nur lesenden Zugriff auf die Datei, währendSchreiber diese verändern können. Das Problem besteht darin, den Zugriff auf diese Datei durchLeser bzw Schreiber zu regulieren.

Linux Der Name Linux bezeichnet eine Familie von ↑Betriebssystemen auf ↑OpenSource-Basis. Esgibt eine reihe von Distributionen. Bekannte Vertreter sind Ubuntu, debian oder Gentoo, um nureinige zu nennen.

43

Maschinencode Der Maschinencode entspricht der Repräsentation eines Programmes, die direkt voneinem Rechner interpretiert und umgesetzt werden kann. Er unterscheidet sich je nach verwendeterArchitektur.

MebiByte Ein MebiByte (MiB) ist ein Wert im ↑Binärsystem entspricht 220=1.048.576 Byte. Dasin der Umgangssprache gebräuchlichere MegaByte (MB) ist ein Wert des ↑Dezimalsystems undentspricht nur 106=1.000.000 Byte, wird jedoch oft in der Bedeutung für MebiByte verwendet.

Mutex Ein Mutex wird verwendet, um gegenseitigen Auschluss zweier ↑Prozesse beim Zugriff aufeinen sogenannten kritischen Abschnitt zu realisieren. Dabei kann ein kritischer Abschnitt zumBeispiel das Verwenden eines Ein-, Ausgabegerätes, wie zum Beispiel einem Drucker, sein.

OpenSource OpenSource beschreibt eine Methode, Software sämtlicher Art zu veröffentlichen. DieBesonderheit besteht hierbei, dass der Quelltext der Software für jeden Anwender zugänglich ist.OpenSource wird meist bei frei erhältlicher Software benutzt, ist jedoch auch bei kommerziellenProdukten zu finden.

Physikalischer Speicher Physikalischer Speicher entspricht dem im Rechner tatsächlich verbauten↑Hauptspeicher. Da gewisse ↑Prozesse oder die Gesamtheit der im System befindlichen Prozes-se in der Summe unter Umständen mehr Speicher benötigen, als so zur Verfügung steht, wird↑virtueller Speicher verwendet.

pipe Eine pipe bezeichnet den Datenstrom zwischen zwei oder mehreren ↑Prozessen. Dies kannbeispielsweise dazu verwendet werden, um die Ergebnisse eines Prozesse als Eingaben für einenanderen Prozess zu nutzen.

Primzahlen Eine Primzahl ist eine besondere Zahl mit den Eigenschaften, dass sie nur durch sichselbst und durch 1 teilbar ist. Die Zahlen 5, 13, 31 oder 4973 sind Beispiele für Primzahlen.

Priorisierung Es wird von Priorisierung gesprochen, wenn ein ↑Prozess gegenüber einem anderenaus unterschiedlichen Gründen eine höhere Priorität hat und bei der Zuweisung der CPU bevorzugtbehandelt wird.

Prozess Ein Prozess beschreibt eine dynamische Ablaufstruktur während der Ausführung eines Pro-gramms, welches bestimmte Aufgaben erfüllt. Es wird hierbei zwischen Betriebssystemprozessenund Benutzerprozessen unterschieden, die bestimmte Rechte für den Zugriff auf eine ↑Ressourcehaben. Ein Betriebssystemprozess hat dabei in der Regel Zugriff auf sämtliche Ressourcen, wäh-rend Benutzerprozesse in diesem Zugriff beschränkt sind und auf die Verwaltung durch das ↑Betriebssystemangewiesen sind, welches die Ressourcen zuteilt.

Register Ein Register ist Teil einer CPU und wird dazu verwendet, bestimmte Werte, zum Beispielvon Variablen, zu speichern, um Operationen darauf ausführen zu können.

Ressource Eine Ressource beschreibt den Oberbegriff für sämtliche Geräte und Strukturen, die voneinem ↑Prozess in der Laufzeit verwendet werden können. Darunter fallen Drucker, Festplatten,Bandspeicher, weitere Peripheriegeräte, aber auch Software.

Round-Robin Round-Robin ist eine ↑Kurzzeit-Schedulingstrategie, bei dem sämtliche ↑Prozessereihum die CPU für eine feste Zeitspanne, auch Zeitscheibe genannt, erhalten, um ihre Aufga-be zu erfüllen. Beendet oder blockiert der Prozess nicht während dieser Zeitspanne, wird ihm die

44 Glossar

CPU wieder entzogen und der nächste Prozess erhält die CPU. Die Größe der Zeitscheibe ist füralle Prozesse gleich.

(Kurzzeit-)Scheduler Ein Kurzzeit-Scheduler ist eine Komponente des ↑Betriebssystems, der da-für zuständig ist, jeden ↑Prozess nach bestimmten Auswahlstrategien der CPU zu zuweisen. Da-bei wird zwischen kooperativen und verdrängenden Schedulern unterschieden. Ein kooperativerScheduler weist einem ↑Prozess die CPU zu, bis dieser sie wieder von sich freigibt oder blockiert,während ein verdrängender Scheduler einem ↑Prozess die CPU wieder entziehen kann.

Seitentausch Durch den Seitentausch können Speicherinhalte, sogenannte Seiten, aus dem ↑Hauptspeicherauf den Hintergrundspeicher, zum Beispiel Festplatten, ausgelagert werden. Dieser Vorgang kannauch umgekehrt werden. Seitentausch wird zur Realisierung von ↑virtuellem Speicher verwendet.

Semaphore Eine Semaphore ist eine Möglichkeit, gegenseitigen Ausschluss verschiedener ↑Prozessezu realsieren. Zur Realisierung von Semaphoren wird das ↑Mutex-Konzept verwendet.

Shell Eine Shell ist ein Programm, durch das der Benutzer mit dem ↑Betriebssystem kommunizierenkann. Eine Shell basiert in der Regel auf textuelle Eingaben und kennt eine Reihe von Kommandos,die oft in der Ausführung eines ↑Systemaufrufs resultieren.

Shortest-Remaining-Time-First Bei Shortest-Remaining-Time-First (SRTF) ordnet der ↑Schedulereinen ↑Prozess anhand seiner noch zu erwartenden verbleibenden CPU-Zeit in die ready-Warteschlange.SRTF entspricht also ↑Highest Priority First, wobei die erwartete verbleibende CPU-Zeit die Prio-rität wiederspiegelt.

Systemaufruf Ein Systemaufruf oder Systemcall wird verwendet, wenn ein ↑Prozess bestimmteOperationen durchführen möchte, die dem ↑Betriebssystem vorbehalten sind. Dies kann zum Bei-spiel das verwenden bestimmter ↑Ressourcen sein.

Übersetzer Der Übersetzer oder Compiler übersetzt den Programmquelltext in eine maschinenver-ständliche Sprache. Er ist in etwa der Dolmetscher zwischen Mensch und Maschine.

Unterbrechung Eine Unterbrechung oder Interrupt unterbricht den Programmablauf, sichert Lauf-zeitvariablen und initiiert eine Unterbrechungsbehandlungsroutine. Der Grund für eine Unterbre-chung kann mehrere Ursachen haben. Dazu zählen beispielsweise Fehler auf Hard- oder Software-bene oder Signale von E/A-Geräten.

Versionskontrollsystem Versionskontrollsysteme werden eingesetzt, um die Entwicklung insbeson-derer größerer Software zu unterstützen. Dabei liegen die Daten zu einem Projekt auf einem zen-tralen Server, auf den alle Projektteilnehmer Zugriff haben. Sie können dadurch lokale Kopien derDaten erstellen und bearbeiten. Nach der Bearbeitung können die lokalen Kopien wieder mit demServer synchronisiert werden. Dabei erhält jede Veränderung der Daten auf dem Server eine neueVersionsnummer. Es kann bei Bedarf zu jeder beliebigen Versionsnummer zurückgekehrt werden.

Virtueller Speicher Mit Hilfe von virtuellem Speicher kann mehr Speicher verwendet werden, alsreal zur Verfügung steht. Dabei werden aktuelle nicht verwendete Speicherinhalte auf den Hinter-grundspeicher, zum Beispiel einer Festplatte, ausgelagert, so dass der schnellere ↑Hauptspeichervon aktuellen Prozessen verwendet werden kann. Bei Bedarf werden die so ausgelagerten Speiche-rinhalte, die durch virtuelle Adressen referenziert werden, wieder in den Hauptspeicher geladen.

45

Windows Windows bezeichnet eine Gruppe von ↑Betriebssystemen auf kommerzieller Basis der Mi-crosoft Corperation.

Zeiger Mit Zeiger oder auch Pointer wird ein Konzept bezeichnet, bei dem die Werte im Programm-quelltext nicht direkt abgefragt werden, sondern die Zeiger auf diese Werte. Ein Zeiger entsprichtsomit der Speicheradresse eines Wertes.

46 Glossar

47

Abkürzungen

ARBI Abteilung Rechner- und Netzbetrieb InformatikBS BetriebssystemCD Compact DiscCPU Central Processing UnitCVS Concurrent Version SystemE/A Eingabe/AusgabeECTS European Credit Transfer SystemELF Executable and Linkable FormatFAT File Allocation TableFCFS First-Come-First-ServedFIFO First-In-First-OutGB GigaByteGiB GibiByteHPF Highest Priority FirstMB MegaByteMiB MebiByteMIPS Microprocessor without Interlocked Pipeline StagesOS Operating SystemPC Personal ComputerRAM Random Access MemoryRR Round-RobinSRTF Shortest Remaining Time FirstSVN Subversion

48 Abkürzungen

49

Abbildungen

3.1 Begleitender Abhängigkeitsgraph . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53.2 Prozesszustandsmodell nach Vorlesung BS 1 [The09] . . . . . . . . . . . . . . . . . 93.3 Abhängigkeistgraph vor Beginn des Projektes . . . . . . . . . . . . . . . . . . . . . 12

50 Abbildungen

51

Literatur

[Cara] CARL VON OSSIETZKY UNIVERSITÄT OLDENBURG (Hrsg.): Änderung der Prüfungs-ordnung für die Fach-Bachelor- und Zwei-Fächer-Bachelorstudiengänge der Carl vonOssietzky Universität Oldenburg (BPO). http://www.uni-oldenburg.de/uni/amtliche_mitteilungen/dateien/AM2009-04_01-BPO_Aenderung.pdf, Abruf: 23. August 2010

[Carb] CARL VON OSSIETZKY UNIVERSITÄT OLDENBURG (Hrsg.): Prüfungsordnung fürdie Fach-Bachelor- und Zwei-Fächer-Bachelorstudiengänge der Carl von Ossietzky Uni-versität Oldenburg (BPO). http://www.uni-oldenburg.de/uni/amtliche_mitteilungen/dateien/AM2008-06_BPO.pdf, Abruf: 23. August 2010

[CHP71] COURTIOS, P.J. ; HEYMANS, F. ; PARNAS, D.L.: Concurrent control with ’readers’ and’writers’. In: Communications of the ACM, 1971, S. 667–668

[CTT95] CARD, Rémy ; TS’O, Theodore ; TWEEDIE, Stephen: Design and Implementation of theSecond Extended Filesystem. In: Proceedings of the First Dutch International Symposiumon Linux, 1995

[Hea00] HEAVNER, Scott D.: Introduction to the Minix File System. 2000

[Mic] MICROSOFT CORPORATION (Hrsg.): Fat32 file system specification. http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx,Abruf: 13. August 2010

[MT09] MÖHLMANN, Eike ; TIMMERMANN, Janko: iPosix - Ein objektorientierter Kernel in C++/ Abschlussarbeit, Carl von Ossietzky Universität Oldenburg, Department für Informatik.2009

[STM10] SURHONE, Lambert M. (Hrsg.) ; TIMPLEDON, Miriam T. (Hrsg.) ; MARSEKEN, Susan F.(Hrsg.): Producer-Consumer Problem. Betascript Publishing, 2010

[Sys] SYSTEMS RESEARCH AT HARVARD (Hrsg.): OS/161. http://www.eecs.harvard.edu/~syrah/os161/, Abruf: 19. Juli 2010

[The09] THEEL, Oliver: Skriptum zur Vorlesung Betriebssysteme 1 / Carl von Ossietzky UniversitätOldenburg, Department für Informatik. 2009

[Ull06] ULLENBOOM, Christian: Java ist auch eine Insel. Galileo Computing, 2006

52 Literatur

53

IndexA

Abschluss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13Assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22, 26assign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

Bblock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10blocked . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

CC++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1, 3, 7, 19, 24chdir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

DDateisystem . . . . . . . . . . . . . . . . . . . . . . . . . . 5, 6, 12dup2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8

Ggetcwd. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8Gruppen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

Hhalt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Iinactive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9Intel x86 . . . . . . . . . . . . . . . . . . . . . . . . . . 1, 3, 18, 23iPosix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1, 3, 7

KKreditpunkte . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1, 15

MMIPS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1, 3mkdir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

OOS/161 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Ppipe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8Projekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11Prozesszustände . . . . . . . . . . . . . . . . . . . . 5, 6, 9, 12Prozesszustandsmodell . . . . . . . . . . . . . . . . . . . . . . 9

putenv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Rready . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9resign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10rmdir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8running . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

SScheduling . . . . . . . . . . . . . . . . . . . . . . . . 5, 6, 11, 12sync . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8Synchronisation . . . . . . . . . . . . . . . . . . . 5, 6, 11, 12Systemaufrufe . . . . . . . . . . . . . . . . . . . . . . 5, 6, 8, 12

Tterminate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

UÜbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

Teil 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15Teil 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16Teil 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16Teil 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Übungsblatt 0 . . . . . . . . . . . . . . . . . . . . . . . . . . 17, 34Übungsblatt Aufbau. . . . . . . . . . . . . . . . . . . . . . . .16unblock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

VVirtueller Speicher . . . . . . . . . . . . . . . . . . . . 5, 6, 12

Seitentausch . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

54 Index

Erklärung

Hiermit erkläre ich, dass ich diese Arbeit selbständig verfasst und keine anderen als die angegebenenQuellen und Hilfsmittel benutzt habe. Außerdem erkläre ich, dass ich die allgemeinen Prinzipienwissenschaftlicher Arbeit und Veröffentlichung, wie sie in den Leitlinien guter wissenschaftlicherPraxis der Carl von Ossietzky Universität Oldenburg festgelegt sind, befolgt habe.

Oldenburg, den 31. August 2010

Mark Phlippen