vfs – 虚拟文件系统控制

vfs 模块包含用于创建文件系统对象以及在虚拟文件系统中挂载/卸载它们的函数。

文件系统挂载

某些端口提供虚拟文件系统(VFS)功能,并能够在该 VFS 中挂载多个“真实”文件系统。文件系统对象可以挂载在 VFS 的根目录或根目录下的子目录中。这允许动态和灵活地配置 Python 程序所看到的文件系统。具有此功能的端口提供 mount()umount() 函数,并可能提供由 VFS 类表示的各种文件系统实现。

vfs.mount(fsobj, mount_point, *, readonly)

将文件系统对象 fsobj 挂载到 VFS 中由 mount_point 字符串指定的位置。fsobj 可以是具有 mount() 方法的 VFS 对象,也可以是块设备。如果是块设备,则会自动检测文件系统类型(如果未识别文件系统,则会引发异常)。mount_point 可以是 '/',表示将 fsobj 挂载到根目录,也可以是 '/<name>',表示将其挂载到根目录下的子目录。

如果 readonlyTrue,则文件系统以只读模式挂载。

在挂载过程中,会调用文件系统对象的 mount() 方法。

如果 mount_point 已经被挂载,将引发 OSError(EPERM)

vfs.umount(mount_point)

卸载文件系统。mount_point 可以是一个表示挂载位置的字符串,或者是一个之前已挂载的文件系统对象。在卸载过程中,会调用文件系统对象的 umount() 方法。

如果未找到 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 文件系统格式 的文件系统对象。littlefs 文件系统的存储由 block_dev 提供,block_dev 必须支持 扩展接口。通过此构造函数创建的对象可以使用 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 文件系统格式 的文件系统对象。littlefs 文件系统的存储由 block_dev 提供,block_dev 必须支持 扩展接口。通过此构造函数创建的对象可以使用 mount() 进行挂载。

mtime 参数启用文件的修改时间戳,这些时间戳使用 littlefs 属性存储。此选项可以在每次挂载时启用或禁用,并且只有在启用 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 对象根目录的路径。否则,将使用主机文件系统的当前目录。

块设备

块设备是实现块协议的对象。这使得设备能够支持 MicroPython 文件系统。物理硬件由用户定义的类表示。 AbstractBlockDev 类是这种类设计的模板:MicroPython 实际上并没有提供该类,但实际的块设备类必须实现以下所描述的方法。

该类的具体实现通常允许访问硬件的一块内存功能(例如闪存)。块设备可以被格式化为任何支持的文件系统,并通过 os 方法进行挂载。

有关使用下面描述的两种块协议变体实现块设备的示例,请参见 使用文件系统

简单接口和扩展接口

readblockswriteblocks 方法有两种兼容的签名(见下文),以支持多种使用场景。一个给定的块设备可以实现其中一种形式,也可以同时实现两种形式。第二种形式(带有 offset 参数)被称为“扩展接口”。

一些文件系统(如 littlefs),由于需要更精确地控制写操作,例如在不擦除的情况下写入子块区域,可能要求块设备支持扩展接口。

class vfs.AbstractBlockDev(...)

构造一个块设备对象。构造函数的参数依赖于特定的块设备。

readblocks(block_num, buf)
readblocks(block_num, buf, offset)

第一种形式读取对齐的块的倍数。从由 block_num 索引指定的块开始,将块从设备读取到 buf*(一个字节数组)中。要读取的块数由 *buf 的长度给出,且该长度将是块大小的倍数。

第二种形式允许在块内的任意位置读取,并且支持任意长度。从块索引 block_num 开始,及该块内的字节偏移 offset,将字节从设备读取到 buf*(一个字节数组)中。要读取的字节数由 *buf 的长度给出。

writeblocks(block_num, buf)
writeblocks(block_num, buf, offset)

第一种形式写入对齐的块的倍数,并要求在写入之前,必须先通过此方法擦除(如果需要)要写入的块。从由 block_num 索引指定的块开始,将 buf*(一个字节数组)中的块写入设备。要写入的块数由 *buf 的长度给出,且该长度将是块大小的倍数。

第二种形式允许在块内的任意位置写入,并且支持任意长度。只有正在写入的字节会被更改,调用此方法的代码必须确保通过之前的 ioctl 调用擦除了相关的块。从块索引 block_num 开始,及该块内的字节偏移 offset,将字节从 buf*(一个字节数组)写入设备。要写入的字节数由 *buf 的长度给出。

请注意,如果指定了偏移量参数(即使是零),实现必须永远不隐式擦除块。

ioctl(op, arg)

控制块设备并查询其参数。要执行的操作由 op 给出,op 是以下整数之一:

  • 1 – 初始化设备(arg 未使用)

  • 2 – 关闭设备(arg 未使用)

  • 3 – 同步设备(arg 未使用)

  • 4 – 获取块的数量,应返回一个整数(arg 未使用)

  • 5 – 获取块中的字节数,应返回一个整数,或者返回 None,在这种情况下将使用默认值 512(arg 未使用)

  • 6 – 擦除一个块,arg 是要擦除的块号

最少需要拦截 ioctl(4, ...);对于 littlefs,还必须拦截 ioctl(6, ...)。其他的需求取决于硬件。

在任何调用 writeblocks(block, ...) 之前,littlefs 会发出 ioctl(6, block)。这使得设备驱动程序在写入之前擦除块(如果硬件要求的话)。或者,驱动程序可以拦截 ioctl(6, block) 并返回 0(成功)。在这种情况下,驱动程序负责检测是否需要擦除。

除非另有说明,ioctl(op, arg) 可以返回 None。因此,实现可以忽略未使用的 op 值。当 op 被拦截时,操作 4 和 5 的返回值如上所述。其他操作应返回 0 表示成功,返回非零值表示失败,返回的值应为 OSError 错误号代码。