vfs — 가상 파일시스템 제어

vfs 모듈은 파일시스템 객체를 생성하고 이를 가상 파일시스템에 마운트/언마운트하는 함수를 포함합니다.

파일시스템 마운트

일부 포트는 가상 파일시스템(VFS)과 이 VFS 안에 여러 개의 “실제” 파일시스템을 마운트할 수 있는 기능을 제공합니다. 파일시스템 객체는 VFS의 루트에 마운트하거나, 루트 아래에 위치한 하위 디렉터리에 마운트할 수 있습니다. 이를 통해 Python 프로그램이 보게 되는 파일시스템을 동적이고 유연하게 구성할 수 있습니다. 이 기능을 갖춘 포트는 mount()umount() 함수를 제공하며, 경우에 따라 VFS 클래스로 표현되는 다양한 파일시스템 구현을 제공할 수도 있습니다.

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

파일시스템 객체 fsobjmount_point 문자열로 지정한 VFS 내 위치에 마운트합니다. fsobjmount() 메서드를 가진 VFS 객체이거나 블록 디바이스일 수 있습니다. 블록 디바이스인 경우 파일시스템 유형이 자동으로 감지됩니다(인식되는 파일시스템이 없으면 예외가 발생합니다). mount_pointfsobj 를 루트에 마운트하려면 '/' 일 수 있고, 루트 아래의 하위 디렉터리에 마운트하려면 '/<name>' 일 수 있습니다.

readonlyTrue 이면 파일시스템이 읽기 전용으로 마운트됩니다.

마운트 과정에서 파일시스템 객체의 mount() 메서드가 호출됩니다.

mount_point 가 이미 마운트되어 있으면 OSError(EPERM) 이 발생합니다.

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

mount() 를 인자 없이 호출하면 모든 활성 마운트 지점을 나타내는 튜플의 리스트를 반환합니다.

반환되는 리스트는 [(fsobj, mount_point), …] 형식입니다.

vfs.umount(mount_point: str | Any) None

파일시스템을 언마운트합니다. mount_point 는 마운트 위치를 나타내는 문자열이거나, 이전에 마운트된 파일시스템 객체일 수 있습니다. 언마운트 과정에서 파일시스템 객체의 umount() 메서드가 호출됩니다.

mount_point 를 찾을 수 없으면 OSError(EINVAL) 이 발생합니다.

class vfs.VfsFat(block_dev: AbstractBlockDev)

FAT 파일시스템 포맷을 사용하는 파일시스템 객체를 생성합니다. FAT 파일시스템의 저장소는 block_dev 가 제공합니다. 이 생성자로 만든 객체는 mount() 를 사용하여 마운트할 수 있습니다.

static mkfs(block_dev: AbstractBlockDev) None

block_dev 에 FAT 파일시스템을 구축합니다.

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

ROMFS 읽기 전용 파일시스템 포맷 을 사용하는 파일시스템 객체를 생성합니다. buffer 는 유효한 ROMFS 이미지를 담고 있으면서 버퍼 프로토콜을 지원하는 객체(bytes, bytearray 또는 memoryview)여야 합니다.

이 생성자로 만든 객체는 mount() 를 사용하여 마운트할 수 있습니다.

mpremote 로 ROMFS 이미지를 구축하고 배포하는 방법을 포함한 전체 세부 사항은 ROMFS 사용하기 를 참조하세요.

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

디바이스의 읽기 전용 메모리(ROM) 파티션에 접근하기 위한 저수준 인터페이스입니다. 지원되는 연산은 다음과 같습니다:

호출

동작

rom_ioctl(1)

사용 가능한 ROM 파티션의 개수를 반환합니다.

rom_ioctl(2, id)

파티션 idmemoryview 로 반환합니다.

rom_ioctl(3, id, length)

쓰기를 준비하기 위해 파티션 id 의 처음 length 바이트를 지웁니다. 최소 쓰기 정렬 크기를 바이트 단위로 반환합니다.

rom_ioctl(4, id, offset, buf)

buf 를 파티션 id 의 바이트 offset 위치에 씁니다.

rom_ioctl(5, id)

파티션 id 에 대한 쓰기 시퀀스를 마무리합니다(캐시 플러시 등).

이 연산들은 일반적으로 ROMFS 이미지를 배포할 때 mpremote 에 의해 간접적으로 호출됩니다. 대부분의 애플리케이션은 이를 직접 호출할 필요가 없습니다.

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

호스트 POSIX 파일시스템에 접근하는 파일시스템 객체를 생성합니다. root 가 지정되면 VfsPosix 객체의 루트로 사용할 호스트 파일시스템의 경로여야 합니다. 그렇지 않으면 호스트 파일시스템의 현재 디렉터리가 사용됩니다.

참고

VfsPosix 는 MicroPython Unix 포트에서만 사용할 수 있으며, OpenMV Cam 펌웨어에는 포함되어 있지 않습니다.

블록 디바이스

블록 디바이스는 블록 프로토콜을 구현하는 객체입니다. 이를 통해 디바이스가 MicroPython 파일시스템을 지원할 수 있습니다. 물리적 하드웨어는 사용자 정의 클래스로 표현됩니다. AbstractBlockDev 클래스는 그러한 클래스를 설계하기 위한 템플릿입니다. MicroPython이 실제로 이 클래스를 제공하지는 않지만, 실제 블록 디바이스 클래스는 아래에 설명된 메서드를 구현해야 합니다.

