Galileo Computing < openbook >
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.


Kompendium der Informationstechnik
 von Sascha Kersken
EDV-Grundlagen, Programmierung, Mediengestaltung
Buch: Kompendium der Informationstechnik
gp Kapitel 4 Betriebssysteme
  gp 4.1 Entwicklung der Betriebssysteme
    gp 4.1.1 Die Geschichte von UNIX
    gp 4.1.2 PC-Betriebssysteme
  gp 4.2 Aufgaben und Konzepte
    gp 4.2.1 Allgemeiner Aufbau von Betriebssystemen
    gp 4.2.2 Prozessverwaltung
    gp 4.2.3 Speicherverwaltung
    gp 4.2.4 Dateisysteme
  gp 4.3 Linux
    gp 4.3.1 Arbeiten mit der Shell
    gp 4.3.2 Wichtige Systembefehle
    gp 4.3.3 Editoren
    gp 4.3.4 Grafische Benutzeroberflächen
    gp 4.3.5 Linux-Installation und -Konfiguration
  gp 4.4 Mac  OS X
    gp 4.4.1 Mit Aqua arbeiten
    gp 4.4.2 Systemkonfiguration
  gp 4.5 Mac  OS 9
    gp 4.5.1 Die Oberfläche von Mac  OS 9
    gp 4.5.2 Systemkonfiguration
  gp 4.6 Windows
    gp 4.6.1 Die verschiedenen Windows-Versionen
    gp 4.6.2 Die Windows-Benutzeroberfläche
    gp 4.6.3 Die Windows-Konsole
    gp 4.6.4 Windows-Konfiguration
  gp 4.7 Zusammenfassung

gp

Prüfungsfragen zu diesem Kapitel (extern)


Galileo Computing

4.2 Aufgaben und Konzepte  downtop

Dieser Abschnitt geht näher auf die weiter oben skizzierten Hauptaufgaben eines Betriebssystems ein. Hier lernen Sie nicht, wie Sie mit einem bestimmten Betriebssystem arbeiten können (das steht in den nächsten drei Abschnitten), sondern Sie erfahren, was »unter der Haube« vorgeht.

In den folgenden Unterabschnitten wird jedes wichtige Konzept zunächst allgemein und theoretisch vorgestellt. Anschließend wird skizziert, wie zwei verbreitete Betriebssysteme das jeweilige Problem lösen: Linux und Windows XP. Für einige der dargestellten Sachverhalte sind Programmierkenntnisse von Vorteil, auch wenn in diesem Kapitel kein Quellcode enthalten ist. Wenn Sie mit der Programmierung überhaupt noch nicht vertraut sind, sollten Sie zunächst Kapitel 5, Grundlagen der Programmierung, und Kapitel 6, Konzepte der Programmierung, lesen.


Galileo Computing

4.2.1 Allgemeiner Aufbau von Betriebssystemen  downtop

Die Überschrift dieses Unterabschnitts ist eine recht kühne Übertreibung. Sie enthält ein Versprechen, das niemand einhalten kann: Selbstverständlich gibt es gar keine allgemeine Art und Weise, wie Betriebssysteme aufgebaut sind. Die verschiedenen Systemfamilien unterscheiden sich gerade durch ihren recht andersartigen Aufbau.

Dennoch soll kurz skizziert werden, aus welchen Bestandteilen Betriebssysteme aufgebaut sind beziehungsweise sein können, bevor in den folgenden Unterabschnitten auf die einzelnen Aufgaben eingegangen wird. Gewisse Grundbestandteile besitzt tatsächlich jedes Betriebssystem, denn alle Systeme müssen Computer verwalten, die bestimmte Gemeinsamkeiten aufweisen.

Beinahe jedes neuere Betriebssystem besteht aus dem Kernel, den mehr oder weniger fest zu diesem gehörenden Gerätetreibern, den Systemprogrammen, einer Schnittstelle für Anwendungsprogramme und der Benutzeroberfläche.

Der Kernel

Der Kernel (englisches Wort für einen Obstkern) ist das grundlegende Computerprogramm, das unmittelbar auf dem Prozessor des Rechners ausgeführt wird. Er läuft bis zum Herunterfahren des Systems permanent im Hintergrund und steuert alle anderen Betriebssystemkomponenten sowie den Start und den Ablauf der Anwendungsprogramme. Der Kernel initialisiert die Zusammenarbeit mit der Hardware, indem er die Treiber lädt und koordiniert. Aus einer technischen Perspektive kann man sich vorstellen, dass der Kernel das einzige echte Programm ist, das permanent ausgeführt wird, während alle anderen Programme, die später geladen werden, nur Unterprogramme sind, die vom Kernel aufgerufen werden und die Kontrolle durch einen Rücksprung wieder abgeben.

Monolithischer Kernel/Mikrokernel

Es gibt verschieden konzipierte Kernels. Das ältere Kernel-Konzept ist der so genannte monolithische Kernel, der so viel Funktionalität wie möglich selbst erledigt. Moderner ist das Konzept des Mikrokernels, der so wenig wie möglich selbst tut und die meisten Aufgaben an Prozesse delegiert, die im Benutzermodus laufen wie gewöhnliche Anwendungsprogramme.

Da Mikrokernels kleine und elegante Programme sind und da sie die einzelnen Teile des Betriebssystems nur bei Bedarf im Speicher halten, müssten Betriebssysteme auf Mikrokernel-Basis theoretisch schneller und effizienter laufen als Systeme mit monolithischen Kernels. Allerdings wird dabei oft vergessen, dass der ständige Wechsel zwischen Benutzer- und Kernel-Modus Zeit und Ressourcen verbraucht. Außerdem können auch monolithische Kernels inzwischen häufig von einem der entscheidenden Vorteile des Mikrokernels profitieren: Die meisten Gerätetreiber sind modular, können also je nach Bedarf geladen und wieder aus dem Speicher entfernt werden. Dies ist besonders wichtig für Hot-Plugging-fähige Schnittstellen wie USB, FireWire oder Bluetooth.

Ein weiterer Fortschritt ist das Threading-Modell, das in immer mehr Betriebssystemen zum Einsatz kommt. Die schwerfälligen Prozesse werden durch eine leichtgewichtige Alternative namens Threads ergänzt, was die Arbeit des Kernels weiter beschleunigt.

Anfang der 90er-Jahre schienen die Mikrokernels sich allmählich durchzusetzen, es wurden um diese Zeit kaum noch völlig neue Betriebssysteme auf der Basis eines monolithischen Kernels konzipiert. Eine wichtige Ausnahme ist Linux – sein Kernel ist bis heute monolithisch, verwendet aber modulare Gerätetreiber und inzwischen auch Threads. Andrew Tanenbaum, der Entwickler von Minix und Autor mehrerer brillanter Fachbücher über Betriebssysteme und andere Informatik-Themen, verfasste aus diesem Grund in der Minix-Newsgroup einen berühmt gewordenen Flame mit dem Titel »Linux is obsolete« (Linux ist überholt).

Ein wichtiges Betriebssystem mit Mikrokernel, und zwar dem bekannten mach-Mikrokernel, ist Mac  OS X. Die meisten anderen UNIX-Systeme besitzen dagegen wie Linux einen monolithischen Kernel. In gewisser Weise lässt sich der Kernel von Windows NT und seinen Nachfolgern als Mikrokernel beschreiben.

Der Bootvorgang

Wenn ein Computer eingeschaltet wird, führt das BIOS des Rechners zunächst einige Überprüfungen durch und übergibt die Kontrolle anschließend dem Boot Loader eines Betriebssystems. Dieser Teil des Systemstarts wurde bereits in Kapitel 3, Die Hardware, beschrieben. Der Boot Loader ermöglicht entweder die Auswahl mehrerer Betriebssysteme, die auf den Datenträgern des Rechners installiert sind, oder startet unmittelbar ein bestimmtes System. Das Booten (kurz für Bootstrapping – die »Stiefel schnüren«) eines Betriebssystems bedeutet zunächst, dass der Kernel geladen und ausgeführt wird. Dieser erledigt alle weiteren erforderlichen Aufgaben.

