Wie implementiere ich einen Dateisystemtreiber in Linux? [geschlossen]

14

Angenommen, ich habe ein neues Dateisystem erfunden und möchte jetzt einen Dateisystemtreiber dafür erstellen.

Wie würde ich diesen Dateisystemtreiber implementieren? Wird dies mit einem Kernelmodul durchgeführt?

Und wie kann der Dateisystemtreiber auf die Festplatte zugreifen? Sollte der Dateisystemtreiber Code für den Zugriff auf die Festplatte enthalten oder enthält Linux einen Gerätetreiber für den Zugriff auf die Festplatte, die von allen Dateisystemtreibern verwendet wird?

user343344
quelle

Antworten:

24

Ja, Dateisysteme in Linux können als Kernelmodule implementiert werden. Es gibt aber auch die FUSE-Schnittstelle (Filesystem in USErspace), über die ein regulärer User-Space-Prozess als Dateisystemtreiber fungieren kann. Wenn Sie ein neues Dateisystem als Prototyp erstellen, kann die Implementierung zunächst über die FUSE-Schnittstelle das Testen und Entwickeln vereinfachen. Sobald Sie die Interna des Dateisystems in FUSE-Form ausgearbeitet haben, können Sie mit der Implementierung einer leistungsoptimierten Kernelmodul-Version davon beginnen.

Im Folgenden finden Sie einige grundlegende Informationen zur Implementierung eines Dateisystems im Kernel-Space. Es ist ziemlich alt (ab 1996!), Aber das sollte Ihnen zumindest eine Grundidee für die Art von Dingen geben, die Sie tun müssen.

Wenn Sie sich für die FUSE-Route entscheiden, finden Sie hier libfuse, die Referenzimplementierung der Userspace-Seite der FUSE-Oberfläche.

Dateisystemtreiber als Kernelmodul

Grundsätzlich muss die Initialisierungsfunktion Ihres Dateisystemtreibermoduls nur eine register_filesystem()Funktion aufrufen und ihr als Parameter eine Struktur geben, die einen Funktionszeiger enthält, der die Funktion in Ihrem Dateisystemtreiber identifiziert, die als erster Schritt zur Identifizierung Ihres Dateisystems verwendet wird Tippen und montieren. In diesem Stadium passiert nichts mehr.

Wenn ein Dateisystem gemountet wird und entweder der Dateisystemtyp passend zu Ihrem Treiber angegeben wird oder die automatische Erkennung des Dateisystemtyps durchgeführt wird, ruft die Kernel-Ebene für das virtuelle Dateisystem (kurz VFS) diese Funktion auf. Grundsätzlich heißt es: "Hier ist ein Zeiger auf eine Darstellung eines Standard-Linux-Blockgeräts auf Kernel-Ebene. Sehen Sie sich das an, prüfen Sie, ob Sie damit umgehen können, und sagen Sie mir dann, was Sie damit tun können."

Zu diesem Zeitpunkt muss Ihr Treiber alle erforderlichen Informationen lesen, um sicherzustellen, dass es sich um den richtigen Treiber für das Dateisystem handelt, und dann eine Struktur zurückgeben, die Zeiger auf weitere Funktionen enthält, die Ihr Treiber mit diesem bestimmten Dateisystem ausführen kann. Wenn der Dateisystemtreiber die Daten auf der Festplatte nicht erkennt, soll er ein entsprechendes Fehlerergebnis zurückgeben. Anschließend meldet VFS dem Userspace entweder einen Fehler oder fragt - wenn die automatische Erkennung des Dateisystemtyps durchgeführt wird - ein anderes Dateisystem Fahrer zu versuchen.

Die anderen Treiber im Kernel stellen die Standardschnittstelle für Blockgeräte bereit, sodass der Dateisystemtreiber keine Hardwareunterstützung implementieren muss. Grundsätzlich kann der Dateisystemtreiber Plattenblöcke mit Standardfunktionen auf Kernel-Ebene mit dem ihm zugewiesenen Gerätezeiger lesen und schreiben.

