vfs — sterowanie wirtualnym systemem plików

Moduł vfs zawiera funkcje do tworzenia obiektów systemu plików oraz montowania i odmontowywania ich w wirtualnym systemie plików.

Montowanie systemu plików

Niektóre porty udostępniają wirtualny system plików (VFS) oraz możliwość montowania w nim wielu „rzeczywistych” systemów plików. Obiekty systemu plików można zamontować zarówno w katalogu głównym VFS, jak i w podkatalogu znajdującym się w katalogu głównym. Pozwala to na dynamiczną i elastyczną konfigurację systemu plików widzianego przez programy w Pythonie. Porty oferujące tę funkcjonalność udostępniają funkcje mount() i umount(), a także ewentualnie różne implementacje systemów plików reprezentowane przez klasy VFS.

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

Montuje obiekt systemu plików fsobj w lokalizacji w VFS określonej przez łańcuch mount_point. fsobj może być obiektem VFS posiadającym metodę mount() lub urządzeniem blokowym. Jeśli jest to urządzenie blokowe, typ systemu plików jest wykrywany automatycznie (jeśli nie rozpoznano żadnego systemu plików, zgłaszany jest wyjątek). mount_point może mieć wartość '/', aby zamontować fsobj w katalogu głównym, lub '/<name>', aby zamontować go w podkatalogu katalogu głównego.

Jeśli readonly ma wartość True, system plików jest montowany tylko do odczytu.

Podczas procesu montowania na obiekcie systemu plików wywoływana jest metoda mount().

Zgłosi OSError(EPERM), jeśli mount_point jest już zamontowany.

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

Wywołanie mount() bez argumentów zwraca listę krotek reprezentujących wszystkie aktywne punkty montowania.

Zwracana lista ma postać [(fsobj, mount_point), …].

vfs.umount(mount_point: str | Any) None

Odmontowuje system plików. mount_point może być łańcuchem nazywającym lokalizację montowania lub wcześniej zamontowanym obiektem systemu plików. Podczas procesu odmontowywania na obiekcie systemu plików wywoływana jest metoda umount().

Zgłosi OSError(EINVAL), jeśli mount_point nie zostanie znaleziony.

class vfs.VfsFat(block_dev: AbstractBlockDev)

Tworzy obiekt systemu plików, który używa formatu systemu plików FAT. Przechowywanie systemu plików FAT zapewnia block_dev. Obiekty utworzone za pomocą tego konstruktora można zamontować przy użyciu mount().

static mkfs(block_dev: AbstractBlockDev) None

Tworzy system plików FAT na block_dev.

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

Tworzy obiekt systemu plików, który używa formatu systemu plików tylko do odczytu ROMFS. buffer musi być obiektem obsługującym protokół bufora (bytes, bytearray lub memoryview) zawierającym prawidłowy obraz ROMFS.

Obiekty utworzone za pomocą tego konstruktora można zamontować przy użyciu mount().

Zobacz Praca z ROMFS, aby uzyskać pełne szczegóły, w tym informacje o tym, jak budować i wdrażać obrazy ROMFS za pomocą mpremote.

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

Niskopoziomowy interfejs dostępu do partycji pamięci tylko do odczytu (ROM) urządzenia. Obsługiwane operacje to:

Wywołanie

Zachowanie

rom_ioctl(1)

Zwraca liczbę dostępnych partycji ROM.

rom_ioctl(2, id)

Zwraca partycję id jako memoryview.

rom_ioctl(3, id, length)

Wymazuje pierwsze length bajtów partycji id w ramach przygotowania do zapisu. Zwraca minimalne wyrównanie zapisu w bajtach.

rom_ioctl(4, id, offset, buf)

Zapisuje buf do partycji id pod bajtem offset.

rom_ioctl(5, id)

Finalizuje sekwencję zapisu do partycji id (opróżnia pamięci podręczne itp.).

Operacje te są zwykle wywoływane pośrednio przez mpremote podczas wdrażania obrazu ROMFS; większość aplikacji nie musi wywoływać ich bezpośrednio.

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

Tworzy obiekt systemu plików, który uzyskuje dostęp do systemu plików POSIX hosta. Jeśli określono root, powinna to być ścieżka w systemie plików hosta używana jako katalog główny obiektu VfsPosix. W przeciwnym razie używany jest bieżący katalog systemu plików hosta.

Informacja

VfsPosix jest dostępny tylko na porcie MicroPython dla systemu Unix; nie występuje w oprogramowaniu układowym OpenMV Cam.

Urządzenia blokowe

Urządzenie blokowe to obiekt implementujący protokół blokowy. Umożliwia to urządzeniu obsługę systemów plików MicroPython. Fizyczny sprzęt jest reprezentowany przez klasę zdefiniowaną przez użytkownika. Klasa AbstractBlockDev jest szablonem do projektowania takiej klasy: MicroPython w rzeczywistości nie udostępnia tej klasy, ale rzeczywista klasa urządzenia blokowego musi implementować opisane poniżej metody.

