:mod:`uos` -- 基本“操作系统”服务 =============================================== .. module:: uos :synopsis: 基本“操作系统”服务 该模块实现相应 `CPython` 模块的子集,如下所示。更多信息,请参见 |CPython文档| :mod:`python:os`. ``uos`` 模块包含文件系统访问和挂载、终端重定向和复制以及 ``uname`` 和 ``urandom`` 函数。 函数 --------- .. function:: uname() 返回一个元组(可能是一个命名的元组),其中包含关于底层机器和/或其操作系统的信息。tuple有五个字段,它们的顺序如下: * ``sysname`` -- 底层系统的名称 * ``nodename`` -- 网络名称(可以与 ``sysname`` 相同) * ``release`` -- 底层系统的版本 * ``version`` -- MicroPython版本和构建日期 * ``machine`` -- 底层硬件(如主板、CPU)的标识符。 .. function:: urandom(n) 返回一个具有*n* 个随机字节的bytes对象。只要有可能,它就会由硬件随机数生成器生成。 文件系统访问 ----------------- .. function:: chdir(path) 改变当前目录。 .. function:: getcwd() 获取当前目录。 .. function:: ilistdir([dir]) 该函数返回一个迭代器,该迭代器将生成与它所列出目录中的条目相对应的3元组。无参数情况下,列出当前目录,否则列出由 *dir* 指定的目录。 元组的形式为 *(name, type, inode[, size])*: - *name* 为一个字符串(若dir为一个字节对象,则名称为字节)且为条目的名称; - *type* 为一个指定条目类型的整数,其中目录为0x4000,常规文件为0x8000; - *inode* 为一个与文件的索引节点相对应的整数,而对于没有这种概念的文件系统来说,可能为0。 - 一些平台可能会返回一个4元组,其中包含条目的*size*。 对于文件条目,*size* 是表示文件大小的整数,如果未知,则为-1。 对于目录项,其含义目前尚未定义。 .. function:: listdir([dir]) 若无参数,则列出当前目录;否则将列出给定目录。 .. function:: mkdir(path) 创建一个新目录。 .. function:: remove(path) 删除一个文件。 .. function:: rmdir(path) 删除一个目录。 .. function:: rename(old_path, new_path) 重命名文件。 .. function:: stat(path) 获取文件或目录的状态。 .. function:: statvfs(path) 获取文件系统的状态。 按照以下顺序返回一个具有文件系统信息的元组: * ``f_bsize`` -- 文件系统块大小 * ``f_frsize`` -- 碎片大小 * ``f_blocks`` -- f_frsize单元中fs的大小 * ``f_bfree`` -- 空闲块的数量 * ``f_bavail`` -- 非特权用户的免费块数 * ``f_files`` -- 索引节点的数量 * ``f_ffree`` -- 空闲索引节点的数量 * ``f_favail`` -- 非特权用户的免费空闲索引节点的数量 * ``f_flag`` -- 挂载标志 * ``f_namemax`` -- 最大文件名长度 与索引节点相关的参数: ``f_files`` 、 ``f_ffree`` 、 ``f_avail`` 、 ``f_flags`` 参数可能会返回0,因为它们在特定于端口的实现中不可用。 .. function:: sync() 同步所有文件系统。 终端重定向和复制 ------------------------------------ .. function:: dupterm(stream_object, index=0) 在给定的 `stream` 类对象上复制或切换MicroPython终端(REPL)。*stream_object* 参数必须是一个本机流对象, 或者派生自 ``uio.IOBase`` 并实现 ``readinto()`` 和 ``write()`` 方法。流应该处于非阻塞模式, 如果没有数据可供读取,``readinto()`` 应该返回 ``None`` 。 调用此函数后,将在此流上重复所有终端输出,并将流上可用的任何输入传递到终端输入。 *index*参数应该是一个非负整数,并指定设置哪个复制插槽。 给定的端口可以实现多个插槽(插槽0总是可用的),在这种情况下,终端输入和输出在所有设置的插槽上重复。 如果 ``None`` 作为 *stream_object* 传递,则在 *index* 提供的插槽上取消复制。 该函数返回给定插槽中的前一个类似流的对象。 文件系统安装 ------------------- 某些端口提供虚拟文件系统(VFS),并能够在此VFS中挂载多个“实际”文件系统。 文件系统对象可以安装在VFS的根目录下,也可以安装在根目录下的子目录中。 这样可以动态灵活地配置Python程序可以看到的文件系统。 具有此功能的端口提供 :func:`mount` 和 :func:`umount` 函数,以及由VFS类表示的各种文件系统实现。 .. function:: mount(fsobj, mount_point, \*, readonly) 将文件系统对象 *fsobj* 挂载在VFS中 *mount_point* 字符串给出的位置。 *fsobj* 可以是一个具有 ``mount()`` 方法的VFS对象,也可以是一个块设备。 如果是块设备,则自动检测文件系统类型(如果没有识别出文件系统,则会引发异常)。 *mount_point* 可以是 ``'/'`` 以便将 *fsobj* 挂载在根目录下, 或者是 ``'/'`` 可以将其挂载在根目录下的子目录中。 如果 *readonly* 是 ``True``,那么文件系统是只读安装的。 在挂载过程中,在文件系统对象上调用 ``mount()`` 方法。 如果 *mount_point* 已经挂载将引发 ``OSError(EPERM)`` 。 .. function:: umount(mount_point) 卸载文件系统。*mount_point* 可以是命名挂载位置的字符串,也可以是以前挂载的文件系统对象。 在卸载过程中,在文件系统对象上调用 ``umount()`` 方法。 如果没有找到 *mount_point* ,将引发 ``OSError(EINVAL)``。 .. class:: VfsFat(block_dev) 创建一个使用FAT文件系统格式的文件系统对象。FAT文件系统的存储由 *block_dev* 提供。 这个构造函数创建的对象可以使用 :func:`mount` 来挂载。 .. staticmethod:: mkfs(block_dev) 在 *block_dev* 上构建一个FAT文件系统。 .. class:: VfsLfs1(block_dev, readsize=32, progsize=32, lookahead=32) 创建一个使用 `littlefs v1 文件系统格式`_ 的文件系统对象。 littlefs 文件系统的存储由 *block_dev* 提供,它必须支持 :ref:`扩展接口 `。 可以使用 :func:`mount` 挂载此构造函数创建的对象。 有关更多信息,请参阅 :ref:`filesystem`。 .. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32) 在 *block_dev* 上构建 Lfs1 文件系统。 .. 注意:: 有报告称 littlefs v1 在某些情况下会失败,详情请参阅 `littlefs issue 347`_。 .. class:: VfsLfs2(block_dev, readsize=32, progsize=32, lookahead=32, mtime=True) 创建一个使用 `littlefs v2 文件系统格式`_ 的文件系统对象。 littlefs 文件系统的存储由 *block_dev* 提供,它必须支持 :ref:`扩展接口 `。 可以使用 :func:`mount` 挂载此构造函数创建的对象。 *mtime* 参数启用文件的修改时间戳,使用 littlefs 属性存储。 此选项可以在每个安装时间以不同的方式禁用或启用, 并且只有在启用 *mtime* 时才会添加或更新时间戳,否则时间戳将保持不变。 没有时间戳的 Littlefs v2 文件系统无需重新格式化即可工作, 一旦打开以进行写入,时间戳将透明地添加到现有文件中。 当 *mtime* 在没有时间戳的文件上启用 `uos.stat` 时,时间戳将返回 0。 有关更多信息,请参阅 :ref:`filesystem`。 .. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32) 在 *block_dev* 上构建 Lfs2 文件系统。 .. 注意:: 有报告称 littlefs v2 在某些情况下会失败, 有关详细信息,请参阅 `littlefs 问题 295`_。 .. _littlefs v1 文件系统格式:https://github.com/ARMmbed/littlefs/tree/v1 .. _littlefs v2 文件系统格式:https://github.com/ARMmbed/littlefs .. _littlefs 问题 295:https://github.com/ARMmbed/littlefs/issues/295 .. _littlefs 问题 347:https://github.com/ARMmbed/littlefs/issues/347 块设备 ------------- 块设备是实现块协议的对象。 这使设备能够支持 MicroPython 文件系统。 物理硬件由用户定义的类表示。 :class:`AbstractBlockDev` 类是设计这样一个类的模板:MicroPython 实际上并没有提供那个类, 但是一个实际的块设备类必须实现下面描述的方法。 此类的具体实现通常允许访问硬件(如闪存)的类似内存的功能。 块设备可以格式化为任何支持的文件系统并使用 uos 方法挂载。 参见 :ref:`filesystem` 使用下面描述的块协议的两个变体来实现块设备的示例。 .. _block-device-interface: 简单和扩展的界面 ............................. ``readblocks`` 和 ``writeblocks`` 方法有两个兼容的签名(见下文),以支持各种用例。 给定的块设备可以实现一种形式或另一种形式,或同时实现两种形式。 第二种形式(带有偏移参数)被称为“扩展接口”。 一些需要对写入操作进行更多控制的文件系统(例如 littlefs),例如在不擦除的情况下写入子块区域,可能需要块设备支持扩展接口。 .. class:: AbstractBlockDev(...) 构造一个块设备对象。构造函数的参数依赖于特定的块设备。 .. method:: readblocks(block_num, buf) readblocks(block_num, buf, offset) 第一种形式读取对齐的块的倍数。 从索引 *block_num* 给出的块开始,从设备读取块到 *buf*(字节数组)。 要读取的块数由 *buf* 的长度给出,它将是块大小的倍数。 第二种形式允许在块内的任意位置和任意长度读取。 从块索引 *block_num* 和 *offset* 块内的字节偏移量开始,将字节从设备读取到 *buf*(字节数组)。 要读取的字节数由 *buf* 的长度给出。 .. method:: writeblocks(block_num, buf) writeblocks(block_num, buf, offset) 第一种形式写入对齐的多个块,并要求通过此方法首先擦除写入的块(如果需要)。 从索引 *block_num* 给出的块开始,将来自 *buf*(字节数组)的块写入设备。 要写入的块数由 *buf* 的长度给出,这将是块大小的倍数。 第二种形式允许在块内的任意位置和任意长度写入。 只应更改写入的字节,并且此方法的调用者必须确保通过先前的 ``ioctl`` 调用擦除相关块。 从块索引 *block_num* 和 *offset* 块内的字节偏移开始,将字节从 *buf*(字节数组)写入设备。 要写入的字节数由 *buf* 的长度给出 . 请注意,如果指定了 offset 参数,则实现绝不能隐式擦除块,即使它为零。 .. method:: ioctl(op, arg) 控制块设备并查询其参数。要执行的操作由 *op* 给出,它是以下整数之一: - 1 -- 初始化设备( *arg* 未使用) - 2 -- 关闭设备( *arg* 未使用) - 3 -- 同步设备( *arg* 未使用) - 4 -- 获取块数的计数,应该返回一个整数( *arg* 未使用) - 5 -- 获取一个块中的字节数,应该返回一个整数,或者 ``None`` ,在这种情况下使用默认值512 ( *arg* 未使用) - 6 -- 擦除一个块,*arg* 是要擦除的块号 至少必须拦截 ``ioctl(4, ...)`` ; 对于 littlefs ``ioctl(6, ...)`` 也必须被拦截。 对其他的需求取决于硬件。 除非另有说明 ``ioctl(op, arg)`` 可以返回 ``None``。 因此,实现可以忽略未使用的 ``op`` 值。 在拦截 ``op`` 的地方,操作4和5的返回值如上详述。 其他操作应该在成功时返回 0,失败时返回非零,返回的值是一个 ``OSError`` 错误代码。