Hallo zusammen, wir teilen mit Ihnen den zweiten Teil der Veröffentlichung "Virtuelle Dateisysteme in Linux: Warum sie benötigt werden und wie sie funktionieren?" Den ersten Teil können Sie lesen . Wir erinnern daran, dass diese Serie von Veröffentlichungen im Rahmen der Einführung eines neuen Kurses , der schon bald beginnt.
Wie man VFS mit eBPF- und bcc-Tools überwacht
Der einfachste Weg zu verstehen, wie der Kernel mit Dateien umgeht sysfs – besteht darin, dies praktisch zu beobachten, und der einfachste Weg, auf ARM64 zu beobachten, besteht darin, eBPF zu verwenden. eBPF (Abkürzung für Berkeley Packet Filter) besteht aus einer virtuellen Maschine, die im , auf die privilegierte Benutzer über die Kommandozeile zugreifen können (query). Der Kernel-Quellcode informiert den Leser darüber, was der Kernel tun kann; die Ausführung von eBPF-Tools in einem ausgelasteten System zeigt, was der Kernel tatsächlich tut.

Glücklicherweise ist es relativ einfach, eBPF mithilfe von Tools zu verwenden, , die als Pakete aus der allgemeinen Distribution verfügbar sind und detailliert dokumentiert sind Die Werkzeuge bcc – das sind Python-Skripte mit kurzen C-Code-Einfügungen, was bedeutet, dass jeder, der mit beiden Sprachen vertraut ist, sie problemlos anpassen kann. In bcc/tools gibt es 80 Python-Skripte, was bedeutet, dass wahrscheinlich ein Entwickler oder Systemadministrator etwas Passendes zur Lösung seiner Aufgaben finden kann.
Um zumindest einen groben Überblick darüber zu bekommen, welche Aufgaben VFS in einem laufenden System erfüllt, versuchen Sie es bitte mit vfscount oder vfsstat. Dies zeigt zum Beispiel, dass Dutzende von Aufrufen vfs_open() und dessen „Verwandten“ buchstäblich jede Sekunde auftreten.

vfsstat.py– ist ein Python-Skript mit C-Code-Einfügungen, das einfach die Aufrufe der VFS-Funktionen zählt.
Lassen Sie uns ein triviales Beispiel anführen und sehen, was passiert, wenn wir einen USB-Stick in den Computer stecken und das System ihn erkennt.

