vfs — Steuerung des virtuellen Dateisystems

Das Modul vfs enthält Funktionen zum Erstellen von Dateisystemobjekten sowie zum Ein- und Aushängen dieser im virtuellen Dateisystem.

Einhängen von Dateisystemen

Einige Ports stellen ein virtuelles Dateisystem (VFS) bereit sowie die Möglichkeit, mehrere „echte“ Dateisysteme innerhalb dieses VFS einzuhängen. Dateisystemobjekte können entweder im Wurzelverzeichnis des VFS oder in einem darunterliegenden Unterverzeichnis eingehängt werden. Dies ermöglicht eine dynamische und flexible Konfiguration des Dateisystems, das von Python-Programmen gesehen wird. Ports mit dieser Funktionalität stellen die Funktionen mount() und umount() bereit sowie gegebenenfalls verschiedene Dateisystemimplementierungen, die durch VFS-Klassen dargestellt werden.

vfs.mount(fsobj: Any, mount_point: str, *, readonly: bool = False) None

Hängt das Dateisystemobjekt fsobj an der durch die Zeichenkette mount_point angegebenen Stelle im VFS ein. fsobj kann ein VFS-Objekt mit einer mount()-Methode oder ein Blockgerät sein. Handelt es sich um ein Blockgerät, wird der Dateisystemtyp automatisch erkannt (wird kein Dateisystem erkannt, wird eine Ausnahme ausgelöst). mount_point kann '/' sein, um fsobj im Wurzelverzeichnis einzuhängen, oder '/<name>', um es in einem Unterverzeichnis unterhalb des Wurzelverzeichnisses einzuhängen.

Ist readonly gleich True, wird das Dateisystem schreibgeschützt eingehängt.

Während des Einhängevorgangs wird die Methode mount() für das Dateisystemobjekt aufgerufen.

Löst OSError(EPERM) aus, wenn mount_point bereits eingehängt ist.

vfs.mount() List[Tuple[Any, str]]

Wird mount() ohne Argumente aufgerufen, gibt es eine Liste von Tupeln zurück, die alle aktiven Einhängepunkte darstellen.

Die zurückgegebene Liste hat die Form [(fsobj, mount_point), …].

vfs.umount(mount_point: str | Any) None

Hängt ein Dateisystem aus. mount_point kann eine Zeichenkette sein, die die Einhängestelle benennt, oder ein zuvor eingehängtes Dateisystemobjekt. Während des Aushängevorgangs wird die Methode umount() für das Dateisystemobjekt aufgerufen.

Löst OSError(EINVAL) aus, wenn mount_point nicht gefunden wird.

class vfs.VfsFat(block_dev: AbstractBlockDev)

Erstellt ein Dateisystemobjekt, das das FAT-Dateisystemformat verwendet. Der Speicher des FAT-Dateisystems wird durch block_dev bereitgestellt. Mit diesem Konstruktor erstellte Objekte können mit mount() eingehängt werden.

static mkfs(block_dev: AbstractBlockDev) None

Erstellt ein FAT-Dateisystem auf block_dev.

class vfs.VfsRom(buffer: bytes | bytearray | memoryview)

Erstellt ein Dateisystemobjekt, das das schreibgeschützte ROMFS-Dateisystemformat verwendet. buffer muss ein Objekt sein, das das Pufferprotokoll unterstützt (bytes, bytearray oder memoryview) und ein gültiges ROMFS-Image enthält.

Mit diesem Konstruktor erstellte Objekte können mit mount() eingehängt werden.

Vollständige Einzelheiten, einschließlich der Erstellung und Bereitstellung von ROMFS-Images mit mpremote, finden Sie unter Arbeiten mit ROMFS.

vfs.rom_ioctl(op: int, *args: Any) Any

Low-Level-Schnittstelle für den Zugriff auf die schreibgeschützte(n) Speicherpartition(en) (ROM) des Geräts. Die unterstützten Operationen sind:

