vfs — controle do sistema de arquivos virtual

O módulo vfs contém funções para criar objetos de sistema de arquivos e montá-los/desmontá-los no Sistema de Arquivos Virtual.

Montagem de sistemas de arquivos

Algumas portas fornecem um Sistema de Arquivos Virtual (VFS) e a capacidade de montar múltiplos sistemas de arquivos “reais” dentro desse VFS. Objetos de sistema de arquivos podem ser montados na raiz do VFS ou em um subdiretório que reside na raiz. Isso permite uma configuração dinâmica e flexível do sistema de arquivos visto pelos programas Python. Portas que possuem essa funcionalidade fornecem as funções mount() e umount() e, possivelmente, várias implementações de sistema de arquivos representadas por classes VFS.

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

Monta o objeto de sistema de arquivos fsobj no local do VFS indicado pela string mount_point. fsobj pode ser um objeto VFS que possua um método mount() ou um dispositivo de bloco. Se for um dispositivo de bloco, o tipo de sistema de arquivos é detectado automaticamente (uma exceção é levantada se nenhum sistema de arquivos for reconhecido). mount_point pode ser '/' para montar fsobj na raiz ou '/<name>' para montá-lo em um subdiretório sob a raiz.

Se readonly for True, o sistema de arquivos é montado como somente leitura.

Durante o processo de montagem, o método mount() é chamado no objeto de sistema de arquivos.

Levanta OSError(EPERM) se mount_point já estiver montado.

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

Sem argumentos para mount(), retorna uma lista de tuplas representando todos os pontos de montagem ativos.

A lista retornada tem a forma [(fsobj, mount_point), …].

vfs.umount(mount_point: str | Any) None

Desmonta um sistema de arquivos. mount_point pode ser uma string indicando o local de montagem ou um objeto de sistema de arquivos previamente montado. Durante o processo de desmontagem, o método umount() é chamado no objeto de sistema de arquivos.

Levanta OSError(EINVAL) se mount_point não for encontrado.

class vfs.VfsFat(block_dev: AbstractBlockDev)

Cria um objeto de sistema de arquivos que usa o formato de sistema de arquivos FAT. O armazenamento do sistema de arquivos FAT é fornecido por block_dev. Objetos criados por este construtor podem ser montados usando mount().

static mkfs(block_dev: AbstractBlockDev) None

Constrói um sistema de arquivos FAT em block_dev.

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

Cria um objeto de sistema de arquivos que usa o formato de sistema de arquivos somente leitura ROMFS. buffer deve ser um objeto que suporte o protocolo de buffer (bytes, bytearray ou memoryview) e que contenha uma imagem ROMFS válida.

Objetos criados por este construtor podem ser montados usando mount().

Consulte Trabalhando com ROMFS para todos os detalhes, incluindo como construir e implantar imagens ROMFS com mpremote.

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

Interface de baixo nível para acessar a(s) partição(ões) de memória somente leitura (ROM) do dispositivo. As operações suportadas são:

Chamada

Comportamento

rom_ioctl(1)

Retorna o número de partições ROM disponíveis.

rom_ioctl(2, id)

Retorna a partição id como um memoryview.

rom_ioctl(3, id, length)

Apaga os primeiros length bytes da partição id em preparação para a escrita. Retorna o alinhamento mínimo de escrita em bytes.

rom_ioctl(4, id, offset, buf)

Escreve buf na partição id no byte offset.

rom_ioctl(5, id)

Finaliza uma sequência de escrita na partição id (descarrega caches, etc.).

Essas operações normalmente são invocadas indiretamente pelo mpremote ao implantar uma imagem ROMFS; a maioria das aplicações não precisa chamá-las diretamente.

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

Cria um objeto de sistema de arquivos que acessa o sistema de arquivos POSIX do host. Se root for especificado, deve ser um caminho no sistema de arquivos do host a ser usado como a raiz do objeto VfsPosix. Caso contrário, o diretório atual do sistema de arquivos do host é usado.

Nota

VfsPosix está disponível somente na porta Unix do MicroPython; não está presente no firmware da OpenMV Cam.

Dispositivos de bloco

Um dispositivo de bloco é um objeto que implementa o protocolo de bloco. Isso permite que um dispositivo suporte sistemas de arquivos do MicroPython. O hardware físico é representado por uma classe definida pelo usuário. A classe AbstractBlockDev é um modelo para o projeto de tal classe: o MicroPython não fornece de fato essa classe, mas uma classe de dispositivo de bloco real deve implementar os métodos descritos abaixo.