Mit eBPF kann man sehen, was passiert in
/sys, wenn ein USB-Stick eingesteckt wird. Hier wird ein einfaches und ein komplexes Beispiel gezeigt.
Im oben gezeigten Beispiel bcc Tool gibt eine Nachricht aus, wenn der Befehl sysfs_create_files()ausgeführt wird. Wir sehen, dass sysfs_create_files() es mit Hilfe von kworker gestartet wurde. Im Kontext der Reaktion auf das Einstecken eines USB-Sticks, welche Datei wurde dabei erstellt? Das zweite Beispiel veranschaulicht die gesamte Leistungsfähigkeit von eBPF. Hier trace.py zeigt die Kernel-Backtrace (Option -K) und den Namen der Datei, die erstellt wurde. sysfs_create_files()Das Einfügen in einfache Aussagen ist ein C-Code, der eine leicht erkennbare Formatzeichenfolge beinhaltet, bereitgestellt durch ein Python-Skript, das LLVM ausführt. Just-in-Time-Compiler. Diese Zeichenfolge wird kompiliert und in einer virtuellen Maschine innerhalb des Kernels ausgeführt. Die vollständige Funktionssignatur sysfs_create_files() muss im zweiten Befehl reproduziert werden, damit die Formatzeichenfolge auf einen der Parameter verweisen kann. Fehler in diesem C-Code-Segment führen zu erkennbaren C-Compilerfehlern. Wenn beispielsweise der Parameter -l fehlt, sehen Sie die Meldung "Failed to compile BPF text." Entwickler, die gut mit C und Python vertraut sind, finden die Tools bcc einfach zu erweitern und zu ändern.
Wenn der USB-Stick eingesteckt ist, zeigt die Kernel-Backtrace, dass PID 7711 der Prozess ist kworker gestartet wurde., der die Datei erstellt hat "events" in sysfs. Entsprechend zeigt der Aufruf von sysfs_remove_files() dass das Entfernen des Speichermediums zur Löschung der Datei events, was der allgemeinen Konzept der Linkzählung entspricht. Dabei zeigt die Ansicht sysfs_create_link () , dass eBPF während des Einsteckens eines USB-Sticks nicht weniger als 48 symbolische Links erstellt.
Was ist also der Sinn der Datei events? Die Verwendung von zum Suchen von , zeigt, dass es disk_add_events (), entweder "media_change", oder "eject_request" in die Ereignisdatei geschrieben werden können. Hier informiert die Blockschicht des Kernels den Userspace über das Erscheinen und Entfernen des „Disks“. Beachten Sie, wie informativ diese Forschungsmethode am Beispiel des Einsteckens eines USB-Sticks im Vergleich zu dem Versuch, herauszufinden, wie alles nur aus dem Quellcode funktioniert.
Nur-Lese-Wurzel-Dateisysteme ermöglichen eingebaute Geräte.
Natürlich schaltet niemand seinen Server oder Computer einfach aus, indem er den Stecker zieht. Aber warum? Das liegt daran, dass die gemounteten Dateisysteme auf physischen Speichermedien verzögerte Schreibvorgänge haben können und die Datenstrukturen, die ihren Zustand festhalten, möglicherweise nicht mit den Aufzeichnungen im Speicher synchronisiert sind. Wenn dies geschieht, müssen die Systembesitzer auf den nächsten Boot warten, um das Tool fsck filesystem-recovery auszuführen und im schlimmsten Fall Daten zu verlieren.
Dennoch wissen wir alle, dass viele IoT-Geräte sowie Router, Thermostate und Autos mittlerweile mit Linux betrieben werden. Viele dieser Geräte haben praktisch keine Benutzeroberfläche, und es gibt keinen Weg, sie "sauber" herunterzufahren. Stellen Sie sich vor, Sie starten ein Auto mit einer leeren Batterie, während die Stromversorgung der Steuereinheit ständig schwankt. Wie kann das System starten, ohne einen langen fsckauszuführen, wenn der Motor schließlich anspringt? Die Antwort ist einfach. Eingebettete Geräte verlassen sich auf das Wurzel-Dateisystem (abgekürzt ro-rootfs (read-only root filesystem)).
ro-rootfs bieten viele Vorteile, die weniger offensichtlich sind als die Unveränderlichkeit. Ein Vorteil besteht darin, dass Malware nicht in schreiben kann, wenn kein Linux-Prozess dazu in der Lage ist. /usr oder /libEin weiterer Vorteil ist, dass ein weitgehend unveränderliches Dateisystem entscheidend für die Unterstützung von Remote-Geräten ist, da das Support-Personal lokale Systeme nutzt, die nominell identisch mit den Systemen vor Ort sind. Möglicherweise ist der wichtigste (aber auch hinterhältigste) Vorteil, dass ro-rootfs Entwickler zwingt, zu entscheiden, welche Systemobjekte unveränderlich sein werden, bereits in der Planungsphase des Systems. Der Umgang mit ro-rootfs kann unangenehm und schmerzhaft sein, ähnlich wie es oft mit const-Variablen in Programmiersprachen der Fall ist, aber ihre Vorteile rechtfertigen leicht die zusätzlichen Kosten.
Erstellung rootfs im Nur-Lesen-Modus erfordert einige zusätzliche Anstrengungen von Entwicklern eingebetteter Systeme, und hier kommt das VFS ins Spiel. Linux erfordert, dass Dateien in /var waren für die Konfiguration verfügbar, und zusätzlich werden viele beliebte Anwendungen, die auf eingebetteten Systemen laufen, versuchen, Konfigurationsdateien zu erstellen. dot-files in $HOME. Eine der Lösungen für Konfigurationsdateien im Home-Verzeichnis besteht normalerweise darin, diese im Voraus zu generieren und zu bündeln. rootfs. Für /var eine mögliche Vorgehensweise besteht darin, es in einem separaten, beschreibbaren Bereich zu mounten, während das System selbst / nur im Lesemodus gemountet wird. Eine andere beliebte Alternative ist die Verwendung von bind- oder overlay-mounts.
Bind- und overlay-mounts, deren Einsatz durch Container
Die Ausführung des Befehls man mount ist der beste Weg, um mehr über bind- und overlay-mounts zu erfahren, die Entwicklern und Systemadministratoren die Möglichkeit geben, ein Dateisystem unter einem Pfad zu erstellen und es dann Anwendungen unter einem anderen zur Verfügung zu stellen. Für eingebettete Systeme bedeutet dies, Dateien in /var auf einem nur lesbaren Flash-Laufwerk zu speichern, jedoch lässt sich ein gebundener oder überlagerter Mount für den Pfad aus tmpfs in /var Beim Laden ermöglicht es den Anwendungen, dort Notizen (scrawl) zu hinterlassen. Beim nächsten Einschalten gehen die Änderungen verloren. /var Das Overlay-Mounting schafft eine Verbindung zwischen tmpfs und dem darunter liegenden Dateisystem und erlaubt, scheinbare Änderungen an bestehenden Dateien in ro-tootf während ein bind-Mount neue leere tmpfs Verzeichnisse sichtbar machen kann, die als beschreibbar in ro-rootfs Pfaden auftreten. Während overlayfs der richtige (proper) Typ eines Dateisystems ist, ist das bind-Mount im .
Basierend auf der Beschreibung von Overlay- und Bind-Mounting ist es nicht überraschend, dass sie aktiv verwenden. Lassen Sie uns beobachten, was passiert, wenn wir um einen Container zu starten, wobei wir das Tool mountsnoop ab bcc.
Aufruf system-nspawn startet den Container während des Betriebs mountsnoop.py.
Schauen wir uns an, was passiert ist:
Start mountsnoop Während des "Ladens" des Containers zeigt es, dass die Laufzeitumgebung des Containers stark vom Bind-Mount abhängig ist (nur der Anfang einer umfangreichen Ausgabe wird angezeigt).
Hier systemd-nspawn stellt ausgewählte Dateien aus procfs und sysfs dem Host im Container als Pfade in dessen rootfs. Neben MS_BIND Flags, die eine bindende Montage festlegen, sowie einige andere Flags im montierten System definieren die Beziehung zwischen Änderungen im Namespace des Hosts und des Containers. Beispielsweise kann eine bindende Montage Änderungen entweder in den Container durchlassen oder sie je nach Aufruf verbergen. /proc und /sys Im Container können Änderungen entweder durchgelassen oder verborgen werden, abhängig von dem Aufruf.
Fazit
Das Verständnis der internen Funktionsweise von Linux kann wie eine unüberwindbare Aufgabe erscheinen, da der Kernel selbst eine riesige Menge an Code enthält, ganz zu schweigen von den Anwendungen im Benutzerspeicher und den Systemaufruf-Interfaces in C-Bibliotheken wie glibc.Eine Möglichkeit, Fortschritte zu erzielen, besteht darin, den Quellcode eines bestimmten Kernelsubsystems mit dem Fokus auf das Verständnis der Systemaufrufe und der Header, die an den Benutzerspeicher gerichtet sind, sowie grundlegender interner Schnittstellen des Kernels zu lesen, zum Beispiel die Tabelle. file_operationsDateioperationen folgen dem Prinzip „Alles ist eine Datei“, daher ist der Umgang mit ihnen besonders angenehm. Die Quellcodes des Kernels in C befinden sich im obersten Verzeichnis. fs/ stellen eine Implementierung von virtuellen Dateisystemen dar, die eine Schicht bereitstellen, die eine breite und relativ einfache Kompatibilität mit populären Dateisystemen und Speichergeräten gewährleistet. Das Einbinden durch Binding und Overlay über die Namensräume von Linux ist die Magie von VFS, die die Erstellung von Containern und schreibgeschützten Root-Dateisystemen ermöglicht. In Kombination mit der Analyse des Quellcodes, dem eBPF-Kernel-Tool und seiner Schnittstelle. bcc
macht die Untersuchung des Kernels einfacher als je zuvor.
Freunde, teilen Sie uns mit, ob dieser Artikel für Sie hilfreich war. Vielleicht haben Sie Kommentare oder Anmerkungen? Und diejenigen, die am Kurs „Linux-Administrator“ interessiert sind, laden wir ein zu , der am 18. April stattfindet.
Quelle: habr.com