Aufruf

Verhalten

rom_ioctl(1)

Gibt die Anzahl der verfügbaren ROM-Partitionen zurück.

rom_ioctl(2, id)

Gibt die Partition id als memoryview zurück.

rom_ioctl(3, id, length)

Löscht die ersten length Bytes der Partition id zur Vorbereitung des Schreibvorgangs. Gibt die minimale Schreibausrichtung in Bytes zurück.

rom_ioctl(4, id, offset, buf)

Schreibt buf an Byte-offset in die Partition id.

rom_ioctl(5, id)

Schließt eine Schreibsequenz für die Partition id ab (leert Caches usw.).

Diese Operationen werden normalerweise indirekt von mpremote beim Bereitstellen eines ROMFS-Images aufgerufen; die meisten Anwendungen müssen sie nicht direkt aufrufen.

class vfs.VfsPosix(root: str | None = None)

Erstellt ein Dateisystemobjekt, das auf das POSIX-Dateisystem des Hosts zugreift. Wird root angegeben, sollte es ein Pfad im Host-Dateisystem sein, der als Wurzelverzeichnis des VfsPosix-Objekts verwendet wird. Andernfalls wird das aktuelle Verzeichnis des Host-Dateisystems verwendet.

Bemerkung

VfsPosix ist nur im MicroPython-Unix-Port verfügbar; in der OpenMV-Cam-Firmware ist es nicht vorhanden.

Blockgeräte

Ein Blockgerät ist ein Objekt, das das Blockprotokoll implementiert. Dadurch kann ein Gerät MicroPython-Dateisysteme unterstützen. Die physische Hardware wird durch eine benutzerdefinierte Klasse dargestellt. Die Klasse AbstractBlockDev ist eine Vorlage für den Entwurf einer solchen Klasse: MicroPython stellt diese Klasse nicht tatsächlich bereit, aber eine konkrete Blockgeräteklasse muss die unten beschriebenen Methoden implementieren.

Eine konkrete Implementierung dieser Klasse ermöglicht in der Regel den Zugriff auf die speicherähnliche Funktionalität einer Hardware (etwa Flash-Speicher). Ein Blockgerät kann auf jedes unterstützte Dateisystem formatiert und mit os-Methoden eingehängt werden.

Beispielimplementierungen von Blockgeräten unter Verwendung der beiden unten beschriebenen Varianten des Blockprotokolls finden Sie unter Arbeiten mit Dateisystemen.

Einfache und erweiterte Schnittstelle

Es gibt zwei kompatible Signaturen für die Methoden readblocks und writeblocks (siehe unten), um eine Vielzahl von Anwendungsfällen zu unterstützen. Ein bestimmtes Blockgerät kann die eine oder die andere Form oder beide gleichzeitig implementieren. Die zweite Form (mit dem offset-Parameter) wird als „erweiterte Schnittstelle“ bezeichnet.

Einige Dateisysteme benötigen mehr Kontrolle über Schreiboperationen – zum Beispiel das Schreiben in Teilblockbereiche ohne Löschen – und erfordern, dass das Blockgerät die erweiterte Schnittstelle unterstützt.

class vfs.AbstractBlockDev

Dokumentationsvorlage für das Blockgeräteprotokoll. MicroPython stellt diese Klasse nicht tatsächlich bereit — sie wird hier nur gezeigt, um die Methoden zu dokumentieren, die eine benutzerdefinierte Blockgeräteklasse implementieren muss. Die Konstruktorargumente liegen vollständig in der Verantwortung der Implementierung (typischerweise Dinge wie Flash-Bus, Chip-Select-Pin, Sektorgröße usw.).

readblocks(block_num: int, buf: bytearray) None
readblocks(block_num: int, buf: bytearray, offset: int) None

Liest Bytes vom Gerät in buf. Zwei Überladungen stellen die einfache und die erweiterte Schnittstelle bereit.