Wichtig ist es, die bei den meisten Betriebssystemen (insbesondere UNIX und Windows) zu beobachtende Trennung zwischen Kernelmodus und Benutzermodus zu verstehen. Ein Prozess, der im Kernelmodus läuft, besitzt gewisse Privilegien, die im Benutzermodus nicht gegeben sind. Bei den meisten Computern werden für die beiden Modi unterschiedliche Betriebsmodi des Prozessors selbst verwendet. Beispielsweise besitzen Intel-Prozessoren und Kompatible seit dem 386er vier verschiedene Modi, die sich durch einen unterschiedlich starken Schutz vor Interrupts, das heißt Unterbrechungsanforderungen durch Hardware oder bestimmte Programmschritte, unterscheiden. Für gewöhnlich wird der Modus mit dem stärksten Schutz als Kernelmodus und der mit dem geringsten als Benutzermodus verwendet.

Prozesse im Kernelmodus führen wichtige Betriebssystemaufgaben durch, die nicht durch Prozesse im Benutzermodus unterbrochen werden dürfen. Beispielsweise sorgen sie für die eigentliche Verarbeitung von Hardware-Interrupts, das Öffnen und Schließen von Dateien oder die Speicherverwaltung. Auch wenn ein Prozess im Kernelmodus nicht von außen unterbrochen werden kann, kann er freiwillig die Kontrolle an einen anderen Prozess abgeben. In der Regel ruft er den Task Scheduler auf, der ebenfalls im Kernelmodus läuft und für die Verteilung der Rechenzeit an die verschiedenen Prozesse zuständig ist.

Ein Prozess im Benutzermodus kann jederzeit unterbrochen werden, etwa durch einen Hardware-Interrupt, durch einen aufwachenden Kernelprozess oder dadurch, dass er selbst einen Befehl aufruft, der nur im Kernelmodus ausgeführt werden kann. Letzteres sind die so genannten Systemaufrufe (system calls), die es Programmierern ermöglichen, die eingebauten Funktionen des Betriebssystems zu nutzen.

Mikrokernel-basierte Betriebssysteme versuchen, so gut wie alle Aufgaben im Benutzermodus auszuführen. Der Kernel selbst führt im Wesentlichen nur noch die Prozessverwaltung durch; selbst das Speichermanagement und die Ein-/Ausgabekontrolle finden im Benutzermodus statt. Auf diese Weise kann ein Mikrokernel-System zwar flexibler auf Anforderungen reagieren, muss dafür aber häufiger zwischen Kernel- und Benutzermodus hin- und herschalten, was zusätzliche Performance kostet.

Windows NT, 2000 und XP verwenden einen Mittelweg zwischen Mikrokernel- und monolithischem System: Gewisse Teile wurden aus dem Kernel ausgelagert und bilden so genannte Subsysteme, die im Benutzermodus laufen und verschiedene Teilfunktionen anbieten, die Kernel-artige Aufgaben erledigen. Andere Teile des Betriebssystems laufen dagegen im Kernelmodus.

Es gibt nur noch einige alte Betriebssysteme, die keine richtige Trennung zwischen Kernel- und Benutzermodus durchführen. Dazu gehört das nicht mehr sehr häufig verwendete MS-DOS in Kombination mit Windows 3.11, der letzten Windows-Version, die kein vollständiges Betriebssystem war. Ein anderes System, auf das diese Aussage zutrifft, ist dagegen noch weit verbreitet: Mac  OS bis zur Version 9.

Multitasking

Der auffälligste Unterschied zwischen einem modernen System und solchen altmodischen Betriebssystemen besteht darin, dass Letztere nur das veraltete kooperative Multitasking verwenden. Ein Prozess entscheidet selbst, wann er die Kontrolle an das Betriebssystem zurückgeben möchte. Stürzt ein Programm ab, das in einem solchen Prozess läuft, dann ist sehr wahrscheinlich das gesamte Betriebssystem instabil geworden. Das in modernen Systemen eingesetzte präemptive Multitasking entscheidet dagegen selbst, wie lange Prozesse im Benutzermodus die Rechenzeit behalten dürfen und entzieht sie ihnen bei Bedarf wieder.

Außerdem besitzen veraltete Betriebssysteme kein richtiges Speichermanagement; Prozesse können gegenseitig auf ihre Speicherbereiche zugreifen und sie versehentlich überschreiben.

Weitere Informationen über Aufgaben des Kernels finden Sie weiter unten unter den Themen Prozessverwaltung, Speichermanagement und Dateisysteme.

Gerätetreiber

Die Gerätetreiber (device drivers) sind spezielle kleine Programme, die sich um die Steuerung einzelner Hardwarekomponenten kümmern. In manchen Betriebssystemen sind Treiber ein fester Bestandteil des Kernels, während sie in den meisten neueren Systemen als Module vorliegen, die sich bei Bedarf laden und wieder aus dem Speicher entfernen lassen.

Es ist eine der schwierigsten Aufgaben für Programmierer, Gerätetreiber zu schreiben. Der Treiber bildet die Schnittstelle zwischen Betriebssystem und Hardware. Er muss die allgemeinen Anforderungen des Betriebssystems an eine bestimmte Geräteklasse in die spezifische Sequenz von Steuerbefehlen umsetzen, die das Gerät eines bestimmten Herstellers versteht, und umgekehrt die Antworten des Geräts wieder in eine allgemein verständliche Form bringen.

Zeichen- und Blockgeräte

Aus der Sicht von Treibern lassen sich zwei grundsätzliche Arten von Geräten unterscheiden. Zeichengeräte (character devices) tauschen Daten mit ihrer Umgebung als sequenzielle Datenströme aus. Die Daten werden also Zeichen für Zeichen nacheinander ausgelesen. Typische Beispiele sind die Tastatur, ein Drucker oder ein Bandlaufwerk. Blockgeräte (block devices) stellen sich dagegen ähnlich dar wie der Arbeitsspeicher: Der Zugriff auf den Inhalt des Geräts kann in beliebiger Reihenfolge blockweise erfolgen. Zu den Blockgeräten zählen vornehmlich die meisten Laufwerke wie Festplatte oder CD-ROM-Laufwerk, aber auch Grafikkarten.

Damit ein Treiber für ein bestimmtes Gerät geschrieben werden kann, muss der Hersteller die Schnittstellen dieses Geräts veröffentlichen. Einige Hersteller wollen dies nicht und bieten stattdessen lieber selbst Treiber für die wichtigsten Betriebssysteme an. Bevor Sie sich ein bestimmtes Gerät anschaffen, müssen Sie also sicherstellen, dass ein Treiber für Ihr Betriebssystem verfügbar ist.

Systemprogramme

Diejenigen Bestandteile des Betriebssystems, die nicht zum Kernel gehören, liegen in der Regel als unabhängige Programme vor, die willkürlich geladen, ausgeführt und wieder beendet werden können. Bei einem Betriebssystem mit Konsolenoberfläche müssen Sie die Namen dieser Programme kennen, weil sie durch Eingabe ihres Namens aufgerufen werden. In einer grafischen Benutzeroberfläche werden sie dagegen hinter den Kulissen automatisch aufgerufen, wenn Sie die entsprechenden Menübefehle aufrufen oder Aufgaben per Drag and Drop erledigen, also durch das Ziehen von Symbolen und ihre Ablage an einer bestimmten Stelle.

Verschiedene Betriebssysteme verfügen über unterschiedlich mächtige Systemprogramme. UNIX-Systeme sind mit besonders leistungsfähigen Systemprogrammen ausgestattet, weshalb UNIX-Benutzer häufiger als die Anwender anderer Betriebssysteme die Konsole verwenden, obwohl auch UNIX-Systeme inzwischen mit sehr überzeugenden grafischen Oberflächen ausgestattet sind.

Bei einem UNIX-System können Sie jede beliebige Verwaltungsaufgabe über die Konsole erledigen, während unter Windows einige Werkzeuge nur unter der grafischen Oberfläche zur Verfügung stehen. Aus diesem Grund können UNIX-Rechner ohne weiteres von fern über ein Netzwerk bedient werden. Die Konsole kann über eine Terminal-Emulation zur Verfügung gestellt werden, ein Programm auf einem anderen Rechner übernimmt also die Funktion eines Terminals. Das einzige System, bei dem man Systemprogramme nicht ohne weiteres direkt aufrufen kann, weil es überhaupt keine Konsole besitzt, ist Mac  OS 9.

Typische Systemprogramme sind beispielsweise Befehle zur Manipulation von Dateien und Verzeichnissen, etwa für das Umbenennen, Löschen oder Kopieren. Außerdem gehören allerlei Steuerungs- und Analysewerkzeuge dazu. Konkrete Systemprogramme werden weiter unten für die einzelnen Betriebssysteme besprochen.

