
嵌入式语言运行时编程语言解释器编译器物联网系统编程【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址https://gitcode.com/gh_mirrors/mi/micropython点击查看免费下载本篇技术指南以 MicroPython 官方文档 docs/library/os.rst 为骨架结合本仓库extmod/与ports/下的 C 语言实现源码系统讲解os模块的四大能力系统信息查询uname、urandom、文件系统访问chdir、ilistdir、statvfs等、终端重定向与复制dupterm、dupterm_notify、文件系统挂载mount、umount与Vfs*类。读完本文你将能在任何启用MICROPY_PY_OS与MICROPY_VFS的 MicroPython 端口上熟练操作目录与文件、查询系统信息、统计磁盘空间并通过 UART/蓝牙等流对象接管 REPL 终端甚至自行实现文件系统并挂载到根目录。一、os模块总览os模块在 MicroPython 中提供操作系统服务其能力范围比 CPython 的os模块更聚焦主要包含三类功能通用函数uname()获取系统信息与urandom(n)获取随机字节文件系统访问chdir、getcwd、listdir、ilistdir、mkdir、remove、rmdir、rename、stat、statvfs、sync等终端重定向与复制dupterm、dupterm_notify。此外为了向后兼容os模块还保留了一批已迁移到vfs模块的函数与类mount、umount、VfsFat、VfsLfs1、VfsLfs2、VfsPosix。它们计划在 MicroPython 2.0 中从os模块移除新代码应直接使用 vfs 模块。从源码层面看模块的注册与成员表定义在 extmod/modos.cos_module_globals_table按编译期宏如MICROPY_PY_OS_SYNC、MICROPY_PY_OS_UNAME、MICROPY_VFS、MICROPY_PY_OS_DUPTERM条件编译地注册各成员因此不同端口可裁剪出不同大小的os模块文件系统相关函数chdir、getcwd、listdir、stat、statvfs等在MICROPY_VFS开启时实际指向extmod/vfs.c中实现的mp_vfs_*系列 C 函数即os模块是 VFS虚拟文件系统层的薄封装部分端口如ports/unix还会额外注册getenv/putenv/unsetenv/system/errno参见 ports/unix/modos.c。二、通用函数uname()与urandom()2.1uname()—— 查询系统与固件信息uname()返回一个命名元组named tuple按固定顺序包含五个字符串字段字段含义源码取值sysname底层系统名称MICROPY_PY_SYS_PLATFORMnodename网络节点名称可与sysname相同MICROPY_PY_SYS_PLATFORMrelease底层系统/固件版本MICROPY_VERSION_STRING或在MICROPY_PY_OS_UNAME_RELEASE_DYNAMIC下动态获取versionMicroPython 版本号与构建日期MICROPY_GIT_TAG on MICROPY_BUILD_DATEmachine底层硬件标识板卡、CPUMICROPY_HW_BOARD_NAME with MICROPY_HW_MCU_NAME实现位于 extmod/modos.c五个字段的定义通过MP_DEFINE_STR_OBJ静态构造再由MP_DEFINE_ATTRTUPLE打包成 5 元属性元组返回。这意味着返回对象既支持下标访问u[0]也支持属性访问u.sysname、u.machine与 attrtuple2.py 测试的行为一致。在典型的 ESP32 端口上运行输出类似 import os u os.uname() u.sysname esp32 u.machine ESP32 module (spiram) with ESP32 u.version v1.24.0 on 2024-08-202.2urandom(n)—— 获取随机字节urandom(n)返回一个长度为n的bytes对象只要硬件具备随机数发生器HWRNG实现会优先从硬件取随机数而不是软件伪随机。源码 extmod/modos.c 中的实现要点对参数n先做负值检查n 0时抛出ValueError通过vstr_init_len预分配n字节缓冲区再调用端口层接口mp_hal_get_random(n, buf)填充mp_hal_get_random通常在各自端口的mphalport.c中定义最终用mp_obj_new_bytes_from_vstr包装成bytes对象返回。对应的单元测试 tests/extmod/os_urandom.py 遍历n从 -2 到 4 的取值验证正数n返回正确长度、负数抛出ValueError os.urandom(4) b\x8f\x1b\xc3\xa6 # 每次运行结果不同使用提示由于返回值是字节串需要取模/转 int 时可配合int.from_bytes()n较大时注意目标板剩余 RAM通常一次请求几字节到几十字节即可满足随机种子、挑战值等需求。三、文件系统访问文件系统访问函数在MICROPY_VFS开启时全部委托给 VFS 层。核心机制是extmod/vfs.c中的mp_vfs_lookup_path()extmod/vfs.c它把路径解析为挂载点mount point 挂载点内路径随后mp_vfs_proxy_call()extmod/vfs.c把调用代理到对应文件系统对象的同名方法上。因此下面的每个os函数本质都是对当前挂载的文件系统实例方法的转发。3.1 目录导航chdir()与getcwd()os.chdir(path)切换当前工作目录os.getcwd()获取当前工作目录。chdir实现见 extmod/vfs.c切换成功后会把目标 VFS 记录到全局状态vfs_curroot pointer注册于 extmod/vfs.c后续所有相对路径都在该 VFS 内解析若切到根目录且根目录上挂载了文件系统还会同步把该文件系统的内部目录重置为/。getcwd见 extmod/vfs.c位于虚拟根目录时返回/否则把挂载点路径前缀拼接到文件系统返回的当前目录上根挂载的特殊情况不重复加/。 os.getcwd() / os.mkdir(data) os.chdir(data) os.getcwd() /data3.2 目录列举listdir()与ilistdir()os.listdir([dir])无参数列出当前目录否则列出指定目录返回条目名字符串列表os.ilistdir([dir])返回一个迭代器逐个产出描述条目的元组。ilistdir是底层原语listdir只是对它的封装见 extmod/vfs.c反复mp_iternext并取元组第 0 个元素即名字。ilistdir产出的元组形式为(name, type, inode[, size])元素类型说明namestr若入参是 bytes 则为 bytes条目名称typeint0x4000 表示目录0x8000 表示普通文件inodeint文件 inode不支持该概念的文件系统可为 0sizeint可选依文件系统而定文件大小未知为 -1对目录条目的含义当前未定义 for name, typ, inode, size in os.ilistdir(/): ... kind DIR if typ 0x4000 else FILE ... print(kind, name, size if size is not None else )由于ilistdir是惰性迭代器对大型目录可以只遍历到需要的条目即停止相关测试见 vfs_fat_ilistdir_del.py它专门验证部分迭代后迭代器析构的安全性。注意type取值是MP_S_IFDIR/MP_S_IFDIR等 POSIX 风格位标志0x4000/0x8000 即宏展开值。3.3 文件与目录操作mkdir、remove、rmdir、renameos.mkdir(path)创建新目录当目标是根目录或根挂载的/时抛出OSError(EEXIST)extmod/vfs.cos.remove(path)删除文件os.rmdir(path)删除目录os.rename(old_path, new_path)重命名文件源码 extmod/vfs.c 显式检查旧路径与新路径是否落在同一个文件系统跨文件系统重命名直接抛OSError(EPERM)。值得一提的细节os.unlink是remove的别名二者指向同一个 C 函数对象见 extmod/modos.c 的注释unlink aliases to remove。这四个写操作仅在MICROPY_VFS_WRITABLE宏开启时编译只读端口如部分发布固件可能没有它们。 os.mkdir(tmp) os.rename(a.txt, b.txt) os.remove(b.txt) os.rmdir(tmp)3.4 状态查询stat()与statvfs()os.stat(path)返回 10 元组st_mode、st_ino、st_dev、st_nlink、st_uid、st_gid、st_size、st_atime、st_mtime、st_ctime其中多数字段在嵌入式文件系统上为 0对虚拟根目录调用时extmod/vfs.c 会构造一个st_mode MP_S_IFDIR、其余为 0 的合成元组。os.statvfs(path)返回文件系统容量信息顺序与 CPython 一致实现见 extmod/vfs.c下标字段含义0f_bsize文件系统块大小1f_frsize片段大小2f_blocks以f_frsize为单位的总块数3f_bfree空闲块数4f_bavail非特权用户可用的空闲块数5f_filesinode 总数6f_ffree空闲 inode 数7f_favail非特权用户可用的空闲 inode 数8f_flag挂载标志9f_namemax最大文件名长度文档同时提醒inode 相关字段f_files、f_ffree、f_favail以及f_flags在特定端口的实现中可能不可用而返回 0。例如 vfs_fat_ramdisk.py 的期望输出statvfs: (512, 512, 16, 16, 16, 0, 0, 0, 0, 255)中inode 与 flags 字段全部为 0f_namemax为 255FAT 的长文件名上限。若根目录上没有任何挂载statvfs(/)会返回一个各容量字段为 0、f_namemax为MICROPY_ALLOC_PATH_MAX的元组——测试 vfs_basic.py 正是据此断言os.statvfs(/)[9] 32。磁盘可用空间计算示例 s os.statvfs(/) block_size s[0] * s[1] # bsize × frsize total s[2] * block_size free s[3] * block_size print(ftotal{total} free{free})3.5sync()—— 同步文件系统os.sync()将所有文件系统同步落盘。实现在 extmod/modos.c遍历全局挂载表vfs_mount_table对每个 FAT 文件系统调用disk_ioctl(..., CTRL_SYNC, NULL)强制刷新缓存。端口差异该函数仅在MICROPY_PY_OS_SYNC宏开启的端口上存在。文档明确指出某些端口如基于 PC 的ports/unix其写入直接进入宿主操作系统缓存在写入后无需显式同步因此没有该函数在微控制器上则建议在关键数据写入后调用以降低掉电丢数据的风险。兼容写法if hasattr(os, sync): os.sync()四、终端重定向与复制dupterm()与dupterm_notify()dupterm是 MicroPython 的扩展功能CPython 中没有用于把 REPL 终端输出复制到或切换至任意 stream 对象上是 UART 控制台、WebREPL、蓝牙 REPL 的核心机制。4.1os.dupterm(stream_object, index0, /)把stream_object注册到编号为index的复制槽位上index为非负整数槽位 0 永远可用端口可提供多个槽位此时终端输入输出会同时复制到所有已设置槽位传入None表示取消该槽位的复制返回该槽位之前的stream 对象便于恢复。对stream_object的要求文档与源码一致必须是原生 stream 对象或继承自io.IOBase并实现readinto()与write()方法必须处于非阻塞模式且readinto()在无数据时应返回None底层校验在 extmod/os_dupterm.c注册时调用mp_get_stream_raise(..., MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL)强制要求对象同时具备读写与 IOCTL 能力index越界负数或 ≥MICROPY_PY_OS_DUPTERM会抛ValueError(invalid dupterm index)。注册之后的行为由两个底层函数驱动extmod/os_dupterm.cmp_os_dupterm_rx_chr()第 100-174 行轮询各槽位读取输入字节并送入 REPL 的标准输入环形缓冲区。实现还处理了几个边界情况读到 EOFout_sz 0时自动去激活该槽位并打印dupterm: EOF received, deactivating读方法抛异常时去激活并打印异常信息读到中断字符mp_interrupt_char默认 CtrlC时调用mp_sched_keyboard_interrupt()调度 KeyboardInterrupt确保用户代码能立即被中断mp_os_dupterm_tx_strn()第 176-213 行把终端输出写入所有注册槽位返回最小成功写入长度某个槽位写入抛异常同样会导致该槽位被去激活。4.2os.dupterm_notify(obj_in, /)—— 主动通知 REPL 有输入dupterm_notify()用于告知 REPL某个已注册的流上有输入数据可读。自定义流实现如 UART、蓝牙等非 USB REPL 流应在数据到达时调用它这样 REPL 才能及时处理 CtrlC 等控制字符若不调用输入可能要等到下一次 REPL 轮询才被发现键盘中断或控制信号会被延迟。obj_in参数被函数本身忽略但保留它是为了允许从中断处理器如UART.irq()直接传入当前中断对象调用。文档给出的经典 UART REPL 示例from machine import UART import os uart UART(0) os.dupterm(uart, 0) uart.irq(os.dupterm_notify, machine.UART.IRQ_RX)源码 extmod/modos.c 中mp_os_dupterm_notify的实现值得注意它循环调用mp_os_dupterm_rx_chr()把当前可读的所有字节灌入stdin_ringbuf直到无数据c 0为止。同时该函数会锁定调度器mp_sched_lock()——注释extmod/os_dupterm.c详细解释了原因dupterm_notify常由中断/事件调度而来若不加锁可能出现mp_hal_stdin_rx_chr → mp_os_dupterm_rx_chr → 执行 Python 代码 → 再次触发 dupterm_notify → 再次进入 rx_chr的递归循环加锁后整个读取过程不会被新调度打断。五、文件系统挂载mount、umount与Vfs*类本节函数与类已从os模块迁移到 vfs 模块。当前os中仍保留它们仅为向后兼容编译期由!MICROPY_PREVIEW_VERSION_2 MICROPY_VFS控制见 extmod/modos.cMicroPython 2.0 将移除。新代码请直接使用vfs.mount()/vfs.umount()/vfs.VfsFat等。os中已废弃的名称等价于vfs中的说明os.mount(fsobj, mount_point, *, readonly)vfs.mount挂载文件系统对象或块设备os.umount(mount_point)vfs.umount卸载os.VfsFat(block_dev)vfs.VfsFatFAT 文件系统os.VfsLfs1(block_dev, readsize32, progsize32, lookahead32)vfs.VfsLfs1littlefs v1os.VfsLfs2(block_dev, readsize32, progsize32, lookahead32, mtimeTrue)vfs.VfsLfs2littlefs v2os.VfsPosix(rootNone)vfs.VfsPosixPOSIX宿主文件系统主要在ports/unix自动检测文件系统vfs.mount()传入块设备对象而非 VFS 实例时mp_vfs_autodetect()extmod/vfs.c会读取块 0 与块 1 的前 44 字节通过 littlefs 的littlefs签名魔数判断 LFS1/LFS2否则回退到 FAT最后调用对应 VFS 类型的make_new完成构造。这与以下日常用法一致import os, vfs # 自动检测并挂载块设备 vfs.mount(block_dev, /sd) # 显式指定文件系统 vfs.mount(vfs.VfsFat(block_dev), /sd, readonlyTrue)挂载过程mp_vfs_mountextmod/vfs.c还会校验目标挂载点未被占用已占用抛OSError(EPERM)根挂载下的子目录挂载除外、把新挂载点插入全局vfs_mount_table链表根挂载保持在链表末尾。umountextmod/vfs.c按挂载点字符串或 VFS 对象本身查找并摘除若卸载的是当前工作目录所在卷会把vfs_cur重置回虚拟根目录挂载点不存在则抛OSError(EINVAL)。在ports/unix上vfs.VfsPosix()直接映射宿主目录因此 import vfs, os vfs.mount(vfs.VfsPosix(/tmp), /host) os.listdir(/host)而典型裸机场景如 SD 卡的挂载、建目录、统计空间流程import os, vfs from machine import SD sd SD() vfs.mount(vfs.VfsFat(sd), /sd) os.chdir(/sd) os.mkdir(logs) with open(logs/run.txt, w) as f: f.write(hello) os.sync() # 确保落盘 s os.statvfs(/sd) print(free bytes:, s[0] * s[1] * s[3]) vfs.umount(/sd)六、综合示例把 UART 变成 REPL 并统计文件系统将本节要点串成一个完整的嵌入式调试场景——用第二路 UART 作为调试控制台同时观察文件系统状态import os from machine import UART, Pin # 1) 把 UART1 接入 REPL所有终端输出复制到 UARTUART 输入进入 REPL uart UART(1, 115200, txPin(4), rxPin(5)) prev os.dupterm(uart, 0) # 返回之前的对象首次为 None uart.irq(os.dupterm_notify, UART.IRQ_RX) # 及时处理 CtrlC # 2) 查看系统信息 u os.uname() print(u.sysname, u.version, u.machine) # 3) 检查/创建目录并统计空间 if data not in os.listdir(/): os.mkdir(/data) s os.statvfs(/data) print(free:, s[3] * s[0] * s[1], bytes) # 4) 恢复原终端 os.dupterm(prev, 0)七、小结与测试验证os模块虽小却是 MicroPython 设备端操作系统能力的入口uname/urandom提供系统信息与随机数文件系统函数经 VFS 层代理到任意可挂载文件系统FAT / littlefs / POSIX / 自定义 VFSdupterm家族让 REPL 能灵活迁移到 UART、蓝牙等流上mount/umount与Vfs*类则正逐步移交vfs模块。上述行为均有对应的测试用例可在本仓库验证tests/extmod/os_urandom.pyurandom的长度与ValueError行为tests/extmod/vfs_basic.py不依赖具体文件系统类型的挂载、listdir、chdir、stat、statvfs、跨文件系统重命名限制等完整行为矩阵tests/extmod/vfs_fat_ramdisk.pyFAT 文件系统上statvfs元组各字段的实际取值tests/basics/attrtuple2.pyos.uname()返回属性元组的可访问性。理解这些函数在 extmod/modos.c、extmod/vfs.c、extmod/os_dupterm.c 中的实现有助于你在移植新端口、编写自定义文件系统或排查 REPL 中断失效问题时快速定位到正确的宏开关与调用链。赞分享嵌入式语言运行时编程语言解释器编译器物联网系统编程【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址https://gitcode.com/gh_mirrors/mi/micropython点击查看免费下载相关推荐Serenity OS mount(2) 系统调用全解挂载文件系统、bind mount、remount 与不可变挂载Serenity OS mount 2 系统调用全解挂载文件系统、bind mount、remount 与不可变挂载 本文基于 Serenity OS 仓库中操作系统内核驱动Emscripten文件系统挂载多层文件系统联合技术Emscripten文件系统挂载多层文件系统联合技术 在WebAssemblyWasm应用开发中文件系统访问一直是痛点。传统浏览器环境缺乏原生文件系统支编译器WebAssembly开发工具构建工具reinstall3 条命令换掉 VPS 系统20 个 Linux 发行版加 Windows 都能装reinstall3 条命令换掉 VPS 系统20 个 Linux 发行版加 Windows 都能装 reinstall 是一键 VPS 系统重装脚本。一条嵌入式语言运行时编程语言解释器编译器物联网系统编程上一篇2025底层编程学习终极指南从零开始掌握lowlevelprogramming-university核心技能下一篇5分钟掌握猫抓浏览器资源嗅探工具让视频下载变简单创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考