vfs — controlul sistemului de fișiere virtual

Modulul vfs conține funcții pentru crearea obiectelor de sistem de fișiere și montarea/demontarea acestora în sistemul de fișiere virtual.

Montarea sistemelor de fișiere

Unele porturi oferă un sistem de fișiere virtual (VFS) și posibilitatea de a monta mai multe sisteme de fișiere „reale” în cadrul acestui VFS. Obiectele de sistem de fișiere pot fi montate fie la rădăcina VFS-ului, fie într-un subdirector aflat în rădăcină. Acest lucru permite configurarea dinamică și flexibilă a sistemului de fișiere văzut de programele Python. Porturile care dispun de această funcționalitate oferă funcțiile mount() și umount(), precum și, eventual, diverse implementări de sisteme de fișiere reprezentate prin clase VFS.

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

Montează obiectul de sistem de fișiere fsobj în locația din VFS indicată de șirul mount_point. fsobj poate fi un obiect VFS care are o metodă mount() sau un dispozitiv de tip bloc. Dacă este un dispozitiv de tip bloc, atunci tipul sistemului de fișiere este detectat automat (se generează o excepție dacă nu a fost recunoscut niciun sistem de fișiere). mount_point poate fi '/' pentru a monta fsobj la rădăcină sau '/<name>' pentru a-l monta într-un subdirector aflat sub rădăcină.

Dacă readonly este True, atunci sistemul de fișiere este montat în mod doar-citire.

În timpul procesului de montare se apelează metoda mount() pe obiectul de sistem de fișiere.

Va genera OSError(EPERM) dacă mount_point este deja montat.

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

Fără argumente pentru mount(), returnează o listă de tupluri reprezentând toate punctele de montare active.

Lista returnată are forma [(fsobj, mount_point), …].

vfs.umount(mount_point: str | Any) None

Demontează un sistem de fișiere. mount_point poate fi un șir care denumește locația de montare sau un obiect de sistem de fișiere montat anterior. În timpul procesului de demontare se apelează metoda umount() pe obiectul de sistem de fișiere.

Va genera OSError(EINVAL) dacă mount_point nu este găsit.

class vfs.VfsFat(block_dev: AbstractBlockDev)

Creează un obiect de sistem de fișiere care utilizează formatul de sistem de fișiere FAT. Stocarea sistemului de fișiere FAT este asigurată de block_dev. Obiectele create de acest constructor pot fi montate folosind mount().

static mkfs(block_dev: AbstractBlockDev) None

Construiește un sistem de fișiere FAT pe block_dev.

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

Creează un obiect de sistem de fișiere care utilizează formatul de sistem de fișiere doar-citire ROMFS. buffer trebuie să fie un obiect care acceptă protocolul buffer (bytes, bytearray sau memoryview) și care conține o imagine ROMFS validă.

Obiectele create de acest constructor pot fi montate folosind mount().

Consultați Lucrul cu ROMFS pentru toate detaliile, inclusiv modul de construire și implementare a imaginilor ROMFS cu mpremote.

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

Interfață de nivel jos pentru accesarea partiției (partițiilor) de memorie doar-citire (ROM) a dispozitivului. Operațiile acceptate sunt:

Apel

Comportament

rom_ioctl(1)

Returnează numărul de partiții ROM disponibile.

rom_ioctl(2, id)

Returnează partiția id ca un memoryview.

rom_ioctl(3, id, length)

Șterge primii length octeți ai partiției id în vederea scrierii. Returnează alinierea minimă de scriere în octeți.

rom_ioctl(4, id, offset, buf)

Scrie buf în partiția id la octetul offset.

rom_ioctl(5, id)

Finalizează o secvență de scriere în partiția id (golește memoriile cache etc.).

Aceste operații sunt în mod normal invocate indirect de mpremote la implementarea unei imagini ROMFS; majoritatea aplicațiilor nu trebuie să le apeleze direct.

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

Creează un obiect de sistem de fișiere care accesează sistemul de fișiere POSIX al gazdei. Dacă root este specificat, atunci ar trebui să fie o cale din sistemul de fișiere al gazdei care să fie folosită ca rădăcină a obiectului VfsPosix. În caz contrar, se utilizează directorul curent al sistemului de fișiere al gazdei.

Notă

VfsPosix este disponibil doar pe portul Unix al MicroPython; nu este prezent în firmware-ul OpenMV Cam.

Dispozitive de tip bloc

Un dispozitiv de tip bloc este un obiect care implementează protocolul de tip bloc. Acesta permite unui dispozitiv să accepte sisteme de fișiere MicroPython. Hardware-ul fizic este reprezentat de o clasă definită de utilizator. Clasa AbstractBlockDev este un șablon pentru proiectarea unei astfel de clase: MicroPython nu oferă efectiv acea clasă, însă o clasă reală de dispozitiv de tip bloc trebuie să implementeze metodele descrise mai jos.