Verwechseln Sie Systemprogramme übrigens nicht mit den weiter unten besprochenen Systemaufrufen. Letztere werden von Prozessen in Gang gesetzt, die auf Dienstleistungen des Kernels zugreifen müssen. Viele Systemprogramme verwenden letztendlich Systemaufrufe, um ihre Aufgabe zu erfüllen, aber nicht alle. Ebenso wenig sollten Sie Systemprogramme mit den einfachen Anwendungsprogrammen durcheinander bringen, die mit vielen Betriebssystemen geliefert werden. Ein einfacher Taschenrechner, ein Texteditor oder ein MP3-Player ist kein Systemprogramm, sondern eine Anwendung.

Die Schnittstelle für Anwendungsprogramme

Jedes Betriebssystem bietet Anwendungsprogrammen die Möglichkeit, seine Dienstleistungen in Anspruch zu nehmen. Dies ermöglicht es Programmierern, bestimmte aufwändige und hardwareabhängige Aufgaben an das Betriebssystem zu delegieren. Bei den meisten aktuellen Systemen bleibt ihnen auch gar nichts anderes übrig, weil der direkte Zugriff auf die Hardware durch Anwendungsprogramme verhindert wird.

Systemaufrufe

Um eine Funktion des Betriebssystems zu verwenden, muss ein Programm einen Systemaufruf (system call) durchführen. Das Betriebssystem reagiert darauf, indem es den aktuellen Prozess unterbricht, den geforderten Systembefehl im Kernelmodus ausführt und dessen Ergebnis an den aufrufenden Prozess zurückliefert.

UNIX-Systeme bieten nur verhältnismäßig wenige, dafür aber sehr mächtige Systemaufrufe an. Einige von ihnen sind auf Dateien und andere Ein- und Ausgabekanäle bezogen, beispielsweise create() zum Erzeugen einer neuen Datei, open() zum Öffnen, read() zum Lesen, write() zum Schreiben oder close() zum Schließen. Andere Systemaufrufe beschäftigen sich mit der Prozessverwaltung, zum Beispiel erzeugt fork() einen neuen Prozess als Kopie des bestehenden, kill() sendet Signale an Prozesse und shmget() fordert das weiter unten angesprochene Shared Memory an.

Neben den eigentlichen Systemaufrufen basiert jedes Betriebssystem auf der Bibliothek der Programmiersprache, in der es geschrieben wurde. Nach wie vor werden die meisten Betriebssysteme zu großen Teilen in der Programmiersprache C geschrieben (nur einige sehr hardwarenahe Teile des Kernels werden in Assembler verfasst). Aus diesem Grund basiert die Arbeitsweise vieler Systembereiche auf Funktionen der C–Standardbibliothek. UNIX, Windows und viele andere Systeme behandeln vieles aus der Sicht von Anwendungsprogrammierern recht ähnlich, weil es mit Hilfe der entsprechenden Bibliotheksroutinen realisiert wurde.

Ein Beispiel soll an dieser Stelle genügen, um einen Eindruck vom Einfluss der C-Standardbibliothek zu geben (konkret lernen Sie sie in Kapitel 5, Grundlagen der Programmierung, kennen): Fast alle Betriebssysteme speichern Datum und Uhrzeit als die Anzahl der Sekunden seit dem 01. Januar 1970, 00:00 Uhr UTC. Dieses Datum wird als EPOCH bezeichnet, weil es als der »Epoche machende« Erfindungszeitpunkt von UNIX gilt. Diese Art der Speicherung von Datum und Uhrzeit ist in der C-Bibliotheksdatei time.h definiert.

Unter Windows gibt es eine äußerst umfangreiche Betriebssystemschnittstelle, die Win32 API. Sie besteht aus tausenden von Befehlen, von denen allerdings nicht alle echte Systemaufrufe sind. Viele von ihnen sind Bibliotheksfunktionen, die beispielsweise den Zugriff auf die Bestandteile der grafischen Benutzeroberfläche ermöglichen. »Win32« steht übrigens für 32-Bit-Windows, in Abgrenzung zu dem längst untergegangenen 16-Bit-Windows, dessen letzte Version Windows 3.11 war. Alle Privatkunden-Versionen seit Windows 95 und alle professionellen Versionen seit der ersten NT-Version gehören zur Win32-Familie.

In Kapitel 6, Konzepte der Programmierung, gibt es einen kurzen Abschnitt über systemnahe Programmierung. Dort erfahren Sie Näheres über den Einsatz von Systemaufrufen.

Die Benutzeroberfläche

Es gibt zwei grundlegende Arten von Benutzeroberflächen: die Konsole oder Kommandozeile und die grafische Oberfläche. Beide dienen dazu, mit dem Betriebssystem zu kommunizieren und stellen ihre Ein- und Ausgabefähigkeiten auch Anwendungsprogrammen zur Verfügung.

Eine Kommandozeilenoberfläche wird (in Abgrenzung zum Kernel) auch Shell genannt. Wenn Sie die Shell verwenden möchten, müssen Sie zunächst wissen, welche Befehle unterstützt werden und wie sie funktionieren. Zu diesem Zweck hält die Windows-Konsole einen Befehl namens help bereit, der eine Liste aller Befehle mit einer kurzen Beschreibung anzeigt. help BEFEHL zeigt dagegen eine ausführliche Beschreibung eines einzelnen Befehls an. Unter UNIX heißt die entsprechende Anweisung man BEFEHL. Das hat übrigens nichts mit dem dummen Klischee zu tun, dass UNIX »nur was für Männer« sei – »man« ist einfach die Abkürzung für »manual«, also Handbuch.

Die unter Windows verwendete Konsole entspricht noch heute weitgehend der Benutzeroberfläche von MS-DOS. Die Befehle, die Sie eingeben können, sind fast alle kompatibel zu den alten DOS-Befehlen. Allerdings wurde inzwischen eine Reihe von Komfort-Funktionen eingebaut, die die Arbeit mit der Windows-Kommandozeile erleichtern.

UNIX-Shells sind allerdings im Vergleich zur Windows-Shell erheblich komfortabler. Das liegt natürlich zum Teil daran, dass die zugrunde liegenden Systembefehle, die Sie aufrufen können, mächtiger sind als die Windows-Konsolenbefehle. Aber auch die Shell selbst hat mehr Bequemlichkeit zu bieten als unter Windows. Beispielsweise wird unter UNIX schon seit langem die Eingabevervollständigung angeboten – wenn Sie Befehle oder Dateinamen eingeben, können Sie die (TAB)-Taste drücken, um einen begonnenen Namen zu ergänzen, falls er bereits eindeutig ist. Microsoft hat dieses Feature erst unter Windows 2000 eingeführt.

Grafische Benutzeroberflächen gibt es inzwischen für jedes Betriebssystem, und auch unter Linux und anderen UNIX-Systemen ist es heutzutage üblich, dass sie gleich die GUI starten, wenn Sie den Rechner booten. In einer grafischen Oberfläche werden die einzelnen Programme und Dokumente in Fenstern dargestellt, die frei über den Bildschirm verschoben, vergrößert und verkleinert und in einer beliebigen Stapelreihenfolge angeordnet werden können. Mit einer Maus bewegen Sie einen Zeiger über diese Oberfläche und können Menübefehle auswählen, Schaltflächen betätigen oder Symbole verschieben.

Unter Linux können Sie sich eine von vielen verschiedenen grafischen Oberflächen aussuchen. Die grundlegenden Grafikfähigkeiten werden von einer Komponente namens X-Window-Server oder kurz X-Server bereitgestellt, darauf aufbauend läuft ein Window-Manager oder ein moderner, voll ausgestatteter Desktop. Die beiden häufigsten Desktops sind KDE und GNOME (sie werden weiter unten kurz vorgestellt).

Windows und Mac  OS lassen Ihnen dagegen keine Wahl bei der Entscheidung für eine bestimmte GUI, weil sie ein fester Bestandteil des Betriebssystems selbst ist. Selbst einige der elementarsten Programme sind so geschrieben, dass sie diese eine Oberfläche voraussetzen. Beide Hersteller haben ihre grafischen Oberflächen in der neuesten Version ihrer Betriebssysteme modernisiert; Mac  OS X verwendet eine elegante Oberfläche namens Aqua, die Windows XP-Oberfläche wird Luna genannt.

