全网独一份!MicroPython 存储 + 文件系统底层原理,新手也能看懂的完整指南
1.MicroPython 的存储区域
在学习 MicroPython 的过程中,了解它的 “存储区域” 就像搞清楚我们的程序 “住” 在哪里、不同数据 “放” 在哪个柜子里,只有知道数据的存放规则,才能避免写出内存溢出、数据莫名出错的代码,也能理解程序运行的底层逻辑。
先补充两个新手必知的基础概念:
- Flash(闪存):可以理解成 “电脑的硬盘”,断电后数据不会丢,读写速度相对慢一点,适合存长期不变的内容。MicroPython 的固件、我们写的程序代码都会存在这里。
- SRAM(静态随机存取存储器):可以理解成 “电脑的内存条”,断电后数据就没了,但读写速度极快,适合存程序运行时临时要用、会频繁变化的数据。
MicroPython 的存储区域分布类似于传统编程语言(C/C++)的内存模型,核心分为 Flash(闪存)和 SRAM(静态随机存取存储器)两大块,每块包含不同功能的子区域,各司其职:
- Flash 里的内容像刻在光盘上的电影,一旦确定就不会随便修改,断电后数据依然保留,主要存储 “不会变的内容”:
- 代码区(Code Section):这里存储了程序代码,即字节码或编译后的机器码以及底层的解释器代码,它在运行时不变,不会被修改,属性为只读;
- 只读数据区(Read-Only Data Section):这里存放常量数据,比如字符串字面量(如
"hello MicroPython")、模块级别的常量变量(如模块开头定义的MAX_NUM = 100),数据在程序运行过程中不会被修改,属于静态内容,可以在整个程序运行期间重复使用( 比如你在程序里多次用到"hello"这个字符串,它只会在这个区域存一份,避免重复占用空间)。
- SRAM 像办公桌上的临时草稿纸,可随时修改,断电(如拔电源)后内容消失,主要存储程序运行时 “临时要用、会变化的内容”:
- 数据区(Data Section):存放 MicroPython 解释器的全局变量(整个程序中都能访问的变量),这些变量从程序启动时加载,直到程序结束(或设备断电)才消失。
- 你在程序最外层定义的
total = 0,这个total就存在数据区,无论在哪个函数里修改它,都是操作这个区域里的值。
- 你在程序最外层定义的
- 堆区(Heap Section):SRAM 中最灵活的区域,专门存储 MicroPython 的 “动态对象” 和动态分配的数据:比如列表(
[1,2,3])、字典({"name":"小明"})、自定义类的实例(如class Car: ...; my_car = Car()),以及函数内部的局部变量。- 解释器通过 “内存分配器” 从堆区按需分配空间(比如新建列表时,就从堆区划一块空间给这个列表);
- 自带 “垃圾回收器(GC)”,如果某个对象(如不用的列表)没有被任何代码引用,GC 会自动回收它占用的堆区空间,避免内存被占满。
- 栈区(Stack Section):专门处理函数调用相关的内容,比如递归函数调用、函数内的局部变量(如
def calc(): num=10; print(num)里的num)。- 栈的总大小有限(不同硬件的
SRAM容量不同,栈区配额也不同); - 栈大小随函数调用 / 返回动态调整:调用函数时,栈区为该函数的局部变量分配空间;函数执行完返回后,空间会被释放;
- 风险提示:若递归调用层数过多(如无限递归函数),栈区空间会被占满,触发 “栈溢出错误”,导致程序崩溃,就像草稿纸写满后,再写会溢出到桌子外一样。
- 栈的总大小有限(不同硬件的
- 数据区(Data Section):存放 MicroPython 解释器的全局变量(整个程序中都能访问的变量),这些变量从程序启动时加载,直到程序结束(或设备断电)才消失。
2.MicroPython 中的文件系统
2.1 文件系统的概念和组成结构
文件系统是操作系统用来管理存储介质(如硬盘、固态硬盘、闪存等)上文件的结构和方法,它负责文件的创建、读取、写入、删除以及目录的组织和管理,使得用户和应用程序能够以结构化的方式存取和管理数据。
你可以把 “文件系统” 理解成设备(比如 U 盘、嵌入式开发板的存储)用来存文件的 “整理规则”—— 就像你给抽屉定好 “哪层放文档、哪层放照片” 的规则,设备靠文件系统来管理 “文件存在哪、怎么找到它、怎么存更高效”。

通常情况下,文件系统具有以下功能:
- 文件管理:包括创建文件、读取文件、写入文件和删除文件等操作;
- 目录管理:包括创建目录、读取目录和删除目录等操作;
- 存储管理:包括为文件分配存储空间和跟踪存储使用等操作。
FAT 是其中一种简单易懂的文件系统(常用在嵌入式设备里),先补充一个新手必知的基础概念:
- 簇:文件系统存储数据的 “最小单位”:
- 把存储设备分成很多大小一致的 “小格子”,每个格子就是一个簇;
- 一个文件会占用 1 个或多个 “小格子”(簇),哪怕文件很小,也会占至少 1 个簇。
以 FAT 文件系统为例,一个完整的文件系统通常由以下部分组成:

文件系统将磁盘空间划分为若干个簇,以便于管理和组织存储的数据,簇(Cluster)是一个基本的存储单位,每个簇包含一个或多个扇区(Sector),而每个扇区是存储设备中最小的存储单元。簇的大小在不同的文件系统和存储设备上可能不同,对于 FAT12/FAT16 来说,簇的大小通常为 512 字节、1KB、2KB 或 4KB
- 引导扇区(Boot Sector):文件系统的 “说明书”,对应图里的 “引导扇区” 区域,它是存储设备的 “第一份信息”,像抽屉的 “使用说明书”,里面记录了:
- 文件系统类型(是 FAT12/FAT16 还是 FAT32);
- 每个簇占多少空间、FAT 表的位置、根目录的大小(对应图里 Boot Sector 里的 “FAT type、FAT size、Root Directory size”)。
- 设备启动时,先读这个 “说明书”,才知道怎么识别后面的文件。
- 目录表(Directory Table):文件的 “清单列表”,对应图里的 “Root Directory(根目录表)”,它是存储设备的 “文件清单”,记录了每个文件的关键信息:
- 文件名(比如图里的
tyui.jpg、mes.doc); - 文件大小(比如
tyui.jpg是 1400B); - 文件存在哪个簇里(“起始簇号”,比如
tyui.jpg从簇 2 开始存); - 你要找文件时,先查这份 “清单”,就能知道 “文件叫啥、多大、从哪个簇开始找”。
- 文件名(比如图里的
- 文件分配表(FAT):簇的 “去向地图”,对应图里的 “FATs” 区域,它是一张 “簇的关系表”(可以理解为数组),因为一个文件可能占多个簇(比如大文件),FAT 会记录 “每个簇的下一个簇是谁”:
- 表中的每个条目对应一个簇,值的含义是:
0x0000:这个簇是空的(可用);0xFFFF:这个簇是文件的最后一个簇(结束标记);0xFF7F:这个簇是坏的(不能存数据)。
tyui.jpg的起始簇是 2:- 看 FAT 里 “2 对应的是 3”;
- 簇 2 的下一个簇是 3;
- “3 对应的是 4”;
- 簇 3 的下一个簇是 4;
- “4 对应的是 0xFFFF”;
- 簇 4 是最后一个簇。所以
tyui.jpg存在簇 2、3、4 里。
mes.doc的起始簇是 5:- FAT 里 “5 对应 6”;
- 簇 5 的下一个是 6;
- “6 对应 0xFFFF”
- 结束。所以
mes.doc存在簇 5、6 里。
- 表中的每个条目对应一个簇,值的含义是:
- 数据区(Data Area):文件的 “实际存放区”,对应图里的 “Data Area”,是存储设备里真正放文件内容的地方,所有文件的实际数据(比如
tyui.jpg的图片内容、mes.doc的文档内容)都存在这里的簇里。- 前面的 “清单” 和 “地图” 都是辅助,真正的文件内容就存在这些簇里。
常见的文件系统类型包括 FAT(FAT12、FAT16 和 FAT32)、NTFS、ext 和 LittleFS 等,其中 FAT 文件系统是嵌入式设备常用的文件系统,具有设计简单,易于实现和理解和开销小等特点,但是:
- FAT 系统支持的最大文件大小较小(比如 FAT16 最大只支持 2GB 文件);;
- 同时在使用过程中可能会产生碎片化(文件存的时候东一个簇、西一个簇,找起来变慢),影响性能;
- 并且没有内置的权限(谁都能改文件)和安全机制,对数据的保护较弱(文件坏了难恢复)。
在 MicroPython 中,最常用的文件系统是 FAT、LittleFS v1 和 LittleFS v2 这三种文件系统,对比如下:

2.2 VFS 虚拟文件系统
先补 2 个新手必懂的基础概念,帮你快速理解 VFS:
- 抽象层:可以理解成 “统一翻译官”,不管底层是啥 “方言”(不同文件系统),它都转换成一套 “通用语言”(统一的操作方法)给你用。
- 块设备:存储设备的 “通用称呼”(比如 SD 卡、开发板自带的闪存),这类设备是按固定大小的 “块” 来读写数据的,是文件系统的 “载体”。
在 MicroPython 中,VFS(Virtual File System,虚拟文件系统)是一个用于在嵌入式设备上提供文件系统支持的模块,它是一个抽象层,提供统一的文件系统接口:
- 使得应用程序可以通过相同的 API 访问不同类型的底层文件系统(如 FAT、SPIFFS、LittleFS 等),而应用程序无需关心底层文件系统的具体实现;
- 简单来说就是,不管你用的是 SD 卡的 FAT 系统、开发板自带的 LittleFS 系统,VFS 都给你一套一模一样的操作方法(比如存文件、读文件),不用因为换了存储设备就重新学新命令。
并且,用户可以将不同类型的文件系统挂载到特定的路径,并在需要时卸载它们:你可以把 “挂载” 理解成给存储设备 “安个入口”—— 比如把 SD 卡 “接” 到系统里的 /sd 文件夹下,之后只要访问 /sd 就能操作 SD 卡;“卸载” 则是安全地 “拔掉” 这个入口,避免数据损坏。
例如,我们可以将一个 SD 卡的 FAT 文件系统挂载到 /sd,同时将一个 SPIFFS 文件系统挂载到 /spiffs,并通过统一的文件操作接口进行文件管理;通过 VFS 模块,我们也可以在软件层面创建一个块设备(按块操作读写的设备),用于模拟存储设备的行为,例如可以在嵌入式系统或操作系统中创建一个虚拟的 RAM 块设备。
VFS 提供了如下文件系统挂载与卸载方法:
vfs.mount(fsobj, mount_point, *, readonly):给存储设备 “安入口”- 描述:把一个文件系统对象(比如 FAT/LittleFS),“挂” 到系统里的某个路径下(比如
/sd),之后就能通过这个路径操作存储设备。 - 参数大白话:
fsobj:要挂载的文件系统对象(比如后面会讲的 FAT/LittleFS 对象),或者直接填块设备(比如 SD 卡的对象)。mount_point:“入口路径”—— 比如用'/'代表系统根目录,用'/sd'代表 SD 卡的专属入口。readonly(可选):选True的话,这个存储设备只能读不能改;选False(默认)可以读写。
- 异常提示:如果这个 “入口路径” 已经被别的设备占了(比如
/sd已经挂了另一个 SD 卡),会报错OSError(EPERM)。
- 描述:把一个文件系统对象(比如 FAT/LittleFS),“挂” 到系统里的某个路径下(比如
vfs.umount(mount_point):安全 “拔入口”- 描述:把之前挂载的文件系统 “卸下来”,比如用完 SD 卡后卸载,避免直接拔卡丢数据。
- 参数:填要卸载的 “入口路径”(比如
'/sd'),或者直接填之前挂载的文件系统对象。 - 异常提示:如果填的 “入口路径” 根本没挂载过设备,会报错
OSError(EINVAL)。
VFS 只是 “总管”,得先创建对应类型的文件系统对象(比如 FAT/LittleFS),才能挂载使用。下面是常用的文件系统类(对应你提供的类说明)。
以下是文件系统实现类,可以实现构建 FAT、LittleFS v1、LittleFS v2 等文件系统:


如下所示:
vfs.VfsFat(block_dev):创建 FAT 文件系统对象- 作用:生成一个用 FAT 格式管理存储的对象(比如 SD 卡常用 FAT 格式),
block_dev是要管理的块设备(比如 SD 卡对象)。 -
mkfs方法:这是个 “格式化” 功能 —— 比如vfs.VfsFat.mkfs(sd_dev),就是把 SD 卡(sd_dev)格式化成 FAT 文件系统,之后才能存文件。
- 作用:生成一个用 FAT 格式管理存储的对象(比如 SD 卡常用 FAT 格式),
vfs.VfsLfs1(block_dev, ...)/vfs.VfsLfs2(...):创建 LittleFS 文件系统对象- LittleFS 是嵌入式设备常用的 “轻量文件系统”(比 FAT 更适合小闪存),分 v1 和 v2 两个版本:
- 作用:生成用 LittleFS 格式管理存储的对象,
block_dev是对应的块设备(比如开发板自带的闪存)。 - 参数(可选):
readsize/progsize等是读写 / 写入的块大小(新手用默认值32就行);v2 版本的mtime参数是用来记录文件修改时间的。 -
mkfs方法:比如vfs.VfsLfs2.mkfs(flash_dev),就是把开发板闪存(flash_dev)格式化成 LittleFS v2 系统。
- 作用:生成用 LittleFS 格式管理存储的对象,
vfs.VfsPosix(root=None):访问电脑的文件系统(仅调试用)- 作用:在电脑上运行 MicroPython 时,用来访问电脑本身的文件系统(比如电脑的 C 盘、D 盘),
root填电脑里的路径(比如'C:/test'),不填的话默认用当前文件夹。
- 作用:在电脑上运行 MicroPython 时,用来访问电脑本身的文件系统(比如电脑的 C 盘、D 盘),
下表显示了默认情况下不同芯片中的 MicroPython 固件中包含的文件系统:

2.3 块设备
文件系统建立在块设备之上,块设备是一种存储设备,它将存储空间划分为固定大小的块,并允许对这些块进行随机访问,即每个块都有一个唯一的地址,可以独立地进行读写操作;简单来说,块设备通过块来存储数据,文件系统将这些块组织成文件和目录,使用户可以方便地访问和管理数据:
- 它把存储空间分成很多大小一致的 “块”(比如每个块 1KB),每个块有唯一的 “逻辑块地址”(图里的 0、1、2、3…);
- 读写数据时,直接指定 “块地址” 就能操作对应块 —— 比如图里写数据到地址 3 的块、读地址 8 的块,不用按顺序从 0 开始翻,想操作哪个块直接找它的编号就行。
- 文件系统(比如 FAT、LittleFS)就是把这些 “块” 组织成文件 / 目录的 —— 比如一个文件可能占块 3、块 4、块 5,文件系统帮你记录 “这个文件对应哪些块”。


MicroPython 没有提供块设备的操作方法,但是提供了一个抽象的块设备接口 vfs.AbstractBlockDev 类,这个模板规定了块设备必须实现的方法(比如 “读某个块的数据”“写数据到某个块”),相当于 “考试答题卡的格式”只有按模板写代码,MicroPython 才能识别这是个块设备,进而在它上面建文件系统。
实际的块设备类必须实现下面描述的方法:


在学习 MicroPython 的过程中,了解它的 “存储区域” 就像搞清楚我们的程序 “住” 在哪里、不同数据 “放” 在哪个柜子里,只有知道数据的存放规则,才能避免写出内存溢出、数据莫名出错的代码,也能理解程序运行的底层逻辑。
浙公网安备 33010602011771号