vfs --- 虛擬檔案系統控制

vfs 模組包含用於建立檔案系統物件,以及在虛擬檔案系統中掛載/卸載這些物件的函式。

檔案系統掛載

有些連接埠提供虛擬檔案系統(VFS),並能在此 VFS 中掛載多個「真實」的檔案系統。檔案系統物件可以掛載在 VFS 的根目錄,或掛載在根目錄下的某個子目錄。這讓 Python 程式所看到的檔案系統能夠進行動態而彈性的設定。具備此功能的連接埠會提供 mount()umount() 函式,以及可能由各種 VFS 類別所代表的不同檔案系統實作。

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

將檔案系統物件 fsobj 掛載到 VFS 中由 mount_point 字串所指定的位置。fsobj 可以是具有 mount() 方法的 VFS 物件,或是一個區塊裝置。如果是區塊裝置,則會自動偵測其檔案系統類型(若無法辨識任何檔案系統則會引發例外)。mount_point 可以是 '/' 以將 fsobj 掛載到根目錄,或是 '/<name>' 以將其掛載到根目錄下的子目錄。

如果 readonlyTrue,則該檔案系統會以唯讀方式掛載。

在掛載過程中,會呼叫檔案系統物件上的 mount() 方法。

如果 mount_point 已被掛載,則會引發 OSError(EPERM)

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

不帶任何引數呼叫 mount() 時,會回傳一個包含所有作用中掛載點的元組(tuple)清單。

回傳的清單格式為 [(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 必須是支援緩衝區協定(bytesbytearraymemoryview)且包含有效 ROMFS 映像的物件。

由此建構式建立的物件可使用 mount() 掛載。

完整細節請參閱 使用 ROMFS,其中包括如何使用 mpremote 建置與部署 ROMFS 映像。

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

用於存取裝置唯讀記憶體(ROM)分割區的低階介面。支援的操作如下:

呼叫

行為

rom_ioctl(1)

回傳可用的 ROM 分割區數量。

rom_ioctl(2, id)

memoryview 的形式回傳分割區 id

rom_ioctl(3, id, length)

抹除分割區 id 的前 length 個位元組以準備寫入。回傳以位元組為單位的最小寫入對齊值。

rom_ioctl(4, id, offset, buf)

在分割區 id 的位元組 offset 位置寫入 buf

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 為零也是如此。

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,失敗時回傳非零值,所回傳的值為一個 OSError errno 代碼。