Für Mac  OS X ist inzwischen immerhin ein X-Server verfügbar, sodass der reichhaltige Bestand X-basierter Software, der für andere UNIX-Versionen vorhanden ist, allmählich auch unter Mac  OS X verfügbar ist.


Galileo Computing

4.2.2 Prozessverwaltung  downtop

Jedes moderne Betriebssystem ist in der Lage, scheinbar mehrere Aufgaben gleichzeitig auszuführen. Diese Fähigkeit wird allgemein als Multitasking bezeichnet. Es geht dabei nicht nur um den bequemen Nebeneffekt, dass Sie mehrere Anwendungsprogramme geöffnet halten und zwischen ihnen hin- und herschalten können, sondern vor allem um Aufgaben, die das Betriebssystem im Hintergrund erledigen muss, während Sie nur eines dieser Programme verwenden.

Definition eines Prozesses

Jede der einzelnen gleichzeitig stattfindenden Aufgaben wird unter den meisten Betriebssystemen durch einen Prozess realisiert. Einem Prozess stehen aus seiner eigenen Sicht alle Ressourcen des Rechners exklusiv zur Verfügung: die gesamte, ungeteilte Rechenzeit des Prozessors, der vollständige Arbeitsspeicher und der alleinige Zugriff auf sämtliche Ein- und Ausgabekanäle. Es ist Sache des Betriebssystems, die Ressourcen hinter den Kulissen zu verteilen. Ein Prozess, der auf eine Ressource wartet, muss in einen Wartezustand versetzt und später wieder aufgerufen werden.

Dieser Service eines Betriebssystems erleichtert es Anwendungsprogrammierern, sich auf ihre eigentlichen Aufgaben zu konzentrieren. Wenn eine Bedingung eintritt, für die ein bestimmter Prozess nicht zuständig ist, übernimmt das System automatisch die Kontrolle, legt den Prozess schlafen, löst das anstehende Problem und ruft den Prozess anschließend wieder auf.

Stellen Sie sich zur Verdeutlichung dieses Sachverhalts vor, Sie wohnten in einem Haus, in dem es für alle Wohnungen nur einen einzigen Klingelknopf an der Haustür gäbe. Ein Druck auf diesen Knopf würde dafür sorgen, dass es in allen Wohnungen klingelt. In diesem Haus müssten alle Mieter auf das Klingeln reagieren und überprüfen, ob es für sie bestimmt ist.

Ähnlich sähe es auf einem Computer aus, wenn es kein Prozessmanagement gäbe: Jedes einzelne Programm müsste sämtliche Bedingungen überprüfen, die auf dem Rechner eintreten können, und keines könnte sich mehr auf seine Tätigkeit konzentrieren.

Das UNIX-Prozessmodell

Besonders gut verständlich ist das Prozessverwaltungssystem von UNIX, weshalb es hier näher erläutert werden soll. Für UNIX-Prozesse gelten die folgenden Aussagen:

gp  Jeder Prozess ist durch eine eindeutige, ganzzahlige Nummer gekennzeichnet, seine Prozess-ID (PID).
gp  Der erste Prozess, der auf dem Rechner gestartet wird, heißt init, hat die PID 1 und erzeugt alle anderen Prozesse direkt oder indirekt.
gp  Jeder Prozess läuft entweder im Kernelmodus oder im Benutzermodus, und zwar ein für alle Mal. Keiner kann den Modus nachträglich wechseln. Ein Anwendungsprogramm kann niemals selbst einen Prozess starten, der im Kernelmodus läuft – dafür gibt es Systemaufrufe.
gp  Ein neuer Prozess wird durch einen speziellen Systemaufruf namens fork() erzeugt. Dieser Systemaufruf erzeugt eine identische Kopie des Prozesses, der ihn gestartet hat – der neue Prozess kann sich sogar daran »erinnern«, fork() aufgerufen zu haben. Lediglich die PID ist eine andere. In der Regel wird der neue Prozess anschließend für eine neue Aufgabe eingesetzt.
gp  Jeder Prozess besitzt einen Parent-Prozess. Dabei handelt es sich um denjenigen Prozess, der ihn aufgerufen hat. Wenn der Parent-Prozess vor dem Child-Prozess beendet wird, dann wird das Child dem Parent-Prozess seines ursprünglichen Parents zugewiesen. Auf diese Weise wird sichergestellt, dass Prozesse auch weiterhin einen Parent-Prozess besitzen. Wenn kein anderer Prozess mehr übrig ist, ist der letzte mögliche Parent init.
gp  Jeder Prozess reagiert auf eine Reihe verschiedener Signale. Diese Signale sind durchnummeriert, in der Praxis werden jedoch symbolische Namen für diese Signale verwendet, die irgendwo in der Betriebssystembibliothek definiert sind. Signale werden mit Hilfe des Systemaufrufs kill() an einen Prozess gesandt. Der etwas seltsame Name rührt daher, dass das Standardsignal den Prozess auffordert, sich zu beenden, falls kein anderes Signal angegeben wird. Wichtige Signale sind etwa folgende: SIGTERM beendet den Prozess normal, SIGKILL erzwingt einen sofortigen Abbruch, SIGHUP (»Hangup«) weist darauf hin, dass eine Verbindung unterbrochen wurde (etwa eine Netzwerkverbindung) und SIGALRM zeigt an, dass ein Timer-Alarm ausgelöst wurde, den Programmierer verwenden können, um einen Prozess nach einer definierten Zeit wieder zu wecken.
gp  Ein Prozess kann jederzeit selbst die Kontrolle abgeben, indem er den Systemaufruf pause() durchführt. In diesem Fall kann er durch ein Signal wieder geweckt werden.
gp  Prozesse im Benutzermodus können auch von außen unterbrochen und später wieder aufgenommen werden.

Wenn ein Prozess unterbrochen wird, muss der Systemzustand, der zurzeit herrscht, gespeichert werden, um ihn bei Wiederaufnahme erneut herzustellen. Dazu gehören vor allem die Inhalte der Prozessorregister und der Flags sowie eine Liste aller geöffneten Dateien. Wenn ein Prozess weiterläuft, findet er die Systemumgebung also genau so vor, wie er sie verlassen hat.

User- und Group-ID

Neben der Prozess-ID besitzt jeder Prozess in einem UNIX-System eine User-ID (UID) und eine Group-ID (GID). Diese beiden Informationen sind für die Systemsicherheit wichtig: Die User-ID kennzeichnet den Benutzer, dem der Prozess gehört, die Group-ID die Benutzergruppe. Ein Benutzer ist entweder eine bestimmte Person oder eine vom Betriebssystem definierte Einheit; einer Gruppe können beliebig viele Benutzer angehören. Ein Prozess reagiert nur auf Signale, die von einem anderen Prozess mit derselben UID und GID aus versandt wurden. Die einzige Ausnahme sind die UID und GID 0, die dem Superuser oder root vorbehalten sind. Dieser spezielle Benutzer darf auf einem UNIX-System alles, also auch jeden Prozess beenden, unterbrechen oder anderweitig steuern.

Mit Hilfe des Befehls ps können Sie sich auf einer UNIX-Konsole anzeigen lassen, welche Prozesse gerade laufen. Angezeigt werden die PID, die UID, die GID und der Pfad des Prozesses. Der Pfad ist die genaue Ortsangabe der Programmdatei, die in dem entsprechenden Prozess ausgeführt wird. Die Verwendung von ps und anderen prozessbezogenen Befehlen wird weiter unten im Linux-Abschnitt genauer erläutert.

Windows verwendet ein etwas komplexeres Prozessmodell. Vor allem wird ein neuer Prozess durch einen Systemaufruf namens CreateProcess() erzeugt, der keine exakte Kopie des aufrufenden Prozesses erzeugt, sondern einen »leeren« Prozess, dem anschließend eine Aufgabe zugewiesen werden muss. Außerdem ist jeder Prozess im Benutzermodus mit einer numerischen Priorität ausgestattet. Diese entscheidet im Zweifelsfall, welcher Prozess Vorrang hat.

Kommunikation zwischen Prozessen

Prozesse besitzen den Vorteil, dass sie vollkommen voneinander abgeschirmt laufen können: Sie besitzen beiderseits getrennte Speicherbereiche und können einander nicht in die Quere kommen. Manchmal kann dieser Vorteil jedoch auch ein Nachteil sein, denn mitunter müssen Prozesse miteinander kommunizieren. Eine einfache, aber auf wenige »Wörter« beschränkte Möglichkeit ist die bereits erwähnte Verwendung von Signalen.

