vfs — besturing van het virtuele bestandssysteem

De module vfs bevat functies voor het maken van bestandssysteemobjecten en het aan- en afkoppelen ervan in het virtuele bestandssysteem.

Bestandssystemen aankoppelen

Sommige ports bieden een virtueel bestandssysteem (VFS) en de mogelijkheid om meerdere “echte” bestandssystemen binnen dit VFS aan te koppelen. Bestandssysteemobjecten kunnen ofwel in de root van het VFS worden aangekoppeld, ofwel in een submap die zich in de root bevindt. Hierdoor kan het bestandssysteem dat door Python-programma’s wordt gezien dynamisch en flexibel worden geconfigureerd. Ports die over deze functionaliteit beschikken, bieden de functies mount() en umount(), en mogelijk diverse bestandssysteemimplementaties die worden vertegenwoordigd door VFS-klassen.

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

Koppel het bestandssysteemobject fsobj aan op de locatie in het VFS die wordt aangegeven door de string mount_point. fsobj kan een VFS-object zijn dat een mount()-methode heeft, of een blokapparaat. Als het een blokapparaat is, wordt het type bestandssysteem automatisch gedetecteerd (er wordt een uitzondering opgeworpen als er geen bestandssysteem werd herkend). mount_point mag '/' zijn om fsobj in de root aan te koppelen, of '/<name>' om het in een submap onder de root aan te koppelen.

Als readonly gelijk is aan True, wordt het bestandssysteem alleen-lezen aangekoppeld.

Tijdens het aankoppelproces wordt de methode mount() aangeroepen op het bestandssysteemobject.

Werpt OSError(EPERM) op als mount_point al is aangekoppeld.

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

Zonder argumenten aan mount() wordt een lijst van tupels geretourneerd die alle actieve aankoppelpunten vertegenwoordigt.

De geretourneerde lijst heeft de vorm [(fsobj, mount_point), …].

vfs.umount(mount_point: str | Any) None

Koppel een bestandssysteem af. mount_point kan een string zijn die de aankoppellocatie benoemt, of een eerder aangekoppeld bestandssysteemobject. Tijdens het afkoppelproces wordt de methode umount() aangeroepen op het bestandssysteemobject.

Werpt OSError(EINVAL) op als mount_point niet wordt gevonden.

class vfs.VfsFat(block_dev: AbstractBlockDev)

Maak een bestandssysteemobject dat de FAT-bestandssysteemindeling gebruikt. De opslag van het FAT-bestandssysteem wordt geleverd door block_dev. Objecten die met deze constructor worden gemaakt, kunnen worden aangekoppeld met mount().

static mkfs(block_dev: AbstractBlockDev) None

Bouw een FAT-bestandssysteem op block_dev.

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

Maak een bestandssysteemobject dat de ROMFS alleen-lezen bestandssysteemindeling gebruikt. buffer moet een object zijn dat het bufferprotocol ondersteunt (bytes, bytearray of memoryview) en dat een geldige ROMFS-image bevat.

Objecten die met deze constructor worden gemaakt, kunnen worden aangekoppeld met mount().

Zie Werken met ROMFS voor alle details, inclusief hoe je ROMFS-images bouwt en implementeert met mpremote.

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

Low-level-interface voor toegang tot de alleen-lezen geheugenpartitie(s) (ROM) van het apparaat. De ondersteunde bewerkingen zijn:

Aanroep

Gedrag

rom_ioctl(1)

Retourneert het aantal beschikbare ROM-partities.

rom_ioctl(2, id)

Retourneert partitie id als een memoryview.

rom_ioctl(3, id, length)

Wist de eerste length bytes van partitie id ter voorbereiding op schrijven. Retourneert de minimale schrijfuitlijning in bytes.

rom_ioctl(4, id, offset, buf)

Schrijft buf naar partitie id op byte-offset.

rom_ioctl(5, id)

Rondt een schrijfreeks naar partitie id af (leegt caches enz.).

Deze bewerkingen worden normaal gesproken indirect aangeroepen door mpremote bij het implementeren van een ROMFS-image; de meeste applicaties hoeven ze niet rechtstreeks aan te roepen.

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

Maak een bestandssysteemobject dat toegang heeft tot het POSIX-bestandssysteem van de host. Als root is opgegeven, moet dit een pad in het hostbestandssysteem zijn dat als root van het VfsPosix-object wordt gebruikt. Anders wordt de huidige map van het hostbestandssysteem gebruikt.

Notitie

VfsPosix is alleen beschikbaar op de MicroPython Unix-port; het is niet aanwezig in de OpenMV Cam-firmware.

Blokapparaten

Een blokapparaat is een object dat het blokprotocol implementeert. Hierdoor kan een apparaat MicroPython-bestandssystemen ondersteunen. De fysieke hardware wordt vertegenwoordigd door een door de gebruiker gedefinieerde klasse. De klasse AbstractBlockDev is een sjabloon voor het ontwerp van zo’n klasse: MicroPython biedt deze klasse niet daadwerkelijk, maar een echte blokapparaatklasse moet de hieronder beschreven methoden implementeren.

