vfs — controlo do sistema de ficheiros virtual

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

Montagem de sistemas de ficheiros

Algumas portas fornecem um Sistema de Ficheiros Virtual (VFS) e a capacidade de montar vários sistemas de ficheiros «reais» dentro deste VFS. Os objetos de sistema de ficheiros podem ser montados na raiz do VFS ou numa subdiretoria que existe na raiz. Isto permite uma configuração dinâmica e flexível do sistema de ficheiros que é visto pelos programas Python. As portas que têm esta funcionalidade fornecem as funções mount() e umount(), e possivelmente várias implementações de sistema de ficheiros representadas por classes VFS.

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

Monta o objeto de sistema de ficheiros fsobj na localização do VFS indicada pela cadeia de caracteres mount_point. fsobj pode ser um objeto VFS que tem um método mount(), ou um dispositivo de bloco. Se for um dispositivo de bloco, o tipo de sistema de ficheiros é detetado automaticamente (é lançada uma exceção se nenhum sistema de ficheiros for reconhecido). mount_point pode ser '/' para montar fsobj na raiz, ou '/<name>' para montá-lo numa subdiretoria sob a raiz.

Se readonly for True, o sistema de ficheiros é montado em modo de apenas leitura.

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

Lançará OSError(EPERM) se mount_point já estiver montado.

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

Sem argumentos para mount(), devolve uma lista de tuplos que representam todos os pontos de montagem ativos.

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

vfs.umount(mount_point: str | Any) None

Desmonta um sistema de ficheiros. mount_point pode ser uma cadeia de caracteres que indica a localização de montagem, ou um objeto de sistema de ficheiros previamente montado. Durante o processo de desmontagem, o método umount() é chamado no objeto de sistema de ficheiros.

Lançará OSError(EINVAL) se mount_point não for encontrado.

class vfs.VfsFat(block_dev: AbstractBlockDev)

Cria um objeto de sistema de ficheiros que utiliza o formato de sistema de ficheiros FAT. O armazenamento do sistema de ficheiros FAT é fornecido por block_dev. Os objetos criados por este construtor podem ser montados utilizando mount().

static mkfs(block_dev: AbstractBlockDev) None

Constrói um sistema de ficheiros FAT em block_dev.

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

Cria um objeto de sistema de ficheiros que utiliza o formato de sistema de ficheiros ROMFS somente de leitura. buffer deve ser um objeto que suporte o protocolo de buffer (bytes, bytearray ou memoryview) que contém uma imagem ROMFS válida.

Os objetos criados por este construtor podem ser montados utilizando mount().

Consulte Trabalhar com ROMFS para detalhes completos, incluindo como construir e implementar imagens ROMFS com mpremote.

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

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

Chamada

Comportamento

rom_ioctl(1)

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

rom_ioctl(2, id)

Devolve 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 escrita. Devolve 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.).

Estas operações são normalmente invocadas indiretamente por mpremote ao implementar uma imagem ROMFS; a maioria das aplicações não necessita de as chamar diretamente.

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

Cria um objeto de sistema de ficheiros que acede ao sistema de ficheiros POSIX do hospedeiro. Se root for especificado, deve ser um caminho no sistema de ficheiros do hospedeiro a usar como raiz do objeto VfsPosix. Caso contrário, é utilizado o diretório atual do sistema de ficheiros do hospedeiro.

Nota

VfsPosix está disponível apenas 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. Isto permite que um dispositivo suporte sistemas de ficheiros do MicroPython. O hardware físico é representado por uma classe definida pelo utilizador. A classe AbstractBlockDev é um modelo para a conceção de tal classe: o MicroPython não fornece essa classe, mas uma classe de dispositivo de bloco concreta deve implementar os métodos descritos abaixo.

Uma implementação concreta desta classe normalmente permitirá o acesso à funcionalidade semelhante à memória de um componente de hardware (como memória flash). Um dispositivo de bloco pode ser formatado para qualquer sistema de ficheiros suportado e montado utilizando os métodos do módulo os.

Consulte Trabalhar com sistemas de ficheiros para exemplos de implementações de dispositivos de bloco utilizando as duas variantes do protocolo de bloco descritas abaixo.

Interface simples e estendida

Existem duas assinaturas compatíveis para os métodos readblocks e writeblocks (ver abaixo), de forma 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) é referida como «interface estendida».

Alguns sistemas de ficheiros requerem mais controlo sobre as operações de escrita – por exemplo, escrita em regiões sub-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 realmente esta classe — é mostrada aqui apenas para documentar os métodos que uma classe de dispositivo de bloco definida pelo utilizador deve implementar. Os argumentos do construtor são inteiramente da responsabilidade da implementação (tipicamente coisas como barramento flash, pino de seleção de chip, 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 a partir do í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 – a partir do byte offset dentro do bloco block_num. Use esta forma quando o sistema de ficheiros necessitar de acesso de leitura sub-bloco.

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

Escreve bytes de buf para o dispositivo.

Forma simples (writeblocks(block_num, buf)): escreve blocos inteiros a partir do í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 cada bloco de destino primeiro se o hardware subjacente o exigir.

Forma estendida (writeblocks(block_num, buf, offset)): escreve len(buf) bytes – não necessariamente um número inteiro de blocos – a partir do byte offset dentro do bloco block_num. Apenas os bytes que estão a ser escritos podem ser alterados; o chamador é responsável por garantir que os blocos afetados foram apagados através de uma chamada prévia a ioctl(6, block_num). As implementações desta forma nunca devem apagar implicitamente um bloco, mesmo quando offset é zero.

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

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

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

  • 2 – encerra o dispositivo (arg não é utilizado)

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

  • 4 – obtém a contagem do número de blocos, deve devolver um inteiro (arg não é utilizado)

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

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

Como mínimo, ioctl(4, ...) deve ser intercetado; os sistemas de ficheiros que usam a interface estendida requerem adicionalmente ioctl(6, ...). A necessidade das outras operações depende do hardware.

Antes de qualquer chamada a writeblocks(block, ...), um sistema de ficheiros que utiliza a interface estendida emite ioctl(6, block) para que o controlador possa apagar o bloco primeiro se o hardware o exigir. Um controlador pode, em alternativa, intercetar ioctl(6, block) e devolver 0 (sucesso), assumindo a responsabilidade de detetar quando o apagamento é necessário.

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