Eine andere Option besteht in der Verwendung so genannter Pipes, die die Ausgabe eines Programms und damit eines Prozesses mit der Eingabe eines anderen verknüpfen. Pipes werden in den Konsolen von UNIX und Windows häufig eingesetzt, um die Ausgabe eines Programms durch ein anderes zu filtern, können aber auch aus Programmen heraus geöffnet werden. Beispiele finden Sie in den entsprechenden konkreten Abschnitten.

Die effizienteste Möglichkeit der Kommunikation zwischen Prozessen heißt Inter Process Communication oder System V IPC. Obwohl sie mit System V eingeführt wurde und nicht zum POSIX-Standard gehört, ist sie inzwischen in fast allen UNIX-Varianten verfügbar, zum Beispiel auch unter Linux. Im Wesentlichen verwendet die IPC zwei verschiedene Mechanismen: In so genannte Nachrichtenwarteschlangen (Message Queues) kann ein Prozess schreiben; ein anderer kann sequenziell daraus lesen. Gemeinsame Speicherbereiche (Shared Memory) sind dagegen einfacher zu handhaben: Was ein Prozess in diesem Speicherbereich ablegt, können andere beliebig oft lesen oder ändern.

Deadlocks

Eines der Probleme, die bei der Verwendung mehrerer Prozesse auftreten können, ist eine Situation, in der mehrere Prozesse im Wartezustand gefangen bleiben, weil sie aufeinander oder auf dieselben Ressourcen gewartet haben. Das Wettrennen um den Zugriff auf Ressourcen wird als Race Condition bezeichnet. Zu einem Deadlock (einer Verklemmung) kommt es, wenn eine solche Race Condition unentschieden ausgeht. Beispielsweise könnten zwei Prozesse in einen Deadlock geraten, weil sie den Zugriff auf ein und dieselbe Datei zu sperren versuchen, um anderweitige Änderungen dieser Datei zu verhindern. Ein Deadlock führt mindestens zum Absturz der betroffenen Prozesse, möglicherweise sogar zum Absturz des gesamten Systems.

Ein gutes Betriebssystemdesign vermeidet Deadlocks durch eine Reihe von Verfahren. Insbesondere reicht das normale Verfahren zum Sperren von Ressourcen nicht immer aus, um damit zurecht zu kommen. Das gewöhnliche Sperren einer Datei oder einer Hardwareressource überprüft zunächst, ob die Ressource nicht anderweitig gesperrt ist. Falls sie gesperrt ist, wird der Prozess blockiert und wartet, bis die andere Sperre gelöst ist. Anschließend sperrt der aktuelle Prozess selbst die Ressource, sodass andere Prozesse, die sie ihrerseits sperren möchten, wiederum warten müssen.

Statt dieses Modells sollte eine mehrstufige Anmeldung für die Verwendung von Ressourcen eingesetzt werden:

gp  Ein Prozess, der eine bestimmte Ressource benötigt, versucht nicht einfach, eine Sperre für diese Ressource zu errichten, sondern überprüft zunächst, ob sie nicht bereits gesperrt ist. Falls doch, gibt er die Kontrolle ab, um nicht aktiv auf das Ende der Sperre warten zu müssen, was Ressourcen kosten würde. Er sollte nach einer gewissen Zeit erneut überprüfen, ob die Ressource noch gesperrt ist.
gp  Wenn die Ressource frei ist, errichtet der Prozess eine Sperre, die andere Prozesse daran hindert, diese Ressource zu verwenden.
gp  Nachdem der Prozess die Ressource nicht mehr benötigt, löst er die Sperre und gibt die Ressource dadurch wieder frei.

Threads

Einige Prozesse müssen gemeinsam dasselbe Problem bearbeiten und ununterbrochen miteinander kommunizieren. Dies gilt insbesondere für Prozesse, die nebeneinander im gleichen Anwendungsprogramm laufen. IPC oder andere Methoden der Prozesskommunikation sind zwar möglich, verschwenden aber auf die Dauer Systemressourcen. Interessanter ist eine Prozessvariante, bei der sich mehrere Abläufe von vornherein dieselben Ressourcen teilen.

Zu diesem Zweck werden in vielen Betriebssystemen die leichtgewichtigen und schnell zu wechselnden Threads verwendet. Diese besitzen innerhalb desselben übergeordneten Prozesses keine voneinander getrennten Speicherbereiche, sondern greifen auf dieselbe Stelle des Speichers zu. Windows unterstützt Threads bereits seit der ersten Version von Windows NT, in UNIX-Systemen wurden sie erst später eingeführt. Zuletzt wurden sie im aktuellen Linux-Kernel 2.4 nachgerüstet.

Threads übernehmen häufig Aufgaben, die parallel innerhalb desselben Programms ausgeführt werden müssen. Besonders anschaulich lässt sich dies anhand eines in Echtzeit laufenden 3-D-Computerspiels erläutern: Gleichzeitig müssen Eingaben zur Steuerung der eigenen Spielfigur entgegengenommen werden, die Umgebung muss ständig neu gezeichnet werden, und es müssen permanente Zustandskontrollen stattfinden. Es wäre für einen Programmierer ein Ärgernis, wenn er sich selbst Gedanken darüber machen müsste, in welcher Reihenfolge die einzelnen Schritte wann stattfinden sollen. Wenn die verschiedenen Aufgaben dagegen in Threads verpackt werden, führt der Prozessor sie abwechselnd in kurzen Zeitintervallen aus.

Die Verwendung von Prozessen und Threads aus Programmierersicht wird übrigens in Kapitel 6, Konzepte der Programmierung, erläutert.


Galileo Computing

4.2.3 Speicherverwaltung  downtop

Eine der wichtigsten Aufgaben eines Betriebssystems besteht in der Verwaltung des fast immer zu kleinen Arbeitsspeichers. So gut wie alle Betriebssysteme (außer Mac  OS 9) verwenden eine echte virtuelle Speicheradressierung, bei der die von Programmen angesprochenen Speicheradressen nicht identisch mit den Hardware-Adressen des RAM-Speichers sein müssen.

Genau wie Gerätetreiber und Prozessmanagement entbindet das Speichermanagement einen Programmierer von einer recht frustrierenden Aufgabe, nämlich von der Verteilung des Arbeitsspeichers an die einzelnen Prozesse beziehungsweise Programme. Da eine richtig funktionierende Speicherverwaltung jedem Programm vorgaukelt, ihm stünde der gesamte Arbeitsspeicher zur Verfügung, müssen Sie sich beim Programmieren nicht mehr viele Sorgen machen, ob der Arbeitsspeicher reicht oder nicht.

Segmentierung

In der Regel wird der virtuelle Speicherraum vom Betriebssystem in so genannte Segmente unterteilt. Bei modernen Computersystemen beherrscht bereits der Prozessor selbst die Speichersegmentierung und kann dadurch mehr Speicher adressieren als im physikalischen RAM zur Verfügung steht. Zu diesem Zweck enthalten aktuelle Prozessoren ein Bauteil namens Memory Management Unit (MMU). Spricht ein Programm eine bestimmte Speicheradresse an, dann nimmt die MMU sie entgegen und rechnet sie in die aktuell zugeordnete physikalische Speicheradresse um.

Aus der Sicht des Speichermanagements im Betriebssystem wird der Speicher in einzelne Seiten unterteilt, die durch das so genannte Paging auf die Festplatte ausgelagert werden, wenn ein Programm sie gerade nicht benötigt, und in den Arbeitsspeicher zurückgeholt, wenn es sie wieder braucht. Die Datei, in der sich die ausgelagerten Speicherseiten befinden, wird als Auslagerungsdatei (Page File) bezeichnet. UNIX-Systeme verwenden häufig keine einzelne Datei dafür, sondern eine Plattenpartition eines speziellen Typs, die als Swap Partition bezeichnet wird.

Die MMU unterhält zu diesem Zweck eine Seitentabelle, die zu jedem Zeitpunkt darüber Auskunft gibt, welche virtuelle Speicherseite sich gerade wo befindet, sei es im Arbeitsspeicher oder in der Auslagerungsdatei. Dass eine Speicherseite benötigt wird, die zurzeit ausgelagert ist, wird dabei durch einen Page Fault (Seitenfehler) zum Ausdruck gebracht.

Intel x86-Speicheradressen

