vfs --- 仮想ファイルシステム制御

vfs モジュールには、ファイルシステムオブジェクトを作成し、それらを仮想ファイルシステムにマウント/アンマウントするための関数が含まれています。

ファイルシステムのマウント

一部のポートでは、仮想ファイルシステム(VFS)と、その VFS 内に複数の「実際の」ファイルシステムをマウントする機能が提供されています。ファイルシステムオブジェクトは、VFS のルート、またはルート直下のサブディレクトリのいずれかにマウントできます。これにより、Python プログラムから見えるファイルシステムを動的かつ柔軟に構成できます。この機能を持つポートでは、mount() 関数と umount() 関数、さらに VFS クラスとして表されるさまざまなファイルシステム実装が提供されることがあります。

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

ファイルシステムオブジェクト fsobj を、mount_point 文字列で指定された VFS 内の場所にマウントします。fsobj には、mount() メソッドを持つ VFS オブジェクト、またはブロックデバイスを指定できます。ブロックデバイスを指定した場合、ファイルシステムの種類は自動的に検出されます(ファイルシステムが認識されなかった場合は例外が発生します)。mount_point には、fsobj をルートにマウントするための '/' や、ルート直下のサブディレクトリにマウントするための '/<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 イメージを含む、バッファプロトコルをサポートするオブジェクト(bytesbytearray、または memoryview)を指定する必要があります。

このコンストラクタで作成したオブジェクトは mount() を使用してマウントできます。

ROMFS イメージを mpremote でビルドおよびデプロイする方法など、詳細については 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 メソッドを使用してマウントできます。

以下で説明する 2 種類のブロックプロトコルを用いたブロックデバイスの実装例については、ファイルシステムの利用 を参照してください。

シンプルインターフェースと拡張インターフェース

さまざまなユースケースをサポートするため、readblocks メソッドと writeblocks メソッド(後述)には互換性のある 2 つのシグネチャがあります。特定のブロックデバイスは、いずれか一方の形式、または両方を同時に実装できます。2 番目の形式(offset パラメータを持つもの)は「拡張インターフェース」と呼ばれます。

一部のファイルシステムは、書き込み操作に対してより細かい制御を必要とします。たとえば、消去せずにサブブロック領域へ書き込む場合などで、ブロックデバイスが拡張インターフェースをサポートしている必要があります。

class vfs.AbstractBlockDev

ブロックデバイスプロトコル用のドキュメント用テンプレートです。MicroPython は実際にはこのクラスを公開していません。ここでは、ユーザー定義のブロックデバイスクラスが実装する必要があるメソッドを説明するためにのみ示しています。コンストラクタの引数は完全に実装側に委ねられています(通常はフラッシュバス、チップセレクトピン、セクタサイズなど)。

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

デバイスから buf にバイトを読み込みます。2 つのオーバーロードが シンプルおよび拡張 インターフェースを公開します。

シンプル形式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 がゼロの場合であっても、ブロックを暗黙的に消去しては いけません

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

ブロックデバイスを制御し、そのパラメータを照会します。実行する操作は op で指定され、次のいずれかの整数です:

  • 1 -- デバイスを初期化します(arg は使用されません)

  • 2 -- デバイスをシャットダウンします(arg は使用されません)

  • 3 -- デバイスを同期します(arg は使用されません)

  • 4 -- ブロック数を取得します。整数を返す必要があります(arg は使用されません)

  • 5 -- 1 ブロックあたりのバイト数を取得します。整数を返すか 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 を、失敗時に非ゼロを返す必要があり、返される値は OSError の errno コードです。