vfs -- 仮想ファイルシステム制御
vfs モジュールには、仮想ファイルシステム内のファイルシステムオブジェクトを作成し、マウント/アンマウントするための関数が含まれています。
ファイルシステムのマウント
いくつかのポートは仮想ファイルシステム(VFS)を提供し、この VFS 内に複数の「実」ファイルシステムをマウントする機能を備えています。ファイルシステムオブジェクトは、VFS のルート、またはルートに存在するサブディレクトリにマウントできます。これにより、Python プログラムで見られるファイルシステムの動的で柔軟な設定が可能になります。この機能を持つポートは mount() と umount() 関数、そしておそらく VFS クラスで表されるさまざまなファイルシステムの実装を提供します。
- vfs.mount(fsobj, mount_point, *, readonly)
ファイルシステムオブジェクト fsobj を mount_point 文字列で指定した VFS 内の場所にマウントします。 fsobj には
mount()メソッドを持つ VFS オブジェクト、またはブロックデバイスを指定できます。ブロックデバイスであればファイルシステムタイプが自動的に検出されます(ファイルシステムが認識されない場合は例外が発生します)。 mount_point が'/'であれば fsobj をルートににマウントし、'/<name>'であればルート配下のサブディレクトリにマウントします。readonly が
Trueであればファイルシステムが読込み専用でマウントされています。マウント処理では、ファイルシステムオブジェクトに対してメソッド
mount()呼出します。mount_point に既にマウントされていれば
OSError(EPERM)例外が発生します。
- vfs.mount()
引数なしで
mount()を呼び出すと、すべてのアクティブなマウントポイントを表すタプルのリストを返します。返されるリストの形式は [(fsobj, mount_point), ...] です。
- vfs.umount(mount_point)
ファイルシステムをアンマウントします。 mount_point には、マウント場所を指定する文字列、または以前にマウントされたファイルシステムオブジェクトを指定できます。アンマウント処理では、ファイルシステムオブジェクトに対してメソッド
unmount()呼出します。mount_point が見つからなければ
OSError(EINVAL)例外が発生します。
ファイルシステムの種類
- class vfs.VfsFat(block_dev)
FAT ファイルシステムのフォーマットを使うファイルシステムオブジェクトを作成します。FAT ファイルシステムのストレージは block_dev によって提供されます。このコンストラクタによって作成されたオブジェクトは
mount()を使ってマウントできます。- static mkfs(block_dev)
block_dev に FAT ファイルシステムを構築します。
- class vfs.VfsLfs1(block_dev, readsize=32, progsize=32, lookahead=32)
littlefs v1 filesystem format を使うファイルシステムオブジェクトを作成します。littlefs ファイルシステムのストレージは block_dev によって提供されます。 block_dev は extended interface をサポートしている必要があります。このコンストラクタによって作成されたオブジェクトは
mount()を使ってマウントできます。詳しくは ファイルシステムの利用 を参照してください。
- static mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
block_dev に Lfs1 ファイルシステムを構築します。
注釈
特定の状況で littlefs v1 が失敗するという報告があります。詳細については littlefs issue 347 を参照してください。
- class vfs.VfsLfs2(block_dev, readsize=32, progsize=32, lookahead=32, mtime=True)
littlefs v2 filesystem format を使うファイルシステムオブジェクトを作成します。littlefs ファイルシステムのストレージは block_dev によって提供されます。 block_dev は extended interface をサポートしている必要があります。このコンストラクタによって作成されたオブジェクトは
mount()を使ってマウントできます。mtime 引数はファイルの更新タイムスタンプを有効にします。このオプションはマウント毎に有効/無効にでき、 mtime が有効な場合にのみタイムスタンプが追加/更新されます。 mtime が無効であれば、タイムスタンプが追加/更新されないままとなります。タイムスタンプのない Littlefs v2 ファイルシステムは、再フォーマットしなくても動作し、既存のファイルをオープンして書出しを行うと、タイムスタンプは透過的に追加されます。 mtime が有効になっている場合、タイムスタンプのないファイルに対して
os.statを行った際のタイムスタンプの値は 0 になります。詳しくは ファイルシステムの利用 を参照してください。
- static mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
block_dev に Lfs2 ファイルシステムを構築します。
注釈
特定の状況で littlefs v2 が失敗するという報告があります。詳細については littlefs issue 295 を参照してください。
- class vfs.VfsPosix(root=None)
ホストの POSIX ファイルシステムにアクセスするファイルシステムオブジェクトを作成します。 root を指定した場合、それは
VfsPosixオブジェクトのルートとして使用するホストファイルシステム内のパスである必要があります。それ以外の場合、ホストファイルシステムの現在のディレクトリが適用されます。
- class vfs.VfsRom(buffer)
このクラスは、ファームウェアが
MICROPY_VFS_ROMを有効にしてビルドされている場合にのみ利用できます。ROMFS の読み出し専用ファイルシステム形式 を使うファイルシステムオブジェクトを作成します。 buffer は、有効な ROMFS イメージを含む、バッファプロトコルをサポートするオブジェクト(
bytes、bytearray、memoryviewなど)でなければなりません。コンストラクタは、 buffer が ROMFS のマジックバイト (b"\xd2\xcd\x31") で始まることを検証します。バッファが小さすぎる場合や有効な ROMFS でない場合はOSError(ENODEV)が発生します。ROMFS のファイルシステムと、 mpremote を使ったイメージのデプロイ方法の詳細は ROMFS の利用 を参照してください。
- open(path, mode)
ROMFS からファイルを開きます。読み出しのモード (
''、'r'、'rt'、'rb') のみサポートされます。バイナリファイルを読み出しモードで開いた場合、返されるオブジェクトはバッファプロトコルもサポートするので、ファイルのデータのmemoryviewを取得できます。これは ROMFS のメモリを直接参照します(ゼロコピー)。
- statvfs(path)
ブロックサイズは 1 として報告され、ブロック数は ROMFS イメージの総サイズ(バイト単位)を表します。
- chdir(path)
ROMFS 内でディレクトリを変更します。ルート (
'/') のみサポートされます。サブディレクトリに移動しようとするとOSError(EOPNOTSUPP)が発生します。
その他の関数
- vfs.rom_ioctl(op, ...)
デバイスの読み出し専用メモリ (ROM) のパーティションにアクセスするための低レベルなインターフェースです。この関数は ROMFS をサポートするポート(つまり
MICROPY_VFS_ROM_IOCTLが有効なポート)でのみ利用できます。サポートされている操作は次のとおりです:
vfs.rom_ioctl(1)-- 利用できる ROM パーティションの数を返します。vfs.rom_ioctl(2, id)-- ROM パーティション id を、バッファプロトコルをサポートするオブジェクトとして返します。ポートによって、これはブロックデバイスかmemoryviewになります。ブロックデバイスは、消去や書き込みの操作を含む標準的なブロックプロトコルをサポートします。memoryviewが返される場合、ポートは下記のvfs.rom_ioctl()の操作 3、4、5 を通じて消去と書き込みの操作を提供しなければなりません。vfs.rom_ioctl(3, id, length)-- ROM パーティション id の先頭 length バイトを書き込み可能な状態にします(たとえばフラッシュを消去します)。最小の書き込みサイズをバイト単位で返します(以降の書き込みに必要な整列の単位です)。vfs.rom_ioctl(3, id, offset, length)-- ROM パーティション id の、バイト位置 offset から length バイトを書き込み可能な状態にします。この形式では、パーティションを少しずつ準備できます。最小の書き込みサイズをバイト単位で返します。vfs.rom_ioctl(4, id, offset, buf)-- インデックス id の ROM パーティションのバイト位置 offset に buf (bytes 風のオブジェクト)を書き込みます。vfs.rom_ioctl(5, id)-- パーティション id への書き込みシーケンスを完了します(キャッシュのフラッシュなど、書き込み後に必要な仕上げの処理を行います)。vfs.rom_ioctl(6, id)-- ROM パーティション id について、一度に準備できる最小のバイト数を返します。正の値が返る場合は、操作 3 の4引数形式がサポートされていることを示し、 offset と length はこの値に整列していなければなりません。そうでない場合は、操作 3 の3引数形式のみがサポートされます。
これらの操作は、ROMFS のイメージをデプロイするために
mpremoteが内部的に使います。ほとんどのユーザーがvfs.rom_ioctl()を直接呼び出す必要はありません。詳しくは ROMFS の利用 を参照してください。
ブロックデバイス
ブロックデバイスは、ブロックプロトコルを実装するオブジェクトです。これによりデバイスが MicroPython ファイルシステムをサポートできるようになります。物理ハードウェアはユーザー定義のクラスによって表されます。 AbstractBlockDev クラスはそのようなクラスを定義するためのテンプレートです。MicroPython が提供していないブロックデバイスクラスを自作する場合は後述のメソッドを実装する必要があります。
このクラスの具象サブクラスでは通常(フラッシュメモリのような)ハードウェアの一部にメモリのような機能へのアクセスが許可されます。ブロックデバイスはサポートされているファイルシステムでフォーマットでき、 os のメソッドを使ってマウントできます。
後述する2種類のブロックプロトコルを使ったブロックデバイスの実装例については ファイルシステムの利用 を参照してください。
シンプルインタフェースと拡張インタフェース
さまざまなユースケースをサポートするために、 readblocks や writeblocks メソッドには2つの互換性のあるシグネチャがあります(以下を参照)。与えられたブロックデバイスは、どちらか一方、または両方を実装しています。2番目の形式(offset 引数のあるもの)は「拡張インタフェース」といいます。
書出し操作をより細かく制御する必要のある一部のファイルシステム(littlefs など)では、たとえば、消去せずにサブブロック領域に書き出す場合、ブロックデバイスが拡張インターフェイスをサポートしている必要がある場合があります。
- class vfs.AbstractBlockDev(...)
ブロックデバイスオブジェクトを構築します。コンストラクタへのパラメータは、特定のブロックデバイスに依存します。
- readblocks(block_num, buf)
- readblocks(block_num, buf, offset)
最初の形式は、整列した複数のブロックを読み込みます。インデックス block_num で指定したブロックを開始点として、デバイスから buf (バイトの配列)にブロックを読み込みます。読み込むブロック数は buf の長さで与えられ、ブロックサイズの倍数になります。
2番目の形式では、ブロック内の任意の場所、任意の長さで読み込めます。ブロックインデックス block_num とブロック内のバイトオフセット offset を開始点として、デバイスから buf (バイトの配列)にブロックを読み込みます。読み込むブロック数は buf の長さで与えられ、読み込むバイト数になります。
メソッドが成功した場合、
Noneまたは 0 を返す必要があります。失敗した場合、OSErrorerrno コードに対応する負の整数を返す必要があります。
- writeblocks(block_num, buf)
- writeblocks(block_num, buf, offset)
最初の形式は、整列した複数のブロックを書き出します。書き出す前には、対象のブロックが(必要に応じて)消去されます。インデックス block_num で指定したブロックに buf (バイトの配列)からブロックを書き出します。書き出すブロック数は buf の長さで与えられ、ブロックサイズの倍数になります。
2番目の形式では、ブロック内の任意の場所に、任意の長さで書き出せます。書き出すバイトのみを変更する必要があり、このメソッドの呼び出し元は、関連するブロックが事前の
ioctl呼び出しによって消去されることを保証する必要があります。ブロックインデックス block_num とそのブロック内のバイトオフセット offset を開始点として、 buf (バイト配列)からデバイスに書き出します。書き出すバイト数は buf の長さで指定されます。offset 引数が指定されている場合、たとえゼロであっても、実装がブロックを暗黙的に消去してはならないことに注意してください。
メソッドが成功した場合、
Noneまたは 0 を返す必要があります。失敗した場合、OSErrorerrno コードに対応する負の整数を返す必要があります。
- ioctl(op, arg)
ブロックデバイスの制御とパラメータ問い合わせをおこないます。実行する操作は op に次の整数のうちの1つで指定します。
1 -- デバイスを初期化します(arg は未使用)
2 -- デバイスをシャットダウンします(arg は未使用)
3 -- デバイスを同期します(arg は未使用)
4 -- ブロック数を取得し、整数で返します(arg は未使用)
5 -- ブロック内のバイト数を取得し、整数で返します。
Noneの場合はデフォルト値の 512 が使われます(arg は未使用)6 -- ブロックを消去します。 arg は消去するブロック数です
少なくとも
ioctl(4, ...)が受け付けられる必要があります。littlefs についてはioctl(6, ...)も受け付けられる必要があります。その他の操作が受け付けられるかはハードウェアに依存します。littlefs は
writeblocks(block, ...)の呼び出しの前にioctl(6, block)を発行します。これによりハードウェアが要求するなら、デバイスドライバは書き出す前にブロックを消去できます。あるいは、ドライバがioctl(6, block)を捉えて 0 (成功)を返すようにするかもしれません。この場合、ドライバは消去の必要性を検出する責任を負います。特に記載のない限り
ioctl(op, arg)はNoneを返します。したがって処理系はopの未使用値を無視できます。opが受け付けられる場合、操作 4 と 5 の戻り値は上記のとおりです。受け付けられる他の操作の戻り値は、成功した場合は 0 を返し、失敗した場合はゼロ以外を返します。失敗した場合の戻り値はOSErrorの errno コードです。