ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

esp-iot-solution XZ 解压工具组件指南:基于 XZ Embedded 的嵌入式解压实战

esp-iot-solution XZ 解压工具组件指南:基于 XZ Embedded 的嵌入式解压实战 esp-iot-solution XZ 解压工具组件指南基于 XZ Embedded 的嵌入式解压实战【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution本文以 esp-iot-solution 仓库中的 xz 组件 为主体系统讲解如何在 ESP-IDF 项目中引入并调用xz_decompress()完成 XZ 格式数据的解压。该组件基于 XZ Embedded 精简解码库移植而来适用于 OTA 固件包解压、资源文件压缩存储等需要以极小内存开销换取高压缩比数据的嵌入式场景。读完本文你将掌握该组件的接入方式、xz_decompress的完整参数语义、四种流式调用模式以及配套示例的压缩生成与运行方法。组件概览面向资源受限设备的 XZ 解压能力xz 组件 是 esp-iot-solution 提供的一个工具型组件对外暴露唯一的公共 APIxz_decompress内部基于 XZ EmbeddedLinux 内核同源的轻量级 XZ 解码实现完成解压。从源码结构看该组件由三层构成公共接口层include/xz_decompress.h 声明唯一公共函数xz_decompress封装实现层src/xz_decompress.c 负责在 XZ Embedded 原生解码 API 之上做单次调用 / 多次调用的自动切换与错误处理XZ Embedded 内核xz-embedded/ 目录内含 Linux 与 userspace 两套移植其中linux/lib/xz下的xz_dec_stream.c、xz_dec_lzma2.c、xz_dec_bcj.c三个文件通过 CMakeLists.txt 直接参与编译。组件在 idf_component.yml 中声明版本为1.1.0要求 IDF 版本4.1并挂载了 xz_decompress_file 示例。快速接入两种方式把组件加入项目方式一命令行添加依赖与普通 ESP-IDF 组件一致最快捷的方式是在项目根目录执行idf.py add-dependency xz1.0.0方式二编写 manifest 文件也可以在主组件的idf_component.yml中手动声明依赖dependencies: espressif/xz: ^1.0.0两种方式等价均由 ESP-IDF 组件管理器idf-component-manager在构建时自动从 Espressif 组件仓库拉取。若希望跳过组件仓库、直接使用本仓库源码也可将 components/utilities/xz 目录整体放入项目的components/目录参与本地构建。核心 APIxz_decompress详解组件唯一公共接口定义在 include/xz_decompress.h其函数原型为int xz_decompress(unsigned char *in, int in_size, int (*fill)(void *dest, unsigned int size), int (*flush)(void *src, unsigned int size), unsigned char *out, int *in_used, void (*error)(const char *x));参数语义参数方向含义in输入指向待解压的压缩数据缓冲区若为NULL组件内部会按 4096 字节分块向fill回调索取数据in_size输入输入缓冲区字节数配合fill使用时初始值可传 0fill输入读取压缩数据的回调原型int (*)(void *dest, unsigned int size)返回实际填充的字节数返回负数表示读取失败flush输入写出解压数据的回调原型int (*)(void *src, unsigned int size)返回实际写出的字节数out输出存放解压结果的缓冲区若提供flush回调则可传NULLin_used输出解压实际消耗的输入字节数可为NULLerror输入错误信息输出回调接收一条描述性字符串返回值成功返回0失败返回-1。自动模式选择该函数实现了 Linux 内核linux/decompress/generic.h定义的解压接口语义。从 src/xz_decompress.c 可以看到它根据回调是否齐全自动选择底层解码模式当fill NULL flush NULL时走xz_dec_init(XZ_SINGLE, 0)单次调用模式——要求输入输出均为整块缓冲其余组合走xz_dec_init(XZ_DYNALLOC, (uint32_t)-1)多次调用模式——字典按需动态分配。四种调用模式从纯缓冲到纯流式示例 xz_decompress_file_example_main.c 完整演示了xz_decompress的四种参数组合覆盖了内存敏感度由低到高的全部场景。1. 缓冲到缓冲buf-to-buf输入输出都是完整内存块适合解压后数据量可预估的场景int ret xz_decompress((unsigned char *)xz_compressed_file_start, compressed_file_length, NULL, NULL, /* 不使用回调 */ (unsigned char *)out_buf, decompressed_count, error);注意注释中的提醒out_buf必须足够大以容纳全部解压结果。2. 缓冲到回调buf-to-cb输入是整块缓冲输出通过flush回调分块写出适合“压缩数据量已知、解压结果量未知”的场景例如边解压边写入存储分区static int flush(void *buf, unsigned int size) { return fwrite(buf, 1, size, stdout); // 示例中直接打印到终端 } int ret xz_decompress((unsigned char *)xz_compressed_file_start, compressed_file_length, NULL, flush, NULL, decompressed_count, error);3. 回调到回调cb-to-cb输入、输出均走回调数据以 4096 字节分块流转是最省内存的用法适合解压大文件时避免一次性占用过多 RAMstatic int fill(void *buf, unsigned int size) { uint32_t len (compressed_file_length - filled_length size) ? size : compressed_file_length - filled_length; if (len 0) { memcpy(buf, xz_compressed_file_start filled_length, len); filled_length len; } return len; } int ret xz_decompress(NULL, 0, fill, flush, NULL, decompressed_count, error);4. 回调到缓冲cb-to-buf输入走fill回调、输出写入整块缓冲。in参数此时需要提供一个缓冲区来承接fill填充的数据unsigned char *in_buf malloc(IO_BUFFER_LEN); unsigned char *out_buf malloc(IO_BUFFER_LEN); int ret xz_decompress(in_buf, 0, fill, NULL, out_buf, decompressed_count, error);模式选择建议解压结果可预估、一次性驻留内存可接受用buf-to-buf代码最简单数据源是内存缓冲、结果要写存储用buf-to-cb数据源和目的都是流式分区、文件、网络块用cb-to-cb内存占用恒定压缩源是流式、结果仍想整块使用用cb-to-buf。底层原理XZ Embedded 移植与 ESP32 适配解码器初始化与运行XZ Embedded 原生的三次调用模型为xz_dec_init → xz_dec_run → xz_dec_end。xz_decompress内部正是这一流程的封装初始化解码器后循环调用xz_dec_run(s, b)并通过struct xz_buf管理输入输出游标。完整定义见 xz-embedded/linux/include/linux/xz.h。在多次调用模式下封装层内部使用XZ_IOBUF_SIZE4096 字节要求 4 字节对齐作为输入/输出分块缓冲见 src/xz_decompress.c。三种操作模式enum xz_mode模式说明内存行为XZ_SINGLE单次调用一次解码整个流内存占用最小不会返回XZ_MEM_ERRORXZ_PREALLOC多次调用预分配 LZMA2 字典内存由dict_max预先决定运行期不再申请XZ_DYNALLOC多次调用字典按需分配可能返回XZ_MEM_ERRORxz_decompress内部使用XZ_SINGLE与XZ_DYNALLOC两种XZ_PREALLOC则通过公开的原生 API 由调用方直接使用。返回值enum xz_retxz_decompress把底层返回值收敛为 0/-1但底层状态码决定了错误信息内容XZ_OK一切正常继续喂数据XZ_STREAM_END解压成功结束对应返回值 0XZ_MEM_ERROR内存申请失败仅多调用模式XZ_FORMAT_ERROR输入不是 XZ 格式魔数错误XZ_OPTIONS_ERROR压缩参数如过滤器、校验类型不被支持XZ_DATA_ERROR/XZ_BUF_ERROR压缩数据损坏或无法推进。从 src/xz_decompress.c 可以看到每种错误对应的提示文案例如Input is not in the XZ format (wrong magic bytes)。面向 ESP 芯片的适配要点CRC32 硬件加速xz_crc32直接调用 ROM 函数esp_rom_crc32_le()见 src/xz_decompress.c并通过#define XZ_INTERNAL_CRC32 1启用内部 CRC 实现避免依赖外部的 crc32 符号内存宏映射port/include/xz_config.h 将内核的kmalloc/kfree/vmalloc/vfree统一映射到malloc/free使 XZ Embedded 源码无需改动即可在 ESP-IDF 的 heap 上运行C89 兼容对 MSVC 提供了bool/true/false/inline的兼容宏其余平台直接使用 C 标准库头文件。功能裁剪配置xz_config.h 以宏开关控制功能裁剪XZ_USE_CRC64取消注释启用 CRC64 校验支持默认关闭节省 ROM/RAMXZ_DEC_X86/XZ_DEC_POWERPC/XZ_DEC_IA64/XZ_DEC_ARM/XZ_DEC_ARMTHUMB/XZ_DEC_SPARC分别启用对应的 BCJ 分支跳转过滤器解码器默认全部关闭。需要注意若压缩端使用了组件未开启的过滤器或 CRC64 校验解压端会返回XZ_OPTIONS_ERROR。因此压缩时建议严格使用示例给出的参数见下节确保与默认配置匹配。实战示例xz_decompress_file示例结构examples/utilities/xz_decompress_file 目录下main/xz_decompress_file_example_main.c示例主程序演示五种用法test_file/hello.txt原始文本文件test_file/hello.txt.xz对应压缩文件编译时通过 CMake 的embed机制以二进制符号形式链接进固件示例通过_binary_hello_txt_xz_start/_end符号访问。生成压缩文件示例 README 给出了压缩命令需预先安装xz命令行工具xz --checkcrc32 --lzma2dict8KiB -k test_file/hello.txt关键参数说明--checkcrc32校验类型使用 CRC32组件默认只支持 CRC32XZ_USE_CRC64默认关闭因此必须这样指定--lzma2dict8KiBLZMA2 字典 8 KiB与嵌入式端内存承受能力匹配-k保留原文件避免压缩后原文件被删除。如需了解xz命令更多选项执行xz -h查看帮助。构建与运行在示例目录下执行idf.py -p PORT flash monitor退出串口监视器使用Ctrl-]。公开的原生分块 APIv1.1.0 起组件将 XZ Embedded 的多调用原生 API 一并公开见 CHANGELOG.md调用方可以直接用xz_dec_init / xz_dec_run / xz_dec_end精确控制内存。示例中的test_chunked_api()展示了典型用法——用XZ_PREALLOC指定 64 KB 字典1 16配合 4096 字节输入/输出缓冲循环驱动解码struct xz_dec *decoder xz_dec_init(XZ_PREALLOC, 1 16); // 64KB dictionary struct xz_buf buffer { .in in_buffer, .in_pos 0, .in_size 0, .out out_buffer, .out_pos 0, .out_size CHUNK_SIZE }; while (ret ! XZ_STREAM_END) { /* 分块填充 in_buffer ... */ ret xz_dec_run(decoder, buffer); /* 消费 buffer.out_pos 中的解压输出 ... */ } xz_dec_end(decoder);这种方式适合对 RAM 占用有硬性预算的 OTA 或资源解压任务。运行输出示例从 示例 README 可以确认预期的运行结果I (309) xz decompress: origin file size is 393, compressed file size is 93 bytes I (319) xz decompress: *****************test buf to buf begin**************** I (329) xz decompress: decompress data: Hello World!Hello Everyone! ... I (369) xz decompress: ret 0, decompressed count is 92 I (369) xz decompress: *****************test buf to buf end******************393 字节的文本被压缩到 93 字节解压后完整还原验证了组件在 ESP 平台上的可用性。版本演进与使用前提组件版本历史见 CHANGELOG.mdv1.1.02025-03-25公开 XZ Embedded 库的多调用原生 APIxz_dec_init等v1.0.12025-02-20修复xz_decompress的error回调原型错误v1.0.02023-02-10首个发布版本支持xz_decompress。使用前提与限制依赖 IDF4.1见 idf_component.yml默认仅支持 CRC32 校验与无 BCJ 过滤器的 XZ 流压缩端请使用xz --checkcrc32且不启用对应过滤器的参数该组件只提供解压能力不包含压缩实现压缩需在 PC 端用xz工具完成。综上xz 组件 以极简的公共 API 封装了成熟的 XZ Embedded 解码内核配合四种流式调用模式与可裁剪配置为 ESP 设备提供了一条低内存、高压缩率的解压路径可安全用于固件升级、资源打包等典型场景。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表