Uma implementação concreta dessa classe normalmente permite o acesso à funcionalidade do tipo memória de um componente de hardware (como memória flash). Um dispositivo de bloco pode ser formatado em qualquer sistema de arquivos suportado e montado usando métodos do os.

Consulte Trabalhando com sistemas de arquivos para exemplos de implementações de dispositivos de bloco usando as duas variantes do protocolo de bloco descritas abaixo.

Interface simples e estendida

Há duas assinaturas compatíveis para os métodos readblocks e writeblocks (veja abaixo), de modo a suportar uma variedade de casos de uso. Um dado dispositivo de bloco pode implementar uma forma ou a outra, ou ambas ao mesmo tempo. A segunda forma (com o parâmetro offset) é chamada de “interface estendida”.

Alguns sistemas de arquivos exigem mais controle sobre as operações de escrita – por exemplo, escrever em sub-regiões de um bloco sem apagar – e precisam que o dispositivo de bloco suporte a interface estendida.

class vfs.AbstractBlockDev

Modelo de documentação para o protocolo de dispositivo de bloco. O MicroPython não expõe de fato esta classe — ela é mostrada aqui apenas para documentar os métodos que uma classe de dispositivo de bloco definida pelo usuário deve implementar. Os argumentos do construtor ficam inteiramente a cargo da implementação (tipicamente coisas como barramento da flash, pino de chip-select, tamanho do setor, etc.).

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

Lê bytes do dispositivo para buf. Duas sobrecargas expõem as interfaces simples e estendida.

Forma simples (readblocks(block_num, buf)): lê blocos inteiros começando no índice de bloco block_num. len(buf) deve ser um múltiplo do tamanho do bloco, e o número de blocos lidos é len(buf) // block_size.

Forma estendida (readblocks(block_num, buf, offset)): lê len(buf) bytes – não necessariamente um número inteiro de blocos – começando no byte offset dentro do bloco block_num. Use esta forma quando o sistema de arquivos precisar de acesso de leitura em sub-blocos.

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

Escreve bytes de buf no dispositivo.

Forma simples (writeblocks(block_num, buf)): escreve blocos inteiros começando no índice de bloco block_num. len(buf) deve ser um múltiplo do tamanho do bloco, e o número de blocos escritos é len(buf) // block_size. A implementação é responsável por apagar primeiro cada bloco de destino, caso o hardware subjacente exija.

Forma estendida (writeblocks(block_num, buf, offset)): escreve len(buf) bytes – não necessariamente um número inteiro de blocos – começando no byte offset dentro do bloco block_num. Somente os bytes que estão sendo escritos podem ser alterados; o chamador é responsável por garantir que os blocos afetados tenham sido apagados por meio de uma chamada prévia a ioctl(6, block_num). Implementações desta forma nunca devem apagar implicitamente um bloco, mesmo quando offset for zero.

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

Controla o dispositivo de bloco e consulta seus parâmetros. A operação a ser realizada é dada por op, que é um dos seguintes inteiros:

  • 1 – inicializa o dispositivo (arg não é usado)

  • 2 – desliga o dispositivo (arg não é usado)

  • 3 – sincroniza o dispositivo (arg não é usado)

  • 4 – obtém uma contagem do número de blocos, deve retornar um inteiro (arg não é usado)

  • 5 – obtém o número de bytes em um bloco, deve retornar um inteiro, ou None caso em que o valor padrão de 512 é usado (arg não é usado)

  • 6 – apaga um bloco, arg é o número do bloco a apagar

No mínimo, ioctl(4, ...) deve ser interceptado; sistemas de arquivos que usam a interface estendida exigem adicionalmente ioctl(6, ...). A necessidade das outras operações depende do hardware.

Antes de qualquer chamada a writeblocks(block, ...), um sistema de arquivos que usa a interface estendida emite ioctl(6, block) para que o driver possa apagar o bloco primeiro, caso o hardware exija. Um driver pode, em vez disso, interceptar ioctl(6, block) e retornar 0 (sucesso), assumindo a responsabilidade de detectar por conta própria quando o apagamento é necessário.

Salvo indicação em contrário, ioctl(op, arg) pode retornar None. Consequentemente, uma implementação pode ignorar valores não utilizados de op. Quando op é interceptado, os valores de retorno para as operações 4 e 5 são os detalhados acima. Outras operações devem retornar 0 em caso de sucesso e um valor diferente de zero em caso de falha, sendo o valor retornado um código errno de OSError.