Die VFS-Ebene erwartet, dass der Dateisystemtreiber der VFS-Ebene eine Reihe von Standardfunktionen zur Verfügung stellt. Einige davon sind obligatorisch, damit die VFS-Ebene mit dem Dateisystem etwas Sinnvolles tun kann. Andere sind optional, und Sie können anstelle eines Zeigers auf eine solche optionale Funktion einfach einen NULL-Wert zurückgeben.

telcoM
quelle
1
Dies ist eine ziemlich gute Antwort, aber um die Frage vollständig zu beantworten, müssen Sie auch ein wenig über die Funktionalität sagen, die die Block-Device-Schicht für die Dateisystemschicht bereitstellt, auf der sie aufbauen kann.
Kasperd
Ich habe das irgendwie mit dem Bit "Hier ist ein Zeiger auf ein Standardblockgerät" angedeutet, aber das ist ein guter Punkt. Darauf habe ich näher eingegangen.
TelcoM
Diese Antwort, insbesondere die Beschreibung dessen, was in welcher Reihenfolge geschieht, ist göttlich. Gibt es eine Art Buch / Website, die ich lesen könnte und die Beschreibungen für all "wie Linux funktioniert" hat?
Adam Barnes
Möglicherweise interessieren Sie sich für Linux Kernel Internals oder Linux Device Drivers, 3rd Edition . Und natürlich besteht die Möglichkeit, den eigentlichen Quellcode zu lesen.
TelcoM
0

Ja, dies wird normalerweise mit einem Kerneltreiber durchgeführt, der entweder als Kernelmodul geladen oder in den Kernel kompiliert werden kann.

Sie können ähnliche Dateisystemtreiber und deren Funktionsweise hier nachlesen .

Diese Treiber verwenden wahrscheinlich interne Kernelfunktionen, um auf Speichergeräte als Byteblöcke zuzugreifen. Sie können jedoch auch Blockgeräte verwenden, die von Treibern in den Ordnern für Blockgeräte und Zeichengeräte verfügbar gemacht werden .

Erik
quelle
0

Sie können fuse verwenden, um ein User-Land-Dateisystem zu erstellen oder ein Kernelmodul zu schreiben. Es ist einfacher, mit Fuse zu arbeiten, da Sie eine Auswahl an Sprachen haben und den Kernel (und damit das gesamte System) nicht zum Absturz bringen.

Kernelmodule können schneller sein, aber die erste Regel für die Optimierung lautet: Tun Sie dies erst, wenn Sie den Arbeitscode getestet haben. Das zweite ist wie es: Tun Sie es nicht, bis Sie Beweise dafür haben, dass es zu langsam ist. Und die dritte: Behalten Sie es nicht bei, es sei denn, Sie haben Beweise dafür, dass es schneller / kleiner wird.

Und ja, der Kernel hat bereits Treiber für die Hardware, Sie implementieren sie nicht erneut.

Strg-Alt-Delor
quelle
FUSE hat neben der Leistung auch große Nachteile: Es ist schwierig, es für Ihr Root-Dateisystem zu verwenden. (Möglicherweise mit einer initrd, aber die FUSE-Binärdatei konnte nach dem Booten nicht freigegeben werden, da sie immer noch von der Ramdisk ausgeführt wird.)
Peter Cordes
1
@PeterCordes Es konnte nicht freigegeben werden , aber das bedeutet nicht, dass es nicht getrennt werden kann. Wenn noch ein Verweis darauf vorhanden ist, wird er im Speicher behalten, unabhängig davon, ob Sie die initramfs verlassen und die zugrunde liegende Binärdatei gelöscht haben.
Wald
@forest: Richtig, daher können Sie die initrd danach nicht mehr aushängen pivot_root, da in den initramfs noch ausgelastete Inodes vorhanden sind.
Peter Cordes
Ein normales, /initvon einem initramfs gestartetes /initProgramm wird (glaube ich) nach pivot_root ausgeführt, um die Kontrolle auf die realen Root-FSs zu übertragen /init. Eine FUSE-Binärdatei konnte sich jedoch nicht durch execve ersetzen, wenn der Zugriff auf den Root-FS davon abhing, dass der FUSE-Prozess auf den Kernel reagiert. Nun, vielleicht, indem Sie zuerst den Pagecache initialisieren, aber das klingt nicht zuverlässig.
Peter Cordes