Da das Speichermanagement auf den Fähigkeiten der zugrunde liegenden Hardware aufbaut, funktioniert es unter Windows und Linux, sofern sie auf Intel-Rechnern oder Kompatiblen laufen, recht ähnlich. Auf einem solchen x86-System ist eine Speicheradresse 32 Bit lang – es handelt sich schließlich um einen 32-Bit-Prozessor. Allerdings werden nicht einfach die verfügbaren physikalischen Speicheradressen durchnummeriert. Stattdessen ist die Adresse in drei Bereiche unterteilt:

gp  Die zehn obersten Bits (31 bis 22) geben den Eintrag im Page Directory (Seitenverzeichnis) an, verweisen also auf eine Adresse in einem Speicherbereich, der eine Liste von Seitentabellen enthält.
gp  Die nächsten zehn Bits (21 bis 12) enthalten die Nummer des Eintrags in der genannten Page Table (Seitentabelle). Dieser Eintrag verweist auf eine einzelne Speicherseite.
gp  Die letzten zwölf Bits (11 bis 0) geben schließlich den Offset an, das heißt das konkrete Byte innerhalb der Speicherseite. Dies führt dazu, dass eine Speicherseite eine Größe von 212  oder 4.096 Byte besitzt.

Auf diese Struktur der Hardware baut die Speicherverwaltung des Betriebssystems auf. Jedes Programm kann dynamisch mehr Speicher anfordern und erhält ihn, indem zurzeit nicht benötigte Speicherseiten ausgelagert werden. Es kommt daher bei einem modernen System nicht oft vor, dass eine Anwendung wegen Speichermangels abgebrochen werden muss oder gar nicht erst startet. Allerdings wird ein Rechner, der zu wenig physikalischen Arbeitsspeicher besitzt, zu langsam, weil er mehr mit dem Paging beschäftigt ist als mit sinnvoller Arbeit.

64-Bit-Adressierung

Für die nächsten Jahre ist eine wesentliche Änderung des Speichermanagements zu erwarten: Die wichtigsten Prozessorhersteller, Intel und AMD, steigen allmählich auch bei den gewöhnlichen PCs auf eine 64-Bit-Architektur um. Auf 64-Bit-Rechnern kann ein erheblich größerer Adressraum verwaltet werden.

Aus diesem Grund verwendet Linux beispielsweise schon seit dem Kernel 2.2 intern ein dreistufiges Paging-Modell: Das Page Directory zeigt nicht gleich auf eine Page Table, sondern zunächst auf ein weiteres Verzeichnis, genannt Middle Directory. Da unter 32-Bit-Architekturen keine Verwendung dafür besteht, wird der Middle-Directory-Eintrag im Page Directory dadurch stillgelegt, dass er immer gleich lautet, also immer auf dasselbe vermeintliche Middle Directory zeigt. Da einige Linux-Versionen bereits auf konkreten 64-Bit-Prozessoren wie Alpha oder Sun SPARC laufen, ermöglicht dieses Vorgehen die Verwendung desselben Speicherverwaltungsmodells für alle Linux-Versionen.


Galileo Computing

4.2.4 Dateisysteme  toptop

Eine der wichtigsten Aufgaben eines Betriebssystems ist die Verwaltung von Dateien. Eine Datei ist eine benannte Einheit, die auf einem Datenträger gespeichert wird. Die verschiedenen Arten von Datenträgern wurden in Kapitel 3, Die Hardware, vorgestellt. Dort erfahren Sie auch, wie die Daten physikalisch auf den Datenträgern organisiert sind.

Die meisten Betriebssysteme sprechen nicht direkt die Hardwaresektoren eines Datenträgers an, sondern unterteilen den Datenträger logisch in größere Abschnitte, die als Zuordnungseinheiten (englisch cluster) bezeichnet werden. Dies hat den Vorteil, dass das System sich nicht weiter um die tatsächliche Größe des Datenträgers kümmern muss. Ein gewisser Nachteil besteht dagegen darin, dass jede Datei mindestens eine ganze Zuordnungseinheit belegt und dass eine neue belegt wird, wenn die Datei auch nur um ein Byte zu groß ist – das Verfahren ist vergleichbar mit einem Parkhaus, in dem Sie für »angefangene Stunden« bezahlen müssen: 61 Minuten werden dort als zwei Stunden gewertet.

Die unterschiedlichen Betriebssysteme verwenden verschiedene Modelle, um Daten auf einem Datenträger abzulegen. Ein solches Modell wird als Dateisystem bezeichnet. Da die meisten Betriebssysteme mit mehreren konkreten Dateisystemen umgehen können, verwenden sie eine zweistufige Dateiverwaltung: Das eigentliche Dateisystem greift auf den Treiber für das Laufwerk zu und organisiert die Daten auf dem eigentlichen Datenträger, während ein virtuelles Dateisystem den Zugriff des Betriebssystems auf die verschiedenen tatsächlichen Dateisysteme und Datenträgerarten vereinheitlicht. Unter UNIX geht die Abstraktion von Dateien so weit, dass selbst der Zugriff auf Geräte über Special Files (Spezialdateien) erfolgt, die normalerweise im Verzeichnis /dev liegen.

Als Benutzer eines Betriebssystems werden Sie vornehmlich mit dem virtuellen Dateisystem konfrontiert. Hier wird vor allem geklärt, wie die einzelnen Datenträger und Partitionen angesprochen werden, wie Verzeichnisse organisiert sind, welche Zeichen in Dateinamen erlaubt sind, und wie lang diese Namen sein dürfen und so weiter.

Das virtuelle Dateisystem, das alle UNIX-Systeme miteinander gemeinsam haben, unterstützt außerdem verschiedene Sicherheitsaspekte, insbesondere die Zugriffsrechte für einzelne Benutzer und Gruppen. Windows unterstützt ähnliche Fähigkeiten, allerdings nur für das konkrete Dateisystem NTFS.


»Verzeichnis« oder »Ordner«? In diesem Kapitel war bisher die ganze Zeit die Rede von Verzeichnissen. Wenn Sie den Computer erst in den letzten sieben bis acht Jahren kennen gelernt haben und mit Windows oder Mac  OS arbeiten, werden Sie wahrscheinlich eher »Ordner« kennen. Das liegt daran, dass die symbolische Darstellung (das Icon) eines Verzeichnisses auf dem Desktop der GUI eine Aktenmappe (folder) zeigt, was in den deutschen Versionen als »Ordner« lokalisiert wurde. In Wirklichkeit finden Sie im Dateisystem immer Verzeichnisse (directories). Sie sind die Ordnungs- und Organisationseinheiten des Dateisystems.

Das virtuelle UNIX-Dateisystem

Die in diesem Kapitel besprochenen UNIX-Systeme Linux und Mac  OS X haben mit allen anderen UNIX-Systemen dasselbe virtuelle Dateisystem gemeinsam. Konkrete Dateisysteme gibt es unter UNIX dagegen unzählige. Beispielsweise unterstützt Mac  OS X das Apple-Dateisystem HFS+, das CD-ROM-Dateisystem ISO 9660 und andere, während Linux mit seinem eigenen Dateisystem ext2, reiserfs, dem Windows-Dateisystem FAT und weiteren zusammenarbeitet.

Die Gemeinsamkeiten der UNIX-Dateisysteme betreffen die Art und Weise, wie Dateien, Verzeichnisse und Datenträger organisiert sind. Außerdem sind die Zugriffsrechte für alle unter UNIX unterstützten Dateisysteme verfügbar.

Der UNIX-Verzeichnisbaum

Auf einem UNIX-Rechner existiert nur ein einziger Verzeichnisbaum, unabhängig davon, auf wie viele konkrete Datenträger er verteilt ist. Die Wurzel des gesamten Baums wird als / bezeichnet. Unterhalb dieses obersten Verzeichnisses liegen einzelne Dateien und Unterverzeichnisse; jedes von ihnen kann wiederum in Unterverzeichnisse unterteilt sein.

Die meisten Verzeichnisse, die direkt unterhalb der Wurzel des UNIX-Dateisystems liegen, haben spezielle Aufgaben, die in allen gängigen UNIX-Systemen identisch oder zumindest ähnlich sind:

gp  bin (binaries) enthält die Systemprogramme.
gp  sbin (start binaries) enthält Initialisierungsprogramme, die beim Systemstart aufgerufen werden.
gp  dev (devices) enthält Gerätedateien, also Dateien, die auf die einzelnen Hardwarekomponenten verweisen. Der Vorteil dieser Methode ist, dass sich der Zugriff auf Geräte genau wie bei einzelnen Dateien über Benutzerrechte regeln lässt.
gp  usr (user) enthält die wichtigsten Anwendungsprogramme.
gp  opt (optional) enthält zusätzliche Anwendungen, die nicht ganz so häufig benötigt werden.
gp  etc enthält allerlei Konfigurationsdateien.
gp  var enthält variable Daten, vor allen Dingen Log-Dateien, in die Systemmeldungen eingetragen werden.
gp  home enthält für jeden Benutzer, der im System angemeldet ist, ein Home-Verzeichnis. Hier werden alle Anwendungsdaten dieses Benutzers abgelegt. Zusätzlich werden auch die persönlichen Einstellungen dieses Benutzers für die verschiedenen Anwendungs- und Systemprogramme gespeichert. Unter Mac  OS X heißt dieses Verzeichnis übrigens Users.
gp  root ist das spezielle Home-Verzeichnis des Superusers. Es liegt nicht im Verzeichnis home wie die anderen Benutzerverzeichnisse. home könnte nämlich so eingerichtet werden, dass es auf einem anderen physikalischen Datenträger oder einer anderen Partition liegt als der Rest des Betriebssystems. Möglicherweise steht es also nicht zur Verfügung, wenn ein Fehler auftritt, den root beheben muss.

Absolute und relative Pfade

Der Pfad zu einer Datei wird von der Wurzel aus angegeben, indem die Namen der entsprechenden Ordner jeweils durch einen Slash voneinander getrennt werden. Das Folgende wäre beispielsweise der Pfad einer Datei in meinem Home-Verzeichnis:

/home/sascha/it_kompendium/betriebssysteme.txt

Da jedes Programm ein Arbeitsverzeichnis besitzt, in dem es standardmäßig seine Daten ablegt oder nach Dateien sucht, kann ein Pfad auch relativ angegeben werden, das heißt vom aktuellen Verzeichnis aus. Angenommen, eine Anwendung hat das Arbeitsverzeichnis /home/user und möchte auf die Datei info.txt in /home/sascha zugreifen. Der Pfad dieser Datei kann entweder absolut als /home/sascha/info.txt oder relativ (von /home/user aus) als ../sascha/info.txt angegeben werden: .. spricht jeweils das übergeordnete Verzeichnis an; untergeordnete Verzeichnisse werden einfach mit ihrem Namen angegeben.

»Geschwister«-Verzeichnisse, also nebengeordnete – in diesem Fall user und sascha – können einander nie direkt ansprechen, sondern müssen mittels ..-Angaben so weit nach oben wandern, bis ein gemeinsamer Vorfahr gefunden wurde. Im Falle von user und sascha müssen Sie nicht weit nach oben gehen; home ist bereits der Elternordner beider.

Eine Abkürzung für das Home-Verzeichnis des aktuell angemeldeten Benutzers ist übrigens die Tilde (~). Sie können durch Angabe der Tilde von überall aus in Ihr Home-Verzeichnis wechseln. Auf dem PC wird eine Tilde übrigens mit Hilfe der Tastenkombination (ALTGR) + (+) erzeugt, auf dem Mac müssen Sie zunächst (ALT) + (N) betätigen und anschließend die (Leertaste) drücken: Das Zeichen funktioniert wie ein Akzent und kann auf ein n gesetzt werden.

Im Übrigen sollten Sie daran denken, dass UNIX bei Datei- und Verzeichnisnamen zwischen Groß- und Kleinschreibung unterscheidet. Die Namen hallo.txt, Hallo.Txt und HALLO.TXT bezeichnen drei verschiedene Dateien, die alle im gleichen Verzeichnis liegen könnten. Aus Gründen der Kompatibilität mit alten Macintosh-Anwendungen ist dies ein wichtiger Unterschied zwischen Mac  OS X und anderen UNIX-Varianten: Mac  OS X unterscheidet nicht zwischen Groß- und Kleinschreibung.

Ein Dateiname, der mit einem Punkt (.) beginnt, wird in der normalen Verzeichnisansicht standardmäßig ausgeblendet (versteckt). Wirkliches Verstecken ist auf diese Weise nicht möglich; effektiver ist die Verwendung von Zugriffsrechten (siehe unten).

inodes

Intern werden Dateien auf dem Datenträger nicht durch ihren Namen dargestellt, sondern durch eine ganzzahlige Nummer namens inode. Die Einträge in einem Verzeichnis sind Verweise auf solche inodes. Interessanterweise können mehrere Verzeichniseinträge auf dieselbe inode zeigen. Ein Verzeichniseintrag wird deshalb auch als Hard Link bezeichnet, der fest auf eine bestimmte inode verweist. Eine Datei wird auf einem UNIX-System erst gelöscht, wenn Sie alle Einträge im Verzeichnisbaum entfernt haben, die auf die entsprechende inode zeigen.

Im Gegensatz zu den Hard Links werden auch symbolische Links oder Symlinks unterstützt, die nicht direkt auf eine inode zeigen, sondern auf einen anderen Verzeichniseintrag. Anders als die Hard Links können Symlinks auch auf Verzeichnisse verweisen sowie auf Dateien, die auf einem anderen physikalischen Datenträger liegen.

Datenträger mounten

Die verschiedenen Datenträger und Partitionen können übrigens an einer beliebigen Stelle im Verzeichnisbaum eingehängt werden. Dieser Vorgang wird als Mounten bezeichnet. Solange ein Datenträger nicht gemountet ist, können die Verzeichnisse und Dateien, die darauf liegen, nicht angesprochen werden. Angenommen, Sie legen unter Linux eine CD-ROM ein, die eine Datei namens hallo.txt in einem Verzeichnis namens test enthält. Nach dem Einlegen muss die CD gemountet werden, falls das CD-ROM-Laufwerk nicht für automatisches Mounten konfiguriert ist.

Die Syntax des Befehls mount wird weiter unten genauer erläutert, im Moment genügt die Angabe, wie Sie ein Verzeichnis namens cd anlegen und die CD-ROM dorthin mounten können. Geben Sie dazu an der Konsole Folgendes ein:

$ mkdir /cd
$ mount /dev/hdc /cd

Der erste Parameter von mount gibt das physikalische Gerät an, das gemountet werden soll – EIDE/ATAPI-Geräte werden unter Linux als /dev/hda bis /dev/hdd geführt. hdc ist somit der Secondary Master. Wenn Sie nun die Datei hallo.txt ansprechen möchten, dann lautet der entsprechende Pfad folgendermaßen: /cd/test/hallo.txt.

Zugriffsrechte

Eine weitere wichtige Eigenschaft der Dateien unter UNIX sind die Benutzerrechte. Jede Datei gehört einem bestimmten Benutzer und einer bestimmten Gruppe (berechtigte Benutzer können diese Besitzverhältnisse ändern). Da ein Benutzer beliebig vielen Gruppen angehören kann, lassen sich die Rechte an bestimmten Dateien sehr effizient über das Gruppenzugriffsrecht ändern.

Der Verzeichniseintrag einer Datei enthält die Zugriffsrechte für den Besitzer, für die Gruppe und für alle anderen Benutzer. Die drei möglichen Zugriffsrechte sind Lesen (r für read), Schreiben (w für write) und Ausführen (x für execute). Ein typischer Verzeichniseintrag enthält beispielsweise die folgende Angabe von Zugriffrechten:

-rwxr-xr-x

Die erste Stelle gibt den Dateityp an: – für eine gewöhnliche Datei, d für ein Verzeichnis oder l für einen Symlink. Die neun folgenden Informationen zeigen in Dreiergruppen die Zugriffsrechte an. Ein Buchstabe steht dafür, dass ein Zugriffsrecht gewährt wird, ein Strich bedeutet, dass es nicht gewährt wird. Im vorliegenden Fall darf der Eigentümer die Datei lesen, schreiben (dazu gehören auch Löschen und Umbenennen) und ausführen. Die Gruppe und der Rest der Welt dürfen nur lesen und ausführen. Das Recht der Ausführung ist nur für Programme und für Verzeichnisse sinnvoll (Letztere lassen sich ansonsten nicht als Arbeitsverzeichnis auswählen).