O implementare concretă a acestei clase va permite de obicei accesul la funcționalitatea de tip memorie a unei componente hardware (precum memoria flash). Un dispozitiv de tip bloc poate fi formatat pentru orice sistem de fișiere acceptat și montat folosind metode os.

Consultați Lucrul cu sistemele de fișiere pentru exemple de implementări ale dispozitivelor de tip bloc folosind cele două variante ale protocolului de tip bloc descrise mai jos.

Interfața simplă și extinsă

Există două semnături compatibile pentru metodele readblocks și writeblocks (vezi mai jos), pentru a susține o varietate de cazuri de utilizare. Un anumit dispozitiv de tip bloc poate implementa una dintre forme sau pe cealaltă, ori ambele în același timp. A doua formă (cu parametrul offset) este denumită „interfața extinsă”.

Unele sisteme de fișiere necesită mai mult control asupra operațiilor de scriere – de exemplu, scrierea în regiuni sub-bloc fără ștergere – și au nevoie ca dispozitivul de tip bloc să accepte interfața extinsă.

class vfs.AbstractBlockDev

Șablon de documentație pentru protocolul dispozitivelor de tip bloc. MicroPython nu expune efectiv această clasă — ea este prezentată aici doar pentru a documenta metodele pe care trebuie să le implementeze o clasă de dispozitiv de tip bloc definită de utilizator. Argumentele constructorului depind în întregime de implementare (de obicei lucruri precum magistrala flash, pinul de selecție a cipului, dimensiunea sectorului etc.).

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

Citește octeți de pe dispozitiv în buf. Două supraîncărcări expun interfețele simplă și extinsă.

Forma simplă (readblocks(block_num, buf)): citește blocuri întregi începând de la indexul de bloc block_num. len(buf) trebuie să fie un multiplu al dimensiunii blocului, iar numărul de blocuri citite este len(buf) // block_size.

Forma extinsă (readblocks(block_num, buf, offset)): citește len(buf) octeți – nu neapărat un număr întreg de blocuri – începând de la octetul offset din interiorul blocului block_num. Folosiți această formă atunci când sistemul de fișiere are nevoie de acces de citire la nivel sub-bloc.

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

Scrie octeți din buf pe dispozitiv.

Forma simplă (writeblocks(block_num, buf)): scrie blocuri întregi începând de la indexul de bloc block_num. len(buf) trebuie să fie un multiplu al dimensiunii blocului, iar numărul de blocuri scrise este len(buf) // block_size. Implementarea este responsabilă de ștergerea în prealabil a fiecărui bloc de destinație, dacă hardware-ul subiacent o impune.

Forma extinsă (writeblocks(block_num, buf, offset)): scrie len(buf) octeți – nu neapărat un număr întreg de blocuri – începând de la octetul offset din interiorul blocului block_num. Pot fi modificați doar octeții care sunt scriși; apelantul este responsabil de a se asigura că blocurile afectate au fost șterse printr-un apel ioctl(6, block_num) anterior. Implementările acestei forme nu trebuie niciodată să șteargă implicit un bloc, chiar și atunci când offset este zero.

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

Controlează dispozitivul de tip bloc și interoghează parametrii acestuia. Operația care trebuie efectuată este dată de op, care este unul dintre următoarele numere întregi:

  • 1 – inițializează dispozitivul (arg nu este utilizat)

  • 2 – oprește dispozitivul (arg nu este utilizat)

  • 3 – sincronizează dispozitivul (arg nu este utilizat)

  • 4 – obține numărul de blocuri, ar trebui să returneze un număr întreg (arg nu este utilizat)

  • 5 – obține numărul de octeți dintr-un bloc, ar trebui să returneze un număr întreg sau None, caz în care se folosește valoarea implicită de 512 (arg nu este utilizat)

  • 6 – șterge un bloc, arg este numărul blocului care trebuie șters

Ca minim, ioctl(4, ...) trebuie interceptat; sistemele de fișiere care utilizează interfața extinsă necesită în plus ioctl(6, ...). Necesitatea celorlalte operații depinde de hardware.

Înaintea oricărui apel către writeblocks(block, ...), un sistem de fișiere care utilizează interfața extinsă emite ioctl(6, block) pentru ca driverul să poată șterge mai întâi blocul, dacă hardware-ul o impune. Un driver poate, în schimb, să intercepteze ioctl(6, block) și să returneze 0 (succes), asumându-și el însuși responsabilitatea de a detecta când este necesară ștergerea.

Cu excepția cazului în care se specifică altfel, ioctl(op, arg) poate returna None. În consecință, o implementare poate ignora valorile neutilizate ale lui op. Acolo unde op este interceptat, valoarea returnată pentru operațiile 4 și 5 este cea detaliată mai sus. Celelalte operații ar trebui să returneze 0 în caz de succes și o valoare diferită de zero în caz de eșec, valoarea returnată fiind un cod errno OSError.