Das Verzeichnis fs

Die Dateiverwaltung ist einer der zentralen Bestandteile eines jeden Unix-Systems, und das Verzeichnis fs ist das wohlgefüllteste aller Verzeichnisse. Es enthält alle von der aktuellen Linux-Version unterstützten Dateisysteme (jeweils in einem eigenen Unterverzeichnis) sowie die wichtigsten Systemaufrufe nach fork und exit.

Der Systemaufruf execve befindet sich in exec.c und benutzt die diversen verfügbaren Binärformate, um die in den ausführbaren Dateien vorgefundenen binären Daten zu interpretieren. Das wichtigste Binärformat ist heutzutage ELF, das in binfmt_elf.c implementiert wird. binfmt_script.c unterstützt die Ausführung interpretierter Dateien. Nachdem festgestellt wurde, daß ein Interpreter benötigt wird (üblicherweise durch die #!-Zeile, auch “shebang” genannt), benutzt die Datei die anderen Binärformate, um den Interpreter zu laden.

Diverse Binärformate (wie das ausführbare Format von Java) können durch den Benutzer mittels einer in binfmt_misc.c definierten /proc-Schnittstelle definiert werden. Das misc-Binärformat ist in der Lage, ein interpretiertes Binärformat auf der Basis des Inhalts der ausführbaren Datei zu identifizieren und den passenden Interpreter mit den passenden Argumenten zu starten. Dies wird in /proc/sys/fs/binfmt_misc konfiguriert.

Die grundlegenden Systemaufrufe für den Datenzugriff sind in open.c und in read_write.c definiert. definiert auch close und einige andere Systemaufrufe für den Dateizugriff (zum Beispiel chown). select.c implementiert select und poll. Die Dateien pipe.c und fifo.c implementieren Pipes und benannte Pipes. readdir.c implementiert den Systemaufruf getdents, mit dem User-Space-Programme Verzeichnisse lesen (der Name steht für “get directory entries”). Andere Programmierschnittstellen für den Zugriff auf Verzeichnisdaten (wie etwa die readdir-Schnittstelle) sind alle als Bibliotheksfunktionen im User-Space definiert und verwenden den Systemaufruf getdents.

Die meisten Systemaufrufe zum Herumbewegen von Dateien wie etwa mkdir, rmdir, rename, link, symlink und mknod sind in der Datei namei.c implementiert, die wiederum auf dem Verzeichniseintrag-Cache aufbaut, der in dcache.c implementiert ist.

Das Ein- und Aushängen von Dateisystemen wie auch die Unterstützung von temporären Wurzelverzeichnissen für initrd werden in super.c implementiert.

Für Gerätetreiber ist devices.c besonders interessant, wo die Register für Zeichen- und Block-Treiber registriert werden und alle Geräte angesteuert werden. Dies geschieht durch das Implementieren der generischen open-Methode, die verwendet wird, bevor die gerätespezifische file_operations-Struktur geholt und verwendet wird. read und write für Block-Geräte sind in block_dev.c implementiert, was wiederum alle Arbeiten rund um die Puffer-Verwaltung an buffer.c delegiert.

Es gibt in diesem Verzeichnis noch mehrere andere Dateien, die aber weniger interessant sind. Die wichtigsten sind inode.c und file.c, die die interne Organisation von Datenstrukturen für Dateien und Inodes erledigen, dann die Datei ioctl.c, die ioctl implementiert, sowie dquot.c, die Quoten implementiert.

Wie wir bereits erwähnt haben, enthalten die meisten Unterverzeichnisse von fs die Implementationen der einzelnen Dateisysteme. fs/partitions ist allerdings kein Dateisystemtyp, sondern vielmehr ein Container für den Code zur Partitionsverwaltung. Manche Dateien in diesem Verzeichnis werden unabhängig von der Kernel-Konfiguration immer kompiliert, andere dagegen, die die Unterstützung spezieller Partitionierungsschemata implementieren, können individuell ein- oder ausgeschaltet werden.