Een concrete implementatie van deze klasse geeft doorgaans toegang tot de geheugenachtige functionaliteit van een stuk hardware (zoals flashgeheugen). Een blokapparaat kan worden geformatteerd naar elk ondersteund bestandssysteem en worden aangekoppeld met os-methoden.

Zie Werken met bestandssystemen voor voorbeeldimplementaties van blokapparaten die gebruikmaken van de twee hieronder beschreven varianten van het blokprotocol.

Eenvoudige en uitgebreide interface

Er zijn twee compatibele signaturen voor de methoden readblocks en writeblocks (zie hieronder), om een verscheidenheid aan toepassingen te ondersteunen. Een bepaald blokapparaat kan de ene of de andere vorm implementeren, of beide tegelijk. De tweede vorm (met de offset-parameter) wordt de “uitgebreide interface” genoemd.

Sommige bestandssystemen vereisen meer controle over schrijfbewerkingen – bijvoorbeeld het schrijven naar subblokgebieden zonder te wissen – en vereisen dat het blokapparaat de uitgebreide interface ondersteunt.

class vfs.AbstractBlockDev

Documentatiesjabloon voor het blokapparaatprotocol. MicroPython stelt deze klasse niet daadwerkelijk beschikbaar — ze wordt hier alleen getoond om de methoden te documenteren die een door de gebruiker gedefinieerde blokapparaatklasse moet implementeren. Constructorargumenten zijn volledig aan de implementatie (doorgaans zaken als flashbus, chip-select-pin, sectorgrootte enz.).

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

Lees bytes van het apparaat in buf. Twee overloads stellen de eenvoudige en uitgebreide interfaces beschikbaar.

Eenvoudige vorm (readblocks(block_num, buf)): leest hele blokken vanaf blokindex block_num. len(buf) moet een veelvoud zijn van de blokgrootte, en het aantal gelezen blokken is len(buf) // block_size.

Uitgebreide vorm (readblocks(block_num, buf, offset)): leest len(buf) bytes – niet noodzakelijk een geheel aantal blokken – vanaf byte-offset binnen blok block_num. Gebruik deze vorm wanneer het bestandssysteem leestoegang op subblokniveau nodig heeft.

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

Schrijf bytes van buf naar het apparaat.

Eenvoudige vorm (writeblocks(block_num, buf)): schrijft hele blokken vanaf blokindex block_num. len(buf) moet een veelvoud zijn van de blokgrootte, en het aantal geschreven blokken is len(buf) // block_size. De implementatie is verantwoordelijk voor het eerst wissen van elk doelblok als de onderliggende hardware dat vereist.

Uitgebreide vorm (writeblocks(block_num, buf, offset)): schrijft len(buf) bytes – niet noodzakelijk een geheel aantal blokken – vanaf byte-offset binnen blok block_num. Alleen de bytes die worden geschreven mogen veranderen; de aanroeper is verantwoordelijk om ervoor te zorgen dat de betrokken blokken zijn gewist via een voorafgaande aanroep ioctl(6, block_num). Implementaties van deze vorm mogen nooit impliciet een blok wissen, zelfs niet wanneer offset nul is.

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

Bestuur het blokapparaat en bevraag de parameters ervan. De uit te voeren bewerking wordt gegeven door op, dat een van de volgende gehele getallen is:

  • 1 – initialiseer het apparaat (arg wordt niet gebruikt)

  • 2 – sluit het apparaat af (arg wordt niet gebruikt)

  • 3 – synchroniseer het apparaat (arg wordt niet gebruikt)

  • 4 – haal een telling op van het aantal blokken, moet een geheel getal retourneren (arg wordt niet gebruikt)

  • 5 – haal het aantal bytes in een blok op, moet een geheel getal retourneren, of None waarin geval de standaardwaarde 512 wordt gebruikt (arg wordt niet gebruikt)

  • 6 – wis een blok, arg is het nummer van het te wissen blok

Ten minste ioctl(4, ...) moet worden onderschept; bestandssystemen die de uitgebreide interface gebruiken vereisen daarnaast ioctl(6, ...). De noodzaak van de andere bewerkingen is hardwareafhankelijk.

Voorafgaand aan elke aanroep van writeblocks(block, ...) geeft een bestandssysteem dat de uitgebreide interface gebruikt ioctl(6, block) uit, zodat de driver het blok eerst kan wissen als de hardware dat vereist. Een driver kan in plaats daarvan ioctl(6, block) onderscheppen en 0 (geslaagd) retourneren, waarbij hij zelf de verantwoordelijkheid op zich neemt om te detecteren wanneer wissen nodig is.

Tenzij anders vermeld kan ioctl(op, arg) None retourneren. Een implementatie kan bijgevolg ongebruikte waarden van op negeren. Waar op wordt onderschept, zijn de retourwaarden voor bewerkingen 4 en 5 zoals hierboven beschreven. Andere bewerkingen moeten 0 retourneren bij succes en niet-nul bij falen, waarbij de geretourneerde waarde een OSError-errno-code is.