Debian GNU/Hurd
Übersetzer
Das Konzept
Bevor wir uns Übersetzer näher ansehen, sollte wir erst einen Blick auf gewöhnliche Dateisysteme werfen. Ein Dateisystem ist ein Speicher für einen hierarchischen Baum von Verzeichnissen und Dateien. Der Zugriff auf diese Verzeichnisse und Dateien erfolgt über eine spezielle Zeichenkette, den Pfad. Darüber hinaus gibt es symbolische Links, die an mehreren Stellen im Baum auf eine bestimmte Datei verweisen, und harte Links, welche ein und derselben Datei mehrere Namen geben. Außerdem gibt es spezielle Gerätedateien für die Kommunikation mit den im Kernel enthaltenen Gerätetreibern für die Hardware, und es gibt Einhängepunkte zum Einbinden anderer Speicher in den Verzeichnisbaum. Des Weiteren gibt es obskure Objekte wie zum Beispiel FIFOs.
All diese Objekte unterscheiden sich sehr, aber dennoch weisen sie einige gemeinsame Eigenschaften auf, beispielsweise sind allen ein Besitzer und eine Gruppe und auch Zugriffsrechte (Berechtigungen) beigefügt. Diese Informationen stehen in Inodes. Hierbei handelt es sich um eine weitere Gemeinsamkeit: Jedes Objekt ist mit genau einer Inode verknüpft (harte Links sind hier etwas ungewöhnlich, da sie sich ein und dieselbe Inode teilen). Manchmal ist in der Inode auch noch zusätzliche Information gespeichert. Zum Beispiel kann eine Inode das Ziel eines symbolischen Links enthalten.
Diese Gemeinsamkeiten werden jedoch gewöhnlich nicht in den
Implementierungen ausgeschöpft, obgleich ihnen eine gemeinsame
Programmierschnittstelle zu Eigen ist. Auf alle Inodes kann über die
Standard-POSIX-Aufrufe wie zum Beispiel read()
und
write()
zugegriffen werden. Wenn man nun also einen neuen
Objekttyp (beispielsweise einen neuen Link-Typ) dem gewöhnlich
monolithischen Unix-Kernel hinzufügen möchte, so ist es notwendig, den
Programm-Code für jedes Dateisystem einzeln abzuändern.
Beim Hurd läuft einiges anders. Obwohl im Hurd ein spezieller Dateisystemserver die speziellen Eigenschaften von Standard-Objekttypen wie Links nutzen kann (zum Beispiel mittels schnellen Links im Ext2-Dateisystem), weist der Hurd eine allgemein gehaltene Schnittstelle auf, über welche solche Fähigkeiten hinzugefügt werden können, ohne dass existierender Programm-Code verändert werden muss.
Der Trick liegt darin, einem Programm zu erlauben, sich zwischen den eigentlichen Inhalt einer Datei und den zugreifenden Benutzer einzufügen. Solch ein Programm wird Übersetzer genannt, denn es ist in der Lage, die eingehenden Anfragen auf viele unterschiedliche Arten zu verarbeiten. In anderen Worten gesagt ist ein Übersetzer ein Hurd-Server, der die grundlegende Schnittstelle zu Dateisystemen bereitstellt.
Übersetzer haben sehr interessante Eigenschaften. Aus Sicht des Kernels sind sie bloß ein weiterer Benutzerprozess. Das bedeutet, dass jeder Benutzer Übersetzer laufen lassen kann. Es werden keine Administratorrechte benötigt, um einen Übersetzer zu installieren oder zu verändern, man braucht nur die Zugriffsrechte zur unterliegenden Inode, an welche der Übersetzer angehängt ist. Für die Funktion vieler Übersetzer ist keine Datei erforderlich, sie können Informationen auf ihre eigenen Art und Weise liefern. Aus diesem Grund werden die Informationen über Übersetzer in der Inode gespeichert.
Übersetzer sind dafür verantwortlich, alle Dateisystemoperationen bereit zu
stellen, die mit der Inode zusammenhängen, an welche sie angehängt sind. Da
sie nicht auf den üblichen Satz von Objekten (Gerätedatei, Link, etc.)
beschränkt sind, steht es ihnen frei, alles zurückzugeben, was dem
entsprechenden Programmierer sinnvoll erscheint. Man stelle sich einen
Übersetzer vor, der sich wie ein Verzeichnis verhält, wenn er über
cd
oder ls
zugegriffen wird, und wie eine Datei,
wenn der Zugriff über cat
erfolgt.
Beispiele
Einhängepunkte
Ein Einhängepunkt kann als eine Inode angesehen werden, an welche ein spezieller Übersetzer angehängt wurde. Sein Zweck wäre es, Dateisystemoperationen am Einhängepunkt in Dateisystemoperationen auf einem anderen Speicher, sagen wir einer anderen Partition, zu übersetzen.
Und wirklich sind Dateisysteme genau so im Hurd implementiert. Ein Dateisystem ist ein Übersetzer. Dieser Übersetzer nimmt einen Speicher als Parameter und ist in der Lage, alle Dateisystemoperationen transparent bereit zu stellen.
Gerätedateien
Es gibt viele verschiedene Gerätedateien, und in Systemen mit einem
monolithischen Kernel werden sie alle vom Kernel selbst bereit gestellt. Im
Hurd werden alle Gerätedateien von Übersetzern bereit gestellt. Ein Übersetzer
kann die Unterstützung für viele ähnliche Gerätedateien, beispielsweise alle
Festplattenpartitionen, bereit stellen. Auf diese Weise ist die Anzahl der
insgesamt wirklich benötigten Übersetzer recht gering. Dennoch sollte man
bedenken, dass für jede zugegriffene Gerätedatei ein separater
Übersetzerprozess gestartet wird. Da der Hurd jedoch ausgesprochen
multi-threaded arbeitet (es laufen viele Fäden
von Programmen gleichzeitig),
ist dies nicht sonderlich aufwändig.
Wenn Hardware im Spiel ist, dann beginnt ein Übersetzer für gewöhnlich mit dem
Kernel zu kommunizieren, um Daten von der Hardware zu erhalten. Wenn jedoch
kein Hardwarezugriff notwendig ist, dann braucht der Kernel nicht beteiligt zu
werden. Zum Beispiel erfordert /dev/zero
keinen Hardwarezugriff
und kann somit komplett im normalen Benutzerkontext eingerichtet werden.
Symbolische Links
Ein symbolischer Link kann als Übersetzer angesehen werden. Beim Zugriff auf den symbolischen Link wird ein Übersetzer gestartet, welcher die Anfrage weiterleitet an das Dateisystem, welches die im Link referenzierte Datei beinhaltet.
Um jedoch bessere Leistung zu erzielen, können Dateisysteme, die symbolische Links nativ unterstützen, dieses Merkmal zu ihrem Vorteil nutzen und symbolische Links auf unterschiedliche Art einrichten. Intern würde der Zugriff auf einen symbolischen Link keinen neuen Übersetzerprozess starten. Für den Benutzer würde es jedoch immer noch so aussehen, als sei ein passiver Übersetzer involviert (siehe unten betreffend eine Erklärung von passiven Übersetzern).
Da der Hurd einen Übersetzer für symbolische Links mitliefert, hat jeder Dateisystemserver mit Unterstützung für Übersetzer auch automatisch Unterstützung für symbolische Links (und harte Links, und Gerätedateien, etc.)! Das bedeutet, dass man sehr schnell ein funktionierendes Dateisystem erhalten und native Unterstützung für symbolische Links und andere Merkmale später hinzufügen kann.
Passive Übersetzer, Aktive Übersetzer
Es gibt zwei Typen von Übersetzern, passive und aktive. Sie sind wirklich komplett unterschiedlich, man vermische die Begriffe also besser nicht, aber sie stehen in naher Relation zu einander.
Aktive Übersetzer
Ein aktiver Übersetzer ist ein laufender Übersetzerprozess wie oben eingeführt.
Man kann aktive Übersetzer einrichten und entfernen mit dem Befehl
settrans -a
. Die Option -a
teilt
settrans
mit, dass der aktive Übersetzer verändert werden soll.
Der Befehl settrans
akzeptiert drei Arten von Parametern. Als
erstes kann man Optionen für den Befehl settrans
selbst setzen,
wie -a
zum Verändern des aktiven Übersetzers. Dann gibt man die
Inode an, die man verändern möchte. Bedenke, dass ein Übersetzer immer mit
einer Inode in der Verzeichnishierarchie verknüpft ist. Man kann nur eine
Inode auf einmal verändern. Wenn man keine weiteren Parameter angibt, dann
wird settrans
das Entfernen eines existierenden Übersetzers
versuchen. Wie intensiv dieses Entfernen versucht wird, hängt davon ab, welche
Optionen zum Forcieren des Vorgangs gesetzt werden (wenn ein Übersetzer noch
durch irgendeinen Prozess in Benutzung ist, dann erhält man die Fehlermeldung
Gerät oder Ressource beschäftigt
(device or resource busy
), es sei denn,
man zwingt ihn zum Beenden).
Wenn man hingegen weitere Parameter angibt, dann werden diese als eine
Kommandozeile zum Starten des Übersetzers interpretiert. Das bedeutet, der
nächste Parameter ist der Dateiname der ausführbaren Datei des Übersetzers.
Weitere Parameter sind dann Optionen für den Übersetzer und nicht für den
Befehl settrans
.
Um zum Beispiel eine Ext2fs-Partition einzuhängen, kann man
settrans -a -c /mnt /hurd/ext2fs /dev/hd2s5
aufrufen. Die Option
-c
wird einen Einhängepunkt einrichten, sofern er noch nicht
existieren sollte. Dies muss übrigens nicht notwendigerweise ein Verzeichnis
sein. Zum Aushängen nutzt man dann settrans -a /mnt
.
Passive Übersetzer
Ein passiver Übersetzer wird eingerichtet und verändert mit derselben Syntax
wie ein aktiver Übersetzer (nur die Option -a
wird weg gelassen),
somit gilt das oben Erwähnte auch für passive Übersetzer. Ein Unterschied
besteht jedoch: passive Übersetzer sind noch nicht gestartet.
Dies ist sinnvoll, denn dies ist was man gewöhnlich möchte. Man will eine Partitionen nicht eingehängt haben, es sei denn, man greift auch wirklich darauf zu. Man will die Netzwerkfunktionalität nicht laden bevor nicht Netzwerkverkehr herrscht, und so weiter.
Das erste Mal, wenn auf einen passiven Übersetzer zugegriffen wird, wird stattdessen die Inode ausgelesen und ein aktiver Übersetzer wird ihr angehängt unter Benutzung der Kommandozeile, die in die Inode gespeichert wurde. Dies ähnelt der Funktionalität zum automatischen Einhängen unter Linux (automounter). Es stellt jedoch keinen zusätzlichen Bonus dar, den man erst manuell einrichten muss, sondern ist ein integraler Bestandteil des Systems. Das Einrichten eines passiven Übersetzers verzögert also das Starten des Übersetzerprozesses, bis man ihn auch wirklich benötigt. Übrigens, wenn der aktive Übersetzer aus irgendwelchen Gründen sterben sollte, so wird er einfach beim nächsten Zugriff auf die Inode neu gestartet.
Es gibt einen weiteren Unterschied: aktive Übersetzer können sterben oder
verloren gehen. Sobald der Prozess eines aktiven Übersetzers getötet wurde
(zum Beispiel aufgrund eines Neustarts des Rechners), ist er für immer
verloren. Passive Übersetzer sind nicht vergänglich und bleiben über einen
Neustart hinweg in der Inode, bis man sie mittels des Befehls
settrans
verändert oder die Inode löscht, an welche sie angehängt
sind. Das bedeutet, dass man keine Konfigurationsdatei zu den Einhängepunkten
führen muss.
Ein letzter Punkt: Selbst wenn schon ein passiver Übersetzer eingerichtet ist, kann man immer noch einen anderen aktiven Übersetzer einrichten. Nur wenn der Übersetzer automatisch gestartet wurde, weil zum Zeitpunkt des Zugriffs auf die Inode kein aktiver Übersetzer existierte, nur dann wird der passive Übersetzer berücksichtigt.
Verwalten von Übersetzern
Wie oben erwähnt kann man settrans
nutzen zum Einrichten und
Verändern von passiven und aktiven Übersetzern. Es gibt eine Vielzahl von
Optionen, mit denen man das Verhalten von settrans
im Fehlerfall
und zur Beeinflussung von Aktionen anpassen kann. Hier ein paar übliche
Nutzanwendungen:
settrans -c /mnt /hurd/ext2fs /dev/hd2s5
hängt eine Partition ein, der Übersetzer wird einen Neustart überleben.settrans -a /mnt /hurd/ext2fs ~/dummy.fs
hängt ein Dateisystem aus einer Datei ein, der Übersetzer wird verschwinden wenn er sterben sollte.settrans -fg /nfs-data
zwingt einen Übersetzer zum Verschwinden.
Man kann den Befehl
showtrans
nutzen um
nachzusehen, ob ein Übersetzer an eine Inode angehängt ist. Dies wird jedoch nur
den passiven Übersetzer anzeigen.
Man kann die Optionen eines aktiven (Dateisystem-)Übersetzers mittels
fsysopts
verändern, ohne ihn dabei neu starten zu müssen. Das ist
sehr praktisch. Zum Beispiel kann man das, was unter Linux eine Partition
nur-lesend neu Einhängen
(remounting a partition read-only
) genannt wird,
mit einem schlichten fsysopts /mntpoint --readonly
erledigen.
Der laufende aktive Übersetzer wird sein Verhalten soweit wie irgend möglich
entsprechend der Anfrage anpassen. fsysopts /mntpoint
ohne
Parameter zeigt die aktuellen Einstellungen.
Beispiele
Am Anfang ist es empfehlenswert, sich den Befehl /bin/mount
durchzulesen, es ist nur ein kleines Skript. Da das Einrichten eines
Dateisystemübersetzers dem Einhängen von Partitionen ähnelt, lässt sich
das Konzept auf diese Art schnell verstehen. Erstellen Sie ein
Dateisystem-Image mittels dd if=/dev/zero of=dummy.fs bs=1024k
count=8; mke2fs dummy.fs
und versuchen Sie, es mit
settrans -c dummy /hurd/ext2fs `pwd`/dummy.fs
einzuhängen
.
Man beachte, dass der Übersetzer noch nicht gestartet wird, es läuft kein
neuer Ext2fs-Prozess (was man mit ps Aux
überprüfen kann).
Überprüfen Sie alles auf Korrektheit mit showtrans
.
Nun geben Sie ls dummy
ein und Sie werden eine kurze Verzögerung
wegen des Startens des Übersetzers bemerken. Danach werden beim Zugriff auf
dummy keine weiteren Verzögerungen mehr auftreten. Unter Linux würde man
sagen, man habe ein lokales Loop-Dateisystem automatisch eingehängt
(automounted a loop file system). Überprüfen Sie mit ps Aux
, ob
ein Prozess ext2fs dummy
gerade läuft. Nun übertragen sie ein
paar Dateien in das neue Verzeichnis. Versuchen Sie, das Dateisystem mit
fsysopts
auf nur-lesend zu setzen. Man beachte, wie daraufhin
weitere Schreibversuche scheitern werden. Versuchen Sie, den aktiven
Übersetzer mit settrans -g
zu entfernen.
Sie dürften nun ein gewisses Verständnis dafür haben, was dabei passiert. Nun
erinnere man sich aber daran, dass dies nur ein spezieller Server
war, der Hurd Ext2fs-Server. Es gibt viele weitere Server im Verzeichnis
hurd
. Manche von ihnen sind für Dateisysteme. Manche werden für
Dateisystemeigenarten wie Links benötigt. Manche braucht man für
Gerätedateien. Manche sind nützlich für Netzwerke. Stellen Sie sich vor, einen
FTP-Server mit settrans
einzuhängen
und Dateien einfach mit dem
Standard-Befehl cp
herunterzuladen. Oder das Bearbeiten Ihrer
Webpräsenz mit emacs /ftp/homepage.my.server.org/index.html
!