이 클래스의 구체적인 구현은 일반적으로 하드웨어(예: 플래시 메모리)의 메모리 유사 기능에 대한 접근을 허용합니다. 블록 디바이스는 지원되는 임의의 파일시스템으로 포맷할 수 있으며 os 메서드를 사용하여 마운트할 수 있습니다.

아래에 설명된 두 가지 블록 프로토콜 변형을 사용하는 블록 디바이스 구현 예제는 파일시스템 다루기 을 참조하세요.

단순 인터페이스와 확장 인터페이스

다양한 사용 사례를 지원하기 위해 readblockswriteblocks 메서드에는 두 가지 호환 시그니처가 있습니다(아래 참조). 특정 블록 디바이스는 둘 중 하나를 구현하거나 둘 다 동시에 구현할 수 있습니다. 두 번째 형태(offset 매개변수가 있는 형태)를 “확장 인터페이스”라고 합니다.

일부 파일시스템은 쓰기 연산에 대한 더 많은 제어가 필요합니다. 예를 들어 지우지 않고 하위 블록 영역에 쓰는 경우 등이며, 이때 블록 디바이스가 확장 인터페이스를 지원해야 합니다.

class vfs.AbstractBlockDev

블록 디바이스 프로토콜을 위한 문서화 템플릿입니다. MicroPython은 실제로 이 클래스를 노출하지 않으며, 사용자 정의 블록 디바이스 클래스가 구현해야 하는 메서드를 문서화하기 위해서만 여기에 표시됩니다. 생성자 인자는 전적으로 구현에 달려 있습니다(일반적으로 플래시 버스, 칩 셀렉트 핀, 섹터 크기 등).

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

디바이스에서 buf 로 바이트를 읽습니다. 두 가지 오버로드가 단순 및 확장 인터페이스를 노출합니다.

단순 형식 (readblocks(block_num, buf)): 블록 인덱스 block_num 부터 시작하여 전체 블록을 읽습니다. len(buf) 는 블록 크기의 배수여야 하며, 읽는 블록 수는 len(buf) // block_size 입니다.

확장 형식 (readblocks(block_num, buf, offset)): 블록 block_num 내의 바이트 offset 부터 시작하여 len(buf) 바이트를 읽습니다. 반드시 전체 블록 단위일 필요는 없습니다. 파일 시스템이 서브 블록 단위의 읽기 접근이 필요할 때 이 형식을 사용하세요.

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

buf 의 바이트를 디바이스에 씁니다.

단순 형식 (writeblocks(block_num, buf)): 블록 인덱스 block_num 부터 시작하여 전체 블록을 씁니다. len(buf) 는 블록 크기의 배수여야 하며, 쓰는 블록 수는 len(buf) // block_size 입니다. 기반 하드웨어에서 필요로 하는 경우 각 대상 블록을 먼저 지우는 것은 구현체의 책임입니다.

확장 형식 (writeblocks(block_num, buf, offset)): 블록 block_num 내의 바이트 offset 부터 시작하여 len(buf) 바이트를 씁니다. 반드시 전체 블록 단위일 필요는 없습니다. 기록되는 바이트만 변경될 수 있으며, 영향을 받는 블록이 사전에 ioctl(6, block_num) 호출을 통해 지워졌는지 확인하는 것은 호출자의 책임입니다. 이 형식의 구현체는 offset 이 0인 경우에도 절대로 블록을 암묵적으로 지워서는 안 됩니다.

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

블록 디바이스를 제어하고 매개변수를 조회합니다. 수행할 연산은 op 로 지정되며, 다음 정수 중 하나입니다:

  • 1 – 디바이스를 초기화합니다(arg 는 사용되지 않음)

  • 2 – 디바이스를 종료합니다(arg 는 사용되지 않음)

  • 3 – 디바이스를 동기화합니다(arg 는 사용되지 않음)

  • 4 – 블록 수를 가져오며, 정수를 반환해야 합니다(arg 는 사용되지 않음)

  • 5 – 블록의 바이트 수를 가져오며, 정수를 반환하거나 None 을 반환해야 하고 후자의 경우 기본값 512가 사용됩니다(arg 는 사용되지 않음)

  • 6 – 블록을 지우며, arg 는 지울 블록 번호입니다

최소한 ioctl(4, ...) 는 처리되어야 합니다. 확장 인터페이스를 사용하는 파일시스템은 추가로 ioctl(6, ...) 를 필요로 합니다. 다른 연산의 필요 여부는 하드웨어에 따라 다릅니다.

확장 인터페이스를 사용하는 파일시스템은 writeblocks(block, ...) 를 호출하기 전에 ioctl(6, block) 을 발행하여, 하드웨어가 요구하는 경우 드라이버가 먼저 블록을 지울 수 있도록 합니다. 드라이버는 대신 ioctl(6, block) 을 가로채 0(성공)을 반환하면서, 지우기가 필요한 시점을 스스로 감지하는 책임을 맡을 수도 있습니다.

별도로 명시되지 않는 한 ioctl(op, arg)None 을 반환할 수 있습니다. 따라서 구현은 사용하지 않는 op 값을 무시할 수 있습니다. op 가 처리되는 경우, 연산 4와 5의 반환값은 위에서 설명한 대로입니다. 다른 연산은 성공 시 0을, 실패 시 0이 아닌 값을 반환해야 하며, 반환되는 값은 OSError errno 코드입니다.