Hurd ist - wie der Titel dieses Vortrages andeutet - kein Kernel, sondern ein Kernel-Ersatz. Es handelt sich bei Hurd um eine Sammlung von Daemonen (auch als "Server" bezeichnet), die auf dem Mach Mikrokernel laufen und gemeinsam mit der GNU C Bibliothek (glibc) die Funktionalit舩 eines Unix-Kernels bereitstellen, bis auf die wenigen Aspekte, die bereits von Mach angeboten werden. Damit ist das Hurd-basierte GNU-System ein POSIX-konformes Betriebssystem.
An dieser Stelle einige Worte zur Terminologie: Es wird unterschieden zwischen GNU Hurd, oder einfach nur Hurd, und dem vollst舅digen, Hurd-basierten GNU-System, jenes als GNU/Hurd bezeichnet wird. Es gibt zwar auch andere Varianten von GNU, n舂lich das Linux-basierte GNU-System und eines, das auf einem nicht-freien Kernel aufsetzt, doch wenn von "dem GNU-System" oder einfach nur "GNU" gesprochen wird, ist blicherweise GNU/Hurd gemeint.
Im Detail funktioniert das folgenderma゚en: Applikationen aus der Unix-Welt, hier als POSIX-Applikationen bezeichnet, nutzen die C Bibliothek fr Unix-Systemrufe. Die glibc implementiert entsprechende Funktionen und nutzt dabei die Dienste der Hurd-Server und teilweise auch des Mach Kernels. Die Hurd-Server wiederum nutzen auch Funktionen aus der glibc, da es sich prinzipiell um gewnliche Prozesse bzw. Daemonen handelt. Diese nutzen dabei ebenfalls Dienste von Mach. Denkbar sind natrlich auch Programme, die direkt mit den Hurd-Servern kommunizieren. Solche Programme sollten aber eher die Minderheit stellen, da in der Regel POSIX-Konformit舩 sinnvoll ist. (Zumindest, solange es noch andere Betriebssysteme gibt.)
In diesem Zusammenhang mhte ich aber schon einmal vorwegnehmen, dass die meisten Programme nicht an die besonderen F臧igkeiten von Hurd angepasst werden mssen, um von diesen profitieren zu knen, da diese berwiegend transparent angeboten werden. Das bedeutet, dass auch die ganzen POSIX-Applikationen m臘htiger werden.
Die POSIX-Konformit舩 ist wohl einer der entscheidenden Punkte, in denen sich das GNU-System von anderen Multiserver-Mikrokernelsystemen unterscheidet. Das schste System nutzt schlie゚lich nichts, wenn es keine Applikationen dafr gibt. Eine abschlie゚ende Bemerkung zu dem Thema sei gestattet, da es ein h舫figes Missverst舅dnis ist: Oft wird behauptet, selbst das propriet舐e System Microsoft Windows NT sei POSIX-konform. Tats臘hlich implementiert es zwar die POSIX-Systemrufe, aber POSIX umfasst weit mehr als nur diese.
Hurd ist ein Teil des GNU-Projektes. GNU wurde in den 80er Jahren von Richard Matthew Stallman mit der Zielsetzung ins Leben gerufen, ein vollst舅diges Betriebssystem zu erschaffen, das ausschlie゚lich aus Freier Software besteht. Dabei wurden bereits als Freie Software existierende Komponenten verwendet, sofern diese vorhanden waren, etwa das X11 Fenstersystem oder TeX. Hier kann man sich also ernsthaft die Frage stellen, warum Hurd entwickelt wird, obwohl mit Linux eine ausgreifte Basis fr das GNU-System existiert.
Die Antwort darauf ist sehr einfach: H舩te Linux bereits existiert (und w舐e dabei noch einigerma゚en portabel gewesen, denn das war Linux zu Beginn nicht), als die Free Software Foundation mit der Entwicklung von Hurd begann, h舩te man wohl in der Tat den Kernel Linux verwendet. Und tats臘hlich hatte die Free Software Foundation wenig Interesse daran, bei Null zu beginnen, und hat daher den bereits exitierenden Mach Mikrokernel als Basis genutzt. Nachdem es durch Linux allerdings mlich wurde, einen Computer zu benutzen, ohne propriet舐e Software einzusetzen, hatte die Weiterentwicklung von Hurd keine hohe Priorit舩 mehr, zwischenzeitlich stand die Entwicklung sogar praktisch still.
Dies ist allerdings keineswegs der einzige Grund, wegen dem Hurd erst auf dem jetzigen Stand der Entwicklung ist, w舐end das Linux-basierte GNU-System bereits in einer etwas heren Liga spielt. Ein weiterer wichtiger Grund dafr ist, dass Hurd mit dem gleichen Ziel entwickelt wurde wie die brige GNU-Software: Besser zu sein als das jeweilige トquivalent der Unix-Welt.
Viele Unix-Programme tragen willkrliche Einschr舅kungen in sich, etwa werden von manchen Tools lange Eingabezeilen stillschweigend nach einer bestimmten Anzahl Zeichen abgeschnitten. So etwas war fr GNU niemals akzeptabel. Der Ehrgeiz, es besser zu machen, fhrte zu Programmen, die tats臘hlich flexibler und leistungsf臧iger waren als entsprechende Unix-Werkzeuge. In gleicher Weise sollte Hurd den Unix-Kernel bertreffen, also seine Einschr舅kungen vermeiden.
Was aber sind nun die Einschr舅kungen des Unix-Kernels? In erster Linie sind es solche, die vergleichbar mit denen aus angestaubten Unix-Programmen sind. Ein typisches Beispiel w舐e die Beschr舅kung auf die L舅ge von Pfadnamen. Doch dies ist keineswegs das grte Problem. Weitaus unangenehmer ist in der Praxis die monolitische Natur des Kernels. Bei n臧erer Betrachtung zeigt sich n舂lich, dass der Unix-Kernel in keiner Weise die Unix-Philosophie wiederspiegelt, denn diese propagiert beispielsweise kleine Programme, die genau eine Aufgabe erfllen. Der Kernel hingegen enth舁t neben Hardware-Treibern auch Treiber fr Dinge wie Dateisysteme und Netzwerkprotokolle, bei denen es keinen Grund gibt, sie im Kernel zu haben. Man mag als Grund hier natrlich die Geschwindigkeit anfhren, und in der Tat war der TCP/IP Stack immer als externe Komponente konzipiert, bis er dann aus Performancegrnden in den Kernel verlegt wurde. Doch selbst unter der Annahme, dass das Argument der heren Geschwindigkeit auch heute noch gltig sei, wrde man damit zugeben, dass man hier auf einmal nicht mehr der Unix-Philosophie folgt, denn diese hat Geschwindigkeit immer geringer gesch舩zt als beispielsweise Aspekte der Wartbarkeit.
Warum passt der Unix-Kernel aber nicht so Recht zum Rest des Systems? Es liegt gewiss nicht daran, dass die Erfinder von Unix unf臧ig waren, im Gegenteil: Unix ist sicherlich ein geniales Stck Technologie, das sich aus guten Grnden bis heute gehalten hat. Allerdings waren die Rechner, auf denen Unix ursprnglich lief, kaum mit den heutigen vergleichbar. Der Kompromiss, den Unix-Kernel anders zu gestalten als den Rest des Systems, war einfach eine Notwendigkeit. Und genau das ist es, was das GNU-System - aus technischer Sicht - von Unix unterscheidet: Es wird angenommen, dass ein solcher Kompromiss heute nicht mehr nig ist und sogar mehr schadet, als er ntzt.
Anders gesagt: Es ist schon schlimm genug, dass uns durch Hardware Grenzen gesetzt werden. Daher sollten wir keine zus舩zlichen in die Software einbauen.
Nachdem am Anfang bereits ein kurzer ワberblick ber die generelle Architektur gegeben wurde, soll hier vertieft werden, wie die einzelnen Komponenten zusammenarbeiten. Ein System, das sich vom Aufbau her so grundlegend von traditionellen Systemen unterscheidet, besitzt natrlich seine eigene Terminologie, d.h. neben dem Mikrokernel-Jargon gibt es zus舩zlich auch einen eigenen Hurd-Jargon, weshalb im Folgenden eine ganze Reihe neuer Begriffe eingefhrt wird. Au゚erdem wird es jetzt vorbergehend ein wenig theoretisch, doch ich werde bald darauf zurckkommen, was all dies fr den Benutzer bedeutet.
Ein Hurd-Server bietet einen Dienst an - Das ist naheliegend. Da ein solcher Server ein Prozess ist, verwenden andere Prozesse, die seine Dienste in Anspruch nehmen wollen, IPC (Inter Process Communication bzw. im Deutschen "Interprozesskommunikation"), um mit ihm zu kommunizieren - Auch das berrascht nicht. In Mikrokernelsystemen ist die wichtigste Art der IPC das sogenannte "Message-Passing", also das ワbergeben von Nachrichten. Eine solche Nachricht wird ber einen "Port" bergeben, d.h. der Client sendet eine Nachricht an den Port, der Server empf舅gt sie von dort. Ein Port ist also sozusagen eine Nachrichten-Warteschlange und ein Client sendet Anfragen in Form von Nachrichten ber einen Port an den Server. In der Praxis wird dann der Mach Interface Generator (MiG) verwendet, um sogenannten Stub-Code zu erzeugen, durch den das Senden einer bestimmten Nachricht in Form eines einfachen Funktionsaufrufes durchgefhrt wird. Dies bezeichnet man als "Remote Procedure Calls" (RPCs).
Nun ist aber noch die Frage offen geblieben, wie ein Client denn an einen Port herankommen kann. Was msste also z.B. ein Programm tun, um den Password-Server zu kontaktieren, der im Austausch gegen eine User-ID und das entsprechende Passwort ein passendes Authentifikationstoken herausrckt (Was das genau bedeutet, werden wir sp舩er sehen)? Die Antwort lautet: Er muss das gleiche tun, was ein Prozess tun muss, um eine Datei zu fnen, wenn er im Austausch auf eine Lese-Anforderung entsprechende Daten erhalten will. D.h. w舐end traditionelle Multiserver einen zentralen "Telefonbuch-Server" haben, der einem Client den Port liefert, der einer bestimmten Bezeichnung entspricht, gibt es bei Hurd eine Reihe solcher Telefonbcher - n舂lich die Dateisystem-Server - die hierarchisch angeordnet sind.
Neben dem Dateisystem gibt es noch weitere Mlichkeiten, an einen Port zu kommen, etwa kann ein Port auch in einer versendeten Nachricht bergeben werden, z.B. um eine Antwort auf eine Nachricht schicken zu knen.
Das bedeutet erstens, dass jeder Benutzer seine eigenen Dateisysteme bzw. Dateisystem-Erweiterungen in den Teilen des Verzeichnisbaumes platzieren kann, ber die er die Kontrolle hat. Wir bezeichnen diese Server als ワbersetzer bzw. Translatoren. Im Hurd-basierten GNU-System kann also jeder Benutzer innerhalb seines Heimverzeichnisses eigene Dateisysteme verwenden, wenn er das will. Was unter GNU/Linux als Loopback-Mounten bekannt ist, kann hier vlig problemlos jedem gestattet werden, da ein dafr verwendeter ext2-Server (oder ein beliebiger anderer) mit den Berechtigungen des Benutzers l舫ft, der ihn gestartet hat und somit dem System nicht mehr Schaden zufgen kann als jeder andere Prozess auch.
Zus舩zlich sind aber ebenso rein virtuelle Dateisysteme denkbar, prinzipiell vergleichbar mit devfs oder dem /proc Dateisystem unter GNU/Linux, mit dem Unterschied, dass diese hier als gewnliche Programme laufen wrden, was interessante Lungen fr verschiedendste Problemstellungen ermlicht. So existiert z.B. ein ワbersetzer, dem man als Argument beim Starten eine Kommandozeile bergibt. Wenn jemand die von ihm bereitgestellte Datei fnet, fhrt er das betreffende Kommando aus. Wenn nun derjenige, der die Datei gefnet hat, daraus lesen will, bekommt er die Daten, die das vom ワbersetzer gestartete Programm an seine Standardausgabe geschrieben hat. Diesen ワbersetzer knte man z.B. auf seiner ~/.signature platzieren und ihn jedes mal ein Fortune-Cookie zurckliefern lassen, wenn ein E-Mail-Client ihn fnet, um die Signatur auszulesen.
Zweitens bewirkt das Konzept der ワbersetzer, dass neben Dateisystemen auch beliebige andere Dienste ber das Dateisystem angeboten werden knen. Ein typisches Beispiel hierfr ist der oben erw臧nte Password-Server, ein anderes w舐e die Socket-Schnittstelle. Ermlicht werden dadurch auch vlig neue Ans舩ze, etwa ist eine grafische Benutzeroberfl臘he - oder auch nur ein X11-Toolkit - denkbar, das neben der Bildschirmausgabe auch noch alle Widgets und Fenster im Dateisystem darstellt, wodurch Aktionen nicht nur vom Benutzer durchgefhrt werden knen, sondern auch von Programmen. Das w舐e nicht zuletzt zum automatisierten Testen von GUI-Applikationen interessant.
Denken Sie bei Gelegenheit einmal darber nach, was durch ワbersetzer alles realisierbar ist. Ich bin sicher, dass Ihnen eine Menge interessanter Dinge einfallen werden, an die noch keiner vor Ihnen gedacht hat.
Die Tatsache, dass es sich bei fast allen Komponenten um gewnliche Prozesse handelt, bedeutet auch, dass jeder Benutzer seinen eigenen Hurd starten kann, also einen "Neighborhurd". Damit kann er praktisch s舂tliche Server durch seine eigenen Implementierungen ersetzen. Da diese Prozesse in einem separaten Hurd laufen, knen sie au゚erhalb keinen Schaden anrichten. Sie knen noch nicht einmal die au゚erhalb laufenden Prozesse sehen, allerdings sind alle Prozesse des Neighborhurds ber den Haupt proc-Server des Systems sichtbar, damit der Administrator auch ber diese Prozesse Kontrolle hat.
GNU/Hurd kann noch nicht in allen Bereichen mit anderen Systemen mithalten, aber es ist fr bestimmte Aufgaben ausreichend. Die allgemeine Stabilit舩 des Systems ist noch nicht ganz zufriedenstellend, verbessert sich aber kontinuierlich. Ich hatte jedenfalls in den letzten Montaten keinen Absturz zu beklagen.
Dafr ist die Feature-Liste bereits sehr interessant, obwohl noch nicht alle geplanten Mlichkeiten implementiert sind. Ich mhte hier einige Beispiele liefern. Ein sehr prominenter Hurd-ワbersetzer ist etwa das FTP-Dateisystem. Die Idee ist eigentlich recht naheliegend, weshalb es auch fr Linux inzwischen ein ftpfs-Modul gibt, schlie゚lich l舖st sich prinzipiell fast alles sowohl im Kernelspace als auch im Userspace implementieren. Falls man also der Administrator eines Rechners ist (und einem darber hinaus gelegentliche Kernel-Panics nichts ausmachen), kann man dieses komfortable Feature also auch unter GNU/Linux nutzen.
Das ftpfs von Hurd verwendet man, indem man mit dem Befehl "settrans" den betreffenden ワbersetzer mit passendem Argument auf eine entsprechenden Node setzt:
settrans -ac debian-ftp /hurd/ftpfs ftp.debian.org
Nun knte man ber das Verzeichnis "debian-ftp" auf den entsprechenden FTP-Server zugreifen. Manch einer wendet zwar als Argument gegen ftpfs ein, dass bestimmte Operationen - etwa das anh舅gende Schreiben einer Datei - hierbei unverh舁tnism葹ig langsamer sind als bei gewnlichen Dateisystemen, aber dies 舅dert nichts daran, dass ftpfs prinzipiell eine ntzliche Funktionalit舩 bereitstellt.
Die Option "c" in obigem Beispiel bewirkt, dass die entsprechende Node erstellt wird, wenn sie noch nicht existiert und die Option "a" macht daraus einen aktiven ワbersetzer. Dies bedeutet, dass er sofort gestartet wird und er nicht mehr existiert, wenn er beendet wird, etwa weil er abstrzt oder weil der Rechner neu gestartet wird. Ein passiver ワbersetzer wrde im Gegensatz dazu mitsamt seinen Argumenten im Dateisystem gespeichert und gestartet, wann immer jemand auf die betreffende Node zugreift und er noch nicht gestartet ist. Er wrde also auch nach einem Reboot des Systems wieder verfgbar sein.
Damit man nicht fr jeden entfernten Rechner, auf den man zugreifen mhte, einen einzelnen ワbersetzer von Hand starten muss, gibt es den "hostmux" ワbersetzer, also einen Host-Multiplexer. Diesen aktiviert man z.B. einmal so:
settrans -ac /ftp /hurd/hostmux /hurd/ftpfs
Das Verzeichnis /ftp wird dabei anf舅glich leer sein, doch wenn man darin auf ein bestimmtes Unterverzeichnis zugreifen will, etwa /ftp/ftp.debian.org/, wird ein entsprechender /hurd/ftpfs ワbersetzer gestartet. Dabei sorgt hostmux dafr, dass nicht mehrere ワbersetzer gestartet werden, nur weil einmal ber den Hostnamen ein einmal ber seine IP-Adresse darauf zugegriffen wird.
Als n臘hstes Beispiel mhte ich ein etwas ungewnliches Dateisystem heranziehen. Wir nennen es "ShadowFS". Es existiert gegenw舐tig nur eine unfertige Implementierung davon, doch diese ist prinzipiell bereits funktionstchtig. Als Argumente erwartet ShadowFS eine Liste von Verzeichnissen:
settrans -ac shadowed /hurd/shadowfs /bin /local/bin ~/bin
Das resultierende Verzeichnis, hier "shadowed" genannt, ist die Vereinigung der brigen Verzeichnisse, enth舁t also alle Dateien aus ihnen. Gleiches gilt fr die Unterverzeichnisse, sofern welche existieren. Wenn in mehreren der Verzeichnisse eine Datei gleichen Namens liegt, hat natrlich eines den Vorrang, d.h. die Verzeichnisse liegen auf unterschiedlichen Ebenen bereinander. Man kann also Speichermedien damit orthogonal zu "mount" miteinander vereinen.
Falls Sie sich fragen, wozu dies dient, hier zwei Anwendungsf舁le: Man knte damit ein System realisieren, dass von CD-ROM gebootet werden kann, aber トnderungen zul舖st, da es sie auf einem beschreibbaren Speichermedium ablegt, oder alternativ auch auf tmpfs, einem Dateisystem im RAM. Der zweite Anwendungsfall ist weniger naheliegend: Wir verwenden ShadowFS, um das /usr-Verzeichnis loszuwerden. Natrlich gibt es zur Erhaltung der Kompatiblit舩 noch einen symbolischen Link von /usr auf das Wurzelverzeichnis, aber die lediglich aus technischen Grnden bisher notwendige Trennung kann entfallen, da die zum Booten notwendigen Dinge durchaus weiterhin auf einer Partition liegen knen und die zus舩zlichen Benutzerprogramme auf einer anderen, greren Partition. Doch man muss die Benutzer nicht durch eine zus舩zliche, semantisch fragwrdige Stufe in der Hierarchie verwirren.
Nun kommen wir zu dem Teil, der wohl haupts臘hlich fr Programmierer interessant ist. Ich werde zun臘hst einen ワberblick ber die Schnittstellen und Bibliotheken des Hurd geben und anschlie゚end einen Einblick in die Entwicklung eines einfachen Hurd-ワbersetzers geben.
Die glibc bietet zwar die POSIX-Schnittstelle an, doch von den Hurd-Servern werden andere, reichhaltigere Schnittstellen implementiert. Die Definitionen dieser Schnittstellen liegen in der von MiG verstandenen Interface-Definitionssprache vor (die ein wenig an Pascal erinnert), damit er automatisch entsprechende Stubs fr die Clients generieren kann. Damit haben Clients die Wahl zwischen den Hurd-Schnittstellen und der POSIX-API, w舐end die Server immer die Schnittstellen des Hurd implementieren mssen. Im Folgenden werde ich einige wichtige Schnittstellen beschreiben, und welche RPCs sie unter anderem umfassen.
Der Name eines jeden RPCs wird dabei mit einem Pr臟ix versehen, das kennzeichnet, auf was fr eine Art von Port er sich bezieht. Meistens ist dieses Pr臟ix der Name der Schnittstelle, etwa hei゚en die RPCs aus der io-Schnitstelle "io_read", "io_write", "io_seek", "io_map" usw.
Dateisystemoperationen wie das トndern der Berechtigungen ("file_chmod"), das Setzen eines ワbersetzers fr Dateien ("file_set_translator"), das Lesen eines Verzeichnisinhaltes ("dir_readdir") sowie das Erstellen von neuen Unterverzeichnissen ("dir_mkdir") sind RPCs aus der fs-Schnitstelle. Hierbei wird also zwischen verschiedenen Typen unterschieden, denn das Auflisten eines Verzeichnisinhaltes und das Erstellen eines neuen Unterverzeichnisses sind Operationen, die nur sinnvoll sind, wenn sie auf ein Verzeichnis angewendet werden.
Darber hinaus gibt es auch die fsys-Schnittstelle, die Kontrolloperationen fr Dateisysteme umfasst, z.B. knen mit "fsys_set_options" die Kommandozeilenargumente des ワbersetzers nachtr臠lich manipuliert werden (dieser RPC wird insbesondere vom Benutzerprogramm "fsysopts" verwendet) und mit "fsys_goaway" fordert man einen ワbersetzer auf, zu sterben.
Das auth-Interface ist sehr wichtig. Man kann damit die Mlichkeiten des flexiblen Umgangs mit Berechtigungen in Hurd nutzen. Jeder Prozess kann eine beliebige Menge an effektiven User-IDs zugleich haben, eventuell auch gar keine; gleiches gilt fr effektive Group-IDs. Desweiteren gibt es jeweils einen Satz an verfgbaren User-IDs und Group-IDs, die mit Hilfe des auth-Servers in entsprechende effektive IDs umgewandelt werden knen. Ein Satz aus diesen IDs entspricht einem Port zum auth-Server, d.h. verwaltet werden diese von auth. Der Administrator kann einen neuen auth-Port erzeugen, der beliebige IDs repr舖entiert. Au゚erdem kann man natrlich jederzeit IDs, ber die man verfgt, aufgeben. Interessant wird dies alles insbesondere im Zusammenspiel mit dem Password-Server. Bevor ich aber auf den Password-Server eingehe, mhte ich noch ein weiteres Feature von auth nennen. Da auth die IDs kennt, ber die jemand verfgt, kann er verwendet werden, um eine "trusted connection" zwischen einem Client und einem Server aufzubauen. Der Client wrde einen sog. Rendezvous-Port erzeugen und diesem dem Server berreichen. Dann kontaktieren sowohl Client als auch Server den auth-Server und bergeben ihm den Rendezvous-Port bzw. der Server liefert zus舩zlich einen Server-Port. Der auth-Server erkennt die beiden Anfragen anhand des bereinstimmenden Rendezvous-Ports und liefert daraufhin dem Client den Server-Port und dem Server die IDs des Clients.
Das password-Interface wird von /hurd/password implementiert, dies ist der Password-Server. Einen Port zu ihm erh舁t man ber /servers/password. Im Verzeichnis /servers sind diverse Server zu finden, z.B. auch der crash-Server, der etwa fr das Erzeugen von Coredumps verantwortlich ist. Wozu dient nun aber der Password-Server? Man bergibt ihm eine User- oder Group-ID und ein Passwort. Wenn das Passwort korrekt ist, erh舁t man einen entsprechenden auth-Port. Der Password-Server kann diesen erzeugen, da er mit Superuser-Rechten l舫ft. Man kann also unter Hurd seine Rechte sowohl senken als auch erhen. Dadurch wird etwa - und das ist ein sehr beliebtes Beispiel dafr - ein FTP-Server denkbar, der ohne IDs l舫ft, solange der Kommunikationspartner sich noch nicht identifiziert hat und sich vom Password-Server die entsprechenden Rechte holt, wenn der entfernte Benutzer einen Benutzernamen und ein Passwort liefert. Es wrde die Notwendigkeit fr den FTP-Server entfallen, mit Fremden zu kommunizieren, w舐end er Superuser-Rechte hat. Dadurch g臙e es zwar einige Remote-Root-Exploits weniger, doch das nehmen wir ganz gerne in Kauf.
Man kann zwar auch direkt die RPCs der Hurd-Schnitstellen implementieren, doch um das Entwickeln von ワbersetzern einfacher zu machen, gibt es diverse Bibliotheken. Auf der einen Seite sind das allgemein ntzliche Bibliotheken wie libports, die ntzliche Funktionen im Umgang mit Ports bietet und zudem eine Abstraktionsschicht repr舖entiert, die beschreibt, welche Erwartungen Hurd an einen Mikrokernel im Bezug auf die im Zusammenhang mit Ports angebotene Funktionalit舩 hat.
Darber hinaus gibt es Bibliotheken, die speziell fr bestimmte Arten von ワbersetzern geeignet sind: Die netfs Bibliothek wird verwendet, um Dateisysteme zu schreiben, jene die zu Grunde liegenden Daten nicht kontrollieren. Das sind typischerweise s舂tliche Dateisysteme, die Daten ber das Netzwerk anfordern, wie ftpfs und nfs. Allerdings z臧len hierzu auch einige andere ワbersetzer, z.B. das weiter oben erl舫terte ShadowFS. Die diskfs Bibliothek wird hingegen verwendet, wenn ein Dateisystem die direkte Kontrolle ber die Daten hat, wie bei UFS, ext2fs und dem derzeit noch leicht fehlerhaften tmpfs. Und dann gibt es auch noch die trivfs Bibliothek, die man fr ワbersetzer verwendet, die kein ganzes Dateisystem bereitstellen, sondern lediglich eine einzelne Datei. Auf letztere Bibliothek werde ich im Folgenden n臧er eingehen, doch auch hier kann ich natrlich nur an der Oberfl臘he kratzen.
Ich werde als Beispiel den ersten ワbersetzer heranziehen, den ich jemals unter GNU geschrieben habe. Er macht fast das gleiche wie /dev/zero, mit dem Unterschied, dass er nicht unendlich viele Nullen liefert, sondern unendlich viele Einsen. Ich nenne ihn daher /dev/one.
Trivfs bietet nach au゚en hin nicht besonders viele Funktionen an, im Gegenteil: Man muss eine Reihe von Funktionen implementieren, die trivfs dann aufrufen wird. Die meisten dieser Funktionen sehen beinahe aus wie Implementierungen verschiedener RPCs, allerdings handelt es sich um trivfs-spezifische Abwandlungen davon, daher werden sie mit dem Pr臟ix "trivfs" versehen. Beispielsweise hei゚t die Funktion, die Leseanforderungen behandeln soll in einem trivfs-ワbersetzer "trivfs_S_io_read". Das "S" als Pr臟ix kennzeichnet immer die serverseitige Implementierung eines RPCs. Im Folgenden werde ich meine Implementierung der Funktion fr /dev/one im Detail erl舫tern, denn diese verdeutlicht zahlreiche wichtige Konzepte.
error_t trivfs_S_io_read (struct trivfs_protid *cred, mach_port_t reply, mach_msg_type_name_t reply_type, vm_address_t *data, size_t *data_len, off_t offs, size_t amount)
Die Liste der Parameter ist offensichtlich recht lang. Allerdings kmmern uns "reply" und "reply_type" nicht im geringsten. Auf "cred" werden ich gleich noch eingehen. Fangen wir mal am Ende an: "amount" beschreibt die Menge der Bytes, die gelesen werden sollen. Ein ワbersetzer ist nicht verpflichtet, tats臘hlich so viele Daten zu liefern, wenn er so viele nicht anbieten kann. Der Parameter "offset" gibt das Offset innerhalb der Datei an, von dem aus gelesen werden soll. In unserem Falle ist dies ja offensichtlich nicht relevant. ワbrig bleiben "data_len" und "data", ber die einerseits der Benutzer einen Puffer zur Verfgung stellen kann (und uns dessen Gre mitteilen kann), andererseits liefern wir hierin auch die Daten und die Information ber die Menge der Daten zurck. Wir sind hierbei nicht verpflichtet, den vom Benutzer angebotenen Puffer zu verwenden.
{ /* Zugriff verweigern? */ if (!cred) return EOPNOTSUPP; else if (! (cred->po->openmodes & O_READ)) return EBADF;
Aus diesem Codestck sollte deutlich werden, wozu "cred" dient: Es gibt uns Informationen ber denjenigen, der eine Nachricht an uns gesendet hat. Besonders interessant ist das "po" Feld der Struktur, das "per-open" Informationen enth舁t. Nebenbei bemerkt besitzt die "peropen"-Struktur ein Feld namens "hook", jenes von einem ワbersetzer fr eigene Zwecke verwendet werden kann.
if (amount > 0) { int i; /* Evtl. neuen Puffer allozieren. */ if (*data_len < amount) *data = (vm_address_t) mmap (0, amount, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0);
In unserem Fall allozieren wir nur einen neuen Puffer, wenn der vom Benutzer angebotene nicht gro゚ genug ist. Dass wir dies mit "mmap" machen, mag berraschend sein, aber hat einen einfachen Grund: Wir mhten "page-aligned memory", also einen an Speicherseiten ausgerichteten Block haben, da dieser fr uns automatisch auf entsprechende Weise freigegeben wird. Es w舐e aufwendig, wenn wir uns merken mssten, welche Puffer wir alloziert haben um diese selbst freizugeben, da ein Puffer erst freigegeben werden kann, nachdem unsere Funktion bereits verlassen wurde.
/* Puffer mit Einsen fllen. */ for (i = 0; i < amount; i++) ((char *) *data)[i] = 1; }
Wir fllen nun noch den Puffer mit Einsen. Der Typecast ist nig, da "*data" vom Typ "vm_address_t" ist.
*data_len = amount; return 0; }
Zuletzt setzen wir noch die Gre des zurckgegebenen Puffers. Das war es bereits. Andere Funktionen werden auf vergleichbare Weise implementiert, und selbst wenn man direkt mit den betreffenden RPCs arbeitet statt mit trivfs, bleibt das Konzept das gleiche.
Das GNU-System n臧ert sich seiner Fertigstellung. Es berzeugt durch gute Konzepte mit guter Umsetzung. Es wird nach Entwicklern gesucht, welche die fehlenden Komponenten implementieren. Wer dem GNU-Projekt helfen mhte, die letzte fehlende Komponente des vollst舅digen GNU-Systems fertigzustellen, ist herzlichst dazu eingeladen. Aber auch fr Benutzer gibt es zahlreiche Aufgaben, die von diesen erledigt werden knen. Manche Programme mssen dokumentiert werden, zuknftigen Neulingen muss geholfen werden, vieles muss getestet werden usw.
Microsoft wirft der Gemeinschaft der Entwickler Freier Software vor, nicht innovativ zu sein. Mit Hurd ist das endgltig widerlegt.