Intern werden die Zugriffsrechte als dreistellige Oktalzahl gespeichert. Die erste Stelle enthält die Benutzerrechte des Eigentümers, die zweite die der Gruppe und die dritte die der anderen Benutzer. Der Wert jeder Stelle ist die Summe aus den gewährten Benutzerrechten: 4 steht für Lesen, 2 für Schreiben und 1 für Ausführen. Das Zugriffsrecht rwxr-xr-x lässt sich also als 0755 darstellen (die vorangestellte 0 steht für eine Oktalzahl). Eine einfache Textdatei könnte dagegen beispielsweise die Zugriffsrechte 0640 aufweisen, was rw-r----- entspricht – der Eigentümer darf die Datei lesen und schreiben, die Gruppe darf sie lesen und alle anderen dürfen gar nichts.

Das virtuelle Windows-Dateisystem

Windows-Dateisysteme unterscheiden sich durch mehrere Merkmale von UNIX-Dateisystemen. Insbesondere ist auffallend, dass es keine gemeinsame Wurzel für alle Dateisysteme gibt, sondern dass jeder Datenträger beziehungsweise jede Partition einen eigenen Verzeichnisbaum bildet. Die einzelnen Partitionen werden durch Laufwerksbuchstaben bezeichnet; die automatisch gewählte Reihenfolge gehorcht einigen seltsamen Regeln:

Laufwerksbuchstaben

gp  A: ist das erste Diskettenlaufwerk.
gp  B: ist das zweite Diskettenlaufwerk, das aber kein Mensch mehr einsetzt.
gp  C: ist die erste Partition auf der ersten physikalischen Platte (bei einem EIDE-System dem Primary Master).
gp  D: ist die erste Partition auf der zweiten physikalischen Platte (dem Primary Slave). Falls das zweite EIDE-Gerät ein CD-ROM- oder DVD-Laufwerk ist, bekommt es einen höheren Buchstaben, und es geht zunächst mit den anderen Festplatten weiter.
gp  Die weiteren Buchstaben werden jeweils der ersten Partition der folgenden Platten zugewiesen, falls weitere vorhanden sind.
gp  Nun folgen Platte für Platte sämtliche restlichen Partitionen.
gp  Ganz am Schluss werden die CD-ROM- und DVD-Laufwerke in ihrer eigenen Anschlussreihenfolge berücksichtigt.

Unter Windows XP und den anderen Systemen der Windows-NT-Familie können Sie diese Reihenfolge mit Hilfe der Datenträgerverwaltung (Verwaltung • Computerverwaltung • Datenträgerverwaltung) ändern. Bei den Privatkunden-Versionen bis Windows Me ist die Reihenfolge dagegen verbindlich.

Windows-Pfade

Pfade werden unter Windows so ähnlich angegeben wie bei UNIX. Das Trennzeichen zwischen den Verzeichnisnamen und zwischen Verzeichnis und Datei ist allerdings der Backslash (\), der umgekehrte Schrägstrich. Die Wurzel innerhalb eines bestimmten Laufwerks ist ein einzelner Backslash, während ein vollständiger absoluter Pfad mit dem Laufwerksbuchstaben beginnt. Das jeweils übergeordnete Verzeichnis wird auch unter Windows durch zwei Punkte (..) angegeben.

Hier sehen Sie einen Auszug aus einem Windows-Verzeichnisbaum einer Festplatte mit dem Laufwerksbuchstaben D:

[D:]
 |
 +-- [dokumente]
      |
      +-- [it-kompendium]
      |    |
      |    +-- betriebssysteme.doc
      |     
      +-- [sonstige]

Wenn Sie die Datei betriebssysteme.doc absolut ansprechen möchten, müssen Sie ihren vollständigen Pfad D:\dokumente\it-kompendium\betriebssysteme.doc angeben. Falls Sie sich dagegen bereits auf Laufwerk D: befinden, und zwar in einem beliebigen Verzeichnis, können Sie auch \dokumente\it-kompendium\betriebssysteme.doc schreiben. Ein relativer Zugriff aus dem Verzeichnis sonstige auf betriebssysteme.doc erfolgt über ..\it-kompendium\betriebssysteme.doc.

Das Konzept des Home-Verzeichnisses wird unter Windows bei weitem nicht so konsequent verfolgt wie in UNIX-Systemen. Zwar existiert auf der Systempartition ein Verzeichnis namens Dokumente und Einstellungen, das für jeden Benutzer ein Unterverzeichnis enthält. Darin befindet sich beispielsweise das Verzeichnis Eigene Dateien, in dem standardmäßig die Dateien gespeichert werden sollten, die der Benutzer in Anwendungsprogrammen anlegt. Konfigurationsdaten werden dagegen nicht an dieser Stelle abgespeichert – die meisten befinden sich ohnehin nicht in Dateien, sondern in der weiter unten behandelten Windows-Registry.

Dateiattribute

Zwar unterstützen nicht alle Windows-Dateisysteme die Verwaltung von Benutzerrechten, aber für jede Datei können vier verschiedene Attribute eingestellt werden: Das Attribut r steht für »Readonly«, also schreibgeschützt; s bezeichnet Systemdateien, die einen noch stärkeren Schutz genießen als schreibgeschützte. h oder »hidden« ist das Archiv für versteckte Dateien, die in der normalen Windows-Grundkonfiguration nicht angezeigt werden. a schließlich ist das Archiv-Attribut, das immer dann gesetzt wird, wenn die Datei seit dem letzten Systemstart geändert wurde - archivieren müssen Sie also nur diejenigen Dateien, bei denen a gesetzt ist. Wie Sie die Attribute modifizieren können, erfahren Sie weiter unten im Windows-Teil dieses Kapitels.

Dateinamen können unter Windows bis zu 255 Zeichen lang sein; zwischen Groß- und Kleinschreibung wird nicht unterschieden. Allerdings werden die Dateien genau mit der Groß- und Kleinbuchstabenkombination gespeichert, die Sie angegeben haben. Eine Reihe von Zeichen sind in Dateinamen nicht zulässig, vor allem :, \, ?, *, <, > und |. Alle diese Zeichen besitzen in Pfadangaben oder auf der Windows-Konsole besondere Bedeutungen.

Ein wesentlicher Bestandteil des Dateinamens ist unter Windows die Dateierweiterung oder -endung (extension). Dieses Anhängsel, das durch einen Punkt vom restlichen Dateinamen getrennt wird, zeigt nämlich den Dateityp an: Wenn Sie unter Windows auf ein Datei-Icon doppelklicken, wird die Datei mit demjenigen Programm geöffnet, mit dem diese Endung verknüpft ist. Beispielsweise bezeichnet die Erweiterung .txt eine einfache Textdatei, .jpg ist eine Bilddatei im JPEG-Format und .exe kennzeichnet ein ausführbares Programm.

Unglücklicherweise wird die Dateiendung in allen Windows-Versionen seit 95 standardmäßig ausgeblendet, obwohl sie im Grunde ein normaler Bestandteil des Dateinamens ist. Sie können also nur noch an den mehr oder weniger aussagefähigen Datei-Icons erkennen, um welche Art von Datei es sich handelt. Abhilfe schafft eine Einstellung in den Ordneroptionen, deren Position und Bezeichnung in den verschiedenen Windows-Versionen leider mehrmals verändert wurde. Unter Windows XP müssen Sie einen beliebigen Ordner öffnen, den Menüpunkt Extras • Ordneroptionen aufrufen und auf der Registerkarte Ansicht die Option Erweiterungen bei bekannten Dateitypen ausblenden deaktivieren. In älteren Windows-Versionen befindet sich dieser Menüpunkt unter Ansicht statt unter Extra.

Bei alten Windows-Versionen bis 3.11 waren Dateinamen auf acht Zeichen für den eigentlichen Namen und drei Zeichen für die Erweiterung begrenzt. Aus Gründen der Kompatibilität erzeugt Windows bis heute für jeden Dateinamen, der länger ist, einen passenden Kurznamen. Dieser besteht aus folgenden Bestandteilen: den ersten fünf bis sechs Zeichen des eigentlichen Namens ohne Leerzeichen, einer Tilde und einer Nummer (um den Fall abzudecken, dass mehrere Dateien im gleichen Verzeichnis denselben Kurznamen erhalten würden) sowie der auf drei Zeichen gekürzten Erweiterung. Aus »Der Name ist zu lang.doc« würde nach diesem Schema DERNAM~1.DOC.






  

Einstieg in PHP 5

Einstieg in Java

C von A bis Z

Einstieg in C++

Einstieg in Linux

Einstieg in XML

Apache 2




Copyright © Galileo Press GmbH 2004
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de