Einfache Form (readblocks(block_num, buf)): liest ganze Blöcke ab dem Blockindex block_num. len(buf) muss ein Vielfaches der Blockgröße sein, und die Anzahl der gelesenen Blöcke beträgt len(buf) // block_size.

Erweiterte Form (readblocks(block_num, buf, offset)): liest len(buf) Bytes – nicht notwendigerweise eine ganze Anzahl von Blöcken – ab Byte-offset innerhalb des Blocks block_num. Verwenden Sie diese Form, wenn das Dateisystem Lesezugriff auf Teilblöcke benötigt.

writeblocks(block_num: int, buf: bytes) None
writeblocks(block_num: int, buf: bytes, offset: int) None

Schreibt Bytes aus buf auf das Gerät.

Einfache Form (writeblocks(block_num, buf)): schreibt ganze Blöcke ab dem Blockindex block_num. len(buf) muss ein Vielfaches der Blockgröße sein, und die Anzahl der geschriebenen Blöcke beträgt len(buf) // block_size. Die Implementierung ist dafür verantwortlich, jeden Zielblock zuvor zu löschen, falls die zugrunde liegende Hardware dies erfordert.

Erweiterte Form (writeblocks(block_num, buf, offset)): schreibt len(buf) Bytes – nicht notwendigerweise eine ganze Anzahl von Blöcken – ab Byte-offset innerhalb des Blocks block_num. Nur die geschriebenen Bytes dürfen sich ändern; der Aufrufer ist dafür verantwortlich, dass die betroffenen Blöcke zuvor durch einen vorangehenden Aufruf von ioctl(6, block_num) gelöscht wurden. Implementierungen dieser Form dürfen niemals implizit einen Block löschen, auch dann nicht, wenn offset gleich null ist.

ioctl(op: int, arg: int) int | None

Steuert das Blockgerät und fragt dessen Parameter ab. Die auszuführende Operation wird durch op angegeben, das eine der folgenden Ganzzahlen ist:

  • 1 – Gerät initialisieren (arg wird nicht verwendet)

  • 2 – Gerät herunterfahren (arg wird nicht verwendet)

  • 3 – Gerät synchronisieren (arg wird nicht verwendet)

  • 4 – Anzahl der Blöcke ermitteln, sollte eine Ganzzahl zurückgeben (arg wird nicht verwendet)

  • 5 – Anzahl der Bytes in einem Block ermitteln, sollte eine Ganzzahl oder None zurückgeben, in welchem Fall der Standardwert 512 verwendet wird (arg wird nicht verwendet)

  • 6 – einen Block löschen, arg ist die Nummer des zu löschenden Blocks

Mindestens ioctl(4, ...) muss abgefangen werden; Dateisysteme, die die erweiterte Schnittstelle verwenden, benötigen zusätzlich ioctl(6, ...). Ob die übrigen Operationen benötigt werden, hängt von der Hardware ab.

Vor jedem Aufruf von writeblocks(block, ...) setzt ein Dateisystem, das die erweiterte Schnittstelle verwendet, ioctl(6, block) ab, damit der Treiber den Block zuvor löschen kann, falls die Hardware dies erfordert. Ein Treiber kann stattdessen ioctl(6, block) abfangen und 0 (Erfolg) zurückgeben und dabei selbst die Verantwortung dafür übernehmen, zu erkennen, wann ein Löschen erforderlich ist.

Sofern nicht anders angegeben, kann ioctl(op, arg) None zurückgeben. Folglich kann eine Implementierung nicht verwendete Werte von op ignorieren. Wird op abgefangen, sind die Rückgabewerte für die Operationen 4 und 5 wie oben beschrieben. Andere Operationen sollten bei Erfolg 0 und bei Fehlern einen Wert ungleich null zurückgeben, wobei der zurückgegebene Wert ein OSError-errno-Code ist.