Konkretna implementacja tej klasy zwykle umożliwia dostęp do funkcjonalności podobnej do pamięci danego elementu sprzętu (jak pamięć flash). Urządzenie blokowe można sformatować do dowolnego obsługiwanego systemu plików i zamontować przy użyciu metod os.

Zobacz Praca z systemami plików, aby zapoznać się z przykładowymi implementacjami urządzeń blokowych wykorzystującymi dwa warianty protokołu blokowego opisane poniżej.

Interfejs prosty i rozszerzony

Istnieją dwie zgodne sygnatury metod readblocks i writeblocks (zobacz poniżej), aby obsłużyć różnorodne przypadki użycia. Dane urządzenie blokowe może implementować jedną lub drugą formę albo obie jednocześnie. Druga forma (z parametrem offset) jest określana jako „interfejs rozszerzony”.

Niektóre systemy plików wymagają większej kontroli nad operacjami zapisu – na przykład zapisu do obszarów podblokowych bez wymazywania – i wymagają, aby urządzenie blokowe obsługiwało interfejs rozszerzony.

class vfs.AbstractBlockDev

Szablon dokumentacji protokołu urządzenia blokowego. MicroPython w rzeczywistości nie udostępnia tej klasy — jest ona tutaj pokazana wyłącznie w celu udokumentowania metod, które musi implementować zdefiniowana przez użytkownika klasa urządzenia blokowego. Argumenty konstruktora zależą całkowicie od implementacji (zazwyczaj rzeczy takie jak magistrala flash, pin chip-select, rozmiar sektora itp.).

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

Odczytuje bajty z urządzenia do buf. Dwa przeciążenia udostępniają interfejs prosty i rozszerzony.

Forma prosta (readblocks(block_num, buf)): odczytuje całe bloki począwszy od indeksu bloku block_num. len(buf) musi być wielokrotnością rozmiaru bloku, a liczba odczytanych bloków wynosi len(buf) // block_size.

Forma rozszerzona (readblocks(block_num, buf, offset)): odczytuje len(buf) bajtów – niekoniecznie całą liczbę bloków – począwszy od bajtu offset w bloku block_num. Użyj tej formy, gdy system plików potrzebuje dostępu do odczytu na poziomie podbloku.

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

Zapisuje bajty z buf na urządzenie.

Forma prosta (writeblocks(block_num, buf)): zapisuje całe bloki począwszy od indeksu bloku block_num. len(buf) musi być wielokrotnością rozmiaru bloku, a liczba zapisanych bloków wynosi len(buf) // block_size. Implementacja jest odpowiedzialna za wcześniejsze wymazanie każdego bloku docelowego, jeśli wymaga tego sprzęt bazowy.

Forma rozszerzona (writeblocks(block_num, buf, offset)): zapisuje len(buf) bajtów – niekoniecznie całą liczbę bloków – począwszy od bajtu offset w bloku block_num. Zmienić mogą się tylko zapisywane bajty; wywołujący jest odpowiedzialny za zapewnienie, że objęte zapisem bloki zostały wymazane za pomocą wcześniejszego wywołania ioctl(6, block_num). Implementacje tej formy nigdy nie mogą niejawnie wymazywać bloku, nawet gdy offset wynosi zero.

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

Steruje urządzeniem blokowym i odpytuje jego parametry. Operacja do wykonania jest określona przez op, który jest jedną z następujących liczb całkowitych:

  • 1 – inicjalizacja urządzenia (arg nie jest używany)

  • 2 – wyłączenie urządzenia (arg nie jest używany)

  • 3 – synchronizacja urządzenia (arg nie jest używany)

  • 4 – pobranie liczby bloków, powinno zwrócić liczbę całkowitą (arg nie jest używany)

  • 5 – pobranie liczby bajtów w bloku, powinno zwrócić liczbę całkowitą lub None, w którym to przypadku używana jest wartość domyślna 512 (arg nie jest używany)

  • 6 – wymazanie bloku, arg to numer bloku do wymazania

Co najmniej ioctl(4, ...) musi być przechwytywane; systemy plików wykorzystujące interfejs rozszerzony dodatkowo wymagają ioctl(6, ...). Potrzeba pozostałych operacji zależy od sprzętu.

Przed każdym wywołaniem writeblocks(block, ...) system plików wykorzystujący interfejs rozszerzony wydaje ioctl(6, block), aby sterownik mógł najpierw wymazać blok, jeśli wymaga tego sprzęt. Sterownik może zamiast tego przechwycić ioctl(6, block) i zwrócić 0 (sukces), przejmując na siebie odpowiedzialność za samodzielne wykrywanie, kiedy wymazanie jest potrzebne.

Jeśli nie zaznaczono inaczej, ioctl(op, arg) może zwrócić None. W konsekwencji implementacja może ignorować nieużywane wartości op. Gdy op jest przechwytywane, wartości zwracane dla operacji 4 i 5 są takie, jak opisano powyżej. Pozostałe operacje powinny zwracać 0 w przypadku sukcesu i wartość niezerową w przypadku niepowodzenia, przy czym zwracana wartość to kod errno OSError.