<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>运行时架构 on Tech Snippets - 嵌入式技术笔记</title><link>https://tech-snippets.xyz/tags/%E8%BF%90%E8%A1%8C%E6%97%B6%E6%9E%B6%E6%9E%84/</link><description>Recent content in 运行时架构 on Tech Snippets - 嵌入式技术笔记</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sat, 19 Sep 2026 17:44:29 +0800</lastBuildDate><atom:link href="https://tech-snippets.xyz/tags/%E8%BF%90%E8%A1%8C%E6%97%B6%E6%9E%B6%E6%9E%84/index.xml" rel="self" type="application/rss+xml"/><item><title>动态扩展运行时架构研究：elf_loader 基座架构与 ESP-Brookesia 对比</title><link>https://tech-snippets.xyz/posts/elf-loader-base-architecture-vs-esp-brookesia-2026/</link><pubDate>Sat, 19 Sep 2026 17:44:29 +0800</pubDate><guid>https://tech-snippets.xyz/posts/elf-loader-base-architecture-vs-esp-brookesia-2026/</guid><description>基于源码逐文件阅读与构建产物实测，对比 elf_loader 基座架构与 ESP-Brookesia 两种动态扩展运行时方案在 ESP32-S3 上的实现差异，并给出可借鉴项与验证计划。</description><content:encoded><![CDATA[<table>
<thead>
<tr>
<th>项</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>文档版本</td>
<td>v1.0</td>
</tr>
<tr>
<td>日期</td>
<td>2026-09-19</td>
</tr>
<tr>
<td>研究范围</td>
<td>ESP32-S3 平台上的动态扩展/多语言运行时机制</td>
</tr>
<tr>
<td>结论来源</td>
<td>源码逐文件阅读 + 构建产物实测（<code>.so</code> 段表/符号表解析、固件 map 归因）</td>
</tr>
</tbody>
</table>
<h2 id="依据说明重要">依据说明（重要）</h2>
<ul>
<li>文中所有<strong>事实性结论</strong>均标注出处 <code>文件路径:行号</code>。</li>
<li>无法从现有源码/产物直接确认的，标注 <code>【推断】</code>。</li>
<li>尚未核对、需要后续确认的，标注 <code>【待核实】</code>。</li>
<li><strong>路径基准</strong>：除特别说明外，路径相对于 <code>bs_hmi_base_s3/</code>，即
<code>[project_root]/</code>。</li>
<li>Brookesia 源码全部位于 <code>so_build/ref/</code>。</li>
<li>本文档<strong>不含推测性评价</strong>；涉及&quot;建议&quot;的部分集中在第 4 章，且均给出依据。</li>
</ul>
<hr>
<h2 id="目录">目录</h2>
<ul>
<li><a href="#0-%E7%BB%93%E8%AE%BA%E9%80%9F%E8%A7%88">0. 结论速览</a></li>
<li><a href="#1-elf_loader-%E5%9F%BA%E5%BA%A7%E6%9E%B6%E6%9E%84">1. elf_loader 基座架构</a>
<ul>
<li><a href="#11-%E5%85%A8%E8%B2%8C">1.1 全貌</a></li>
<li><a href="#12-%E5%9F%BA%E5%BA%A7%E5%9B%BA%E4%BB%B6bs_hmi_base_s3">1.2 基座固件</a></li>
<li><a href="#13-elf-%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD%E5%B1%82elf_loader">1.3 ELF 动态加载层</a></li>
<li><a href="#14-%E7%AC%A6%E5%8F%B7%E4%B8%8E%E5%AE%BF%E4%B8%BB%E8%83%BD%E5%8A%9B%E5%AF%BC%E5%87%BAelf_ext">1.4 符号与宿主能力导出</a></li>
<li><a href="#15-lua-%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B1%82lua_engineso">1.5 Lua 运行时层</a></li>
<li><a href="#16-%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98%E6%95%B0%E6%8D%AE%E9%80%9A%E9%81%93">1.6 共享内存数据通道</a></li>
<li><a href="#17-%E5%8C%85%E5%88%86%E5%8F%91%E4%B8%8E%E5%8A%A0%E5%AF%86">1.7 包分发与加密</a></li>
<li><a href="#18-%E5%85%B3%E9%94%AE%E6%8C%87%E6%A0%87%E5%AE%9E%E6%B5%8B">1.8 关键指标实测</a></li>
<li><a href="#19-elf_loader-%E5%9F%BA%E5%BA%A7%E6%9E%B6%E6%9E%84%E7%89%B9%E5%BE%81%E6%80%BB%E7%BB%93">1.9 特征总结</a></li>
</ul>
</li>
<li><a href="#2-esp-brookesia-%E6%9E%B6%E6%9E%84">2. ESP-Brookesia 架构</a>
<ul>
<li><a href="#21-%E7%BB%84%E4%BB%B6%E5%85%A8%E6%99%AF">2.1 组件全景</a></li>
<li><a href="#22-%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B1%82runtime_manager">2.2 运行时层</a></li>
<li><a href="#23-%E5%9B%9B%E4%B8%AA%E5%90%8E%E7%AB%AF">2.3 四个后端</a></li>
<li><a href="#24-%E6%9C%8D%E5%8A%A1%E5%B1%82service_manager--helper--agent">2.4 服务层</a></li>
<li><a href="#25-%E7%B3%BB%E7%BB%9F%E5%B1%82system_core">2.5 系统层</a></li>
<li><a href="#26-hal-%E5%B1%82">2.6 HAL 层</a></li>
<li><a href="#27-%E6%97%A7%E7%BA%BF-esp-brookesia-050">2.7 旧线 esp-brookesia 0.5.0</a></li>
<li><a href="#28-wamr-%E5%9C%A8-esp-idf--esp32-s3-%E4%B8%8A%E7%9A%84%E9%9B%86%E6%88%90%E4%BA%8B%E5%AE%9E">2.8 WAMR 集成事实</a></li>
<li><a href="#29-%E8%90%BD%E5%9C%B0%E9%97%A8%E6%A7%9B">2.9 落地门槛</a></li>
<li><a href="#210-brookesia-%E7%89%B9%E5%BE%81%E6%80%BB%E7%BB%93">2.10 特征总结</a></li>
</ul>
</li>
<li><a href="#3-%E5%AF%B9%E6%AF%94%E5%88%86%E6%9E%90">3. 对比分析</a>
<ul>
<li><a href="#31-%E6%A0%B9%E6%9C%AC%E5%B7%AE%E5%BC%82%E6%8A%BD%E8%B1%A1%E6%94%BE%E5%9C%A8%E5%93%AA%E4%B8%80%E5%B1%82">3.1 抽象位置</a></li>
<li><a href="#32-%E5%88%86%E5%B1%82%E5%9B%BE%E5%AF%B9%E7%85%A7">3.2 分层图对照</a></li>
<li><a href="#33-%E9%80%90%E7%BB%B4%E5%BA%A6%E5%AF%B9%E6%AF%94">3.3 维度对比表</a></li>
<li><a href="#34-lua-%E5%B1%82%E7%9A%84%E5%AE%9A%E4%BD%8D%E5%B7%AE%E5%BC%82%E9%87%8D%E7%82%B9">3.4 Lua 层定位差异</a></li>
<li><a href="#35-%E5%8F%8C%E6%96%B9%E5%BC%BA%E9%A1%B9%E5%BC%B1%E9%A1%B9%E6%B8%85%E5%8D%95">3.5 强项弱项</a></li>
</ul>
</li>
<li><a href="#4-%E5%8F%AF%E5%80%9F%E9%89%B4%E9%A1%B9%E4%B8%8E%E9%AA%8C%E8%AF%81%E8%AE%A1%E5%88%92">4. 可借鉴项与验证计划</a></li>
<li><a href="#5-%E9%99%84%E5%BD%95">5. 附录</a>
<ul>
<li><a href="#51-%E4%BE%9D%E6%8D%AE%E7%B4%A2%E5%BC%95">5.1 依据索引</a></li>
<li><a href="#52-%E5%BE%85%E6%A0%B8%E5%AE%9E%E6%B8%85%E5%8D%95">5.2 待核实清单</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="0-结论速览">0. 结论速览</h2>
<table>
<thead>
<tr>
<th>结论</th>
<th>依据</th>
</tr>
</thead>
<tbody>
<tr>
<td>elf_loader 基座架构是<strong>层级式</strong>：<code>elf_loader</code> 是唯一执行基座，Lua 是运行在其中一个 <code>.so</code> 内的内容</td>
<td><code>so_build/lua_engine/CMakeLists.txt</code>、<code>components/elf_loader/src/esp_elf.c</code></td>
</tr>
<tr>
<td>Brookesia 是<strong>对等式</strong>：ELF/Lua/JS/WASM 四个平级后端，共享一套宿主契约</td>
<td><code>brookesia_runtime_manager/include/brookesia/runtime_manager/backend.hpp:19-64</code></td>
</tr>
<tr>
<td>elf_loader 基座的加载链路<strong>强于</strong>官方 ELF 后端（加密、符号白名单、host call）</td>
<td>对比见 3.3；官方证据 <code>brookesia_runtime_elf/src/backend.cpp:101-104, 266-281</code></td>
</tr>
<tr>
<td><code>lua_engine</code>（跑在基座上的 Lua 层）定位更接近官方 <strong>system_core（应用服务器）</strong>，而非 <code>runtime_lua</code>（脚本容器）</td>
<td>对比见 3.4</td>
</tr>
<tr>
<td>Brookesia v0.8 全栈<strong>无法在 IDF 5.5.4 落地</strong>，硬门槛是 <code>idf: &gt;=6.0,&lt;=6.2</code></td>
<td><code>brookesia_lib_utils/idf_component.yml:8</code></td>
</tr>
<tr>
<td>WASM 方向的关键未知项（AOT 代码落点）已确认：S3 开 PSRAM 时 AOT 进 PSRAM</td>
<td><code>wasm-micro-runtime/core/shared/platform/esp-idf/shared_platform.cmake:18-22</code>、<code>espidf_memmap.c:20-51</code></td>
</tr>
<tr>
<td><code>lua_engine.so</code> 已完成 <code>-Os</code> + 元数据段裁剪，体积 553,048 → 257,972 B（-53.4%）</td>
<td>本文 1.8 节实测数据</td>
</tr>
</tbody>
</table>
<hr>
<h1 id="1-elf_loader-基座架构">1. elf_loader 基座架构</h1>
<blockquote>
<p><strong>命名说明</strong>：本文档用 <strong>&ldquo;elf_loader 基座架构&rdquo;</strong> 指代我们当前的实现（基座固件 + <code>elf_loader</code> + <code>.so</code> + Lua），
而不使用&quot;我方架构&quot;这类表述。原因有二：</p>
<ol>
<li>它描述的是<strong>架构形态</strong>（单一 ELF 执行基座）而非归属，便于与 Brookesia 的&quot;多后端对等&quot;形态直接对照；</li>
<li>Brookesia 的 <code>runtime_elf</code> 后端<strong>同样复用官方 <code>espressif/elf_loader</code></strong>（<code>ref/brookesia_runtime_elf/idf_component.yml:5-7</code>），
若用&quot;我方&quot;会掩盖&quot;同一个 loader、两种用法&quot;这一关键对照点。</li>
</ol>
<p>后文对比表格中该列简称为 <strong>&ldquo;elf_loader 基座&rdquo;</strong>。</p>
</blockquote>
<h2 id="11-全貌">1.1 全貌</h2>
<figure>
<svg width="920" height="560" viewBox="0 0 920 560" xmlns="http://www.w3.org/2000/svg">
<defs><linearGradient id="d1-bg" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#111827"/><stop offset="100%" stop-color="#1f2937"/></linearGradient><marker id="d1-ar" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#38bdf8"/></marker></defs>
<rect width="920" height="560" fill="url(#d1-bg)" rx="16"/><text x="460.0" y="34" text-anchor="middle" fill="#facc15" font-family="Arial,sans-serif" font-size="18" font-weight="bold">elf_loader 基座架构总览</text><rect x="210" y="60" width="500" height="190" rx="10" fill="#172554" stroke="#60a5fa" stroke-width="2"/><text x="460" y="90" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">基座固件 bs_hmi_base_s3</text><text x="460" y="112" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">（ESP32-S3 / ESP-IDF 5.5.4）</text><line x1="230" y1="124" x2="690" y2="124" stroke="#334155" stroke-width="1"/><text x="230" y="148" text-anchor="start" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">LVGL / lcd_ui / arduino-esp32 / esp-fs-webserver ...</text><text x="230" y="168" text-anchor="start" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">shared_memory 组件（区域表 + 字段布局）</text><text x="230" y="188" text-anchor="start" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">elf_loader 组件（ELF 加载 + 重定位 + 解密回调）</text><text x="230" y="208" text-anchor="start" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">elf_ext 组件（符号导出 + .so 调度 + 动态加载器）</text><text x="230" y="228" text-anchor="start" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">LFS 分区（lfs_storage 7MB）：.so / 脚本 / 资源</text><path d="M460 250 L460 296" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d1-ar)"/><text x="475" y="280" text-anchor="start" fill="#94a3b8" font-family="Arial,sans-serif" font-size="11">esp_elf_init / relocate / request</text><path d="M460 250 L137 300" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d1-ar)"/><rect x="40" y="300" width="195" height="95" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="137" y="334" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">lua_engine.so</text><text x="137" y="360" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">内含 Lua VM</text><path d="M460 250 L352 300" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d1-ar)"/><rect x="255" y="300" width="195" height="95" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="352" y="334" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">ui_mirror.so</text><text x="352" y="360" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">WebSocket 镜像</text><path d="M460 250 L567 300" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d1-ar)"/><rect x="470" y="300" width="195" height="95" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="567" y="334" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">bs_link_hmi.so</text><text x="567" y="360" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">总线 / OTA</text><path d="M460 250 L782 300" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d1-ar)"/><rect x="685" y="300" width="195" height="95" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="782" y="334" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">其他 .so</text><text x="782" y="360" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">HMI 等</text><path d="M137 395 L137 452" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d1-ar)"/><rect x="30" y="452" width="330" height="78" rx="10" fill="#172554" stroke="#60a5fa" stroke-width="2"/><text x="195" y="483" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">执行 .lua 脚本（作业模型）</text><text x="195" y="508" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">脚本经 shm 与基座 / 其他 .so 交换数据</text><figcaption style="text-align:center;color:#888;font-size:12px;margin-top:8px;">图 1.1　elf_loader 基座架构全貌：.so 是唯一的扩展单元，Lua 解释器运行在 .so 内部，脚本经共享内存与基座交换数据。</figcaption>
</svg>
</figure>
<p><strong>核心特征</strong>：<code>.so</code> 是唯一的扩展单元；脚本（Lua）不直接由基座执行，而是由运行在 <code>.so</code> 内的解释器执行。</p>
<p>依据：</p>
<ul>
<li><code>so_build/lua_engine/CMakeLists.txt:154-155</code> 的自定义链接命令（<code>-shared -fPIC -nostdlib -nostartfiles -Wl,--allow-shlib-undefined</code>）</li>
<li><code>components/elf_loader/src/esp_elf.c:127</code>（读文件到 PSRAM）、<code>:432-442</code>（pdata 分配）</li>
<li><code>components/elf_ext/src/elf_so_loader.c:247-283</code>（<code>dlsym(&quot;app_main&quot;)</code> → 起任务）</li>
</ul>
<h2 id="12-基座固件bs_hmi_base_s3">1.2 基座固件（bs_hmi_base_s3）</h2>
<h3 id="121-平台与关键配置">1.2.1 平台与关键配置</h3>
<table>
<thead>
<tr>
<th>配置</th>
<th>值</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>目标芯片</td>
<td>esp32s3</td>
<td><code>sdkconfig.defaults:1</code></td>
</tr>
<tr>
<td>IDF 版本</td>
<td>5.5.4</td>
<td><code>_run_build.bat:4</code>（<code>IDF_PATH=[idf_path]/</code>）</td>
</tr>
<tr>
<td>ELF 加载到 PSRAM</td>
<td><code>CONFIG_ELF_LOADER_LOAD_PSRAM=y</code></td>
<td><code>sdkconfig:2394</code></td>
</tr>
<tr>
<td>总线地址镜像</td>
<td><code>CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR=y</code></td>
<td><code>sdkconfig:2389</code></td>
</tr>
<tr>
<td>Cache 偏移</td>
<td><code>CONFIG_ELF_LOADER_CACHE_OFFSET=y</code></td>
<td><code>sdkconfig:2393</code></td>
</tr>
<tr>
<td>libc 符号表</td>
<td><code>CONFIG_ELF_LOADER_LIBC_SYMBOLS=y</code></td>
<td><code>sdkconfig:2399</code></td>
</tr>
<tr>
<td>IDF 符号表</td>
<td><code>CONFIG_ELF_LOADER_ESPIDF_SYMBOLS=y</code></td>
<td><code>sdkconfig:2400</code></td>
</tr>
<tr>
<td>符号表预分配数</td>
<td><code>CONFIG_ELF_LOADER_NUMBER_SYMBOLS=32</code></td>
<td><code>sdkconfig:2402</code></td>
</tr>
<tr>
<td>PSRAM malloc</td>
<td><code>CONFIG_SPIRAM_USE_MALLOC=y</code></td>
<td><code>sdkconfig:1279</code></td>
</tr>
<tr>
<td>PSRAM BSS 段</td>
<td><code>CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y</code></td>
<td><code>sdkconfig:1284</code></td>
</tr>
<tr>
<td>编译优化</td>
<td><code>CONFIG_COMPILER_OPTIMIZATION_SIZE=y</code></td>
<td><code>sdkconfig:654</code></td>
</tr>
<tr>
<td>断言</td>
<td><code>CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y</code>，LEVEL=2</td>
<td><code>sdkconfig:657,662</code></td>
</tr>
<tr>
<td>日志等级</td>
<td><code>CONFIG_LOG_DEFAULT_LEVEL=3</code>（INFO），<code>MAXIMUM=3</code></td>
<td><code>sdkconfig:1683,1687</code></td>
</tr>
</tbody>
</table>
<h3 id="122-分区">1.2.2 分区</h3>
<table>
<thead>
<tr>
<th>分区</th>
<th>类型</th>
<th>偏移</th>
<th>大小</th>
</tr>
</thead>
<tbody>
<tr>
<td>nvs</td>
<td>data/nvs</td>
<td>0x9000</td>
<td>0x4000</td>
</tr>
<tr>
<td>otadata</td>
<td>data/ota</td>
<td>0xd000</td>
<td>0x2000</td>
</tr>
<tr>
<td>phy_init</td>
<td>data/phy</td>
<td>0xf000</td>
<td>0x1000</td>
</tr>
<tr>
<td>lfs_storage</td>
<td>data/littlefs</td>
<td>0x10000</td>
<td><strong>0x700000（7 MB）</strong></td>
</tr>
<tr>
<td>ota_0</td>
<td>app/ota_0</td>
<td>0x710000</td>
<td>0x400000（4 MB）</td>
</tr>
<tr>
<td>ota_1</td>
<td>app/ota_1</td>
<td>0xB10000</td>
<td>0x400000（4 MB）</td>
</tr>
</tbody>
</table>
<p>出处：<code>partitions.csv:1-7</code></p>
<h3 id="123-构建产物规模实测">1.2.3 构建产物规模（实测）</h3>
<table>
<thead>
<tr>
<th>指标</th>
<th>值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>app bin</td>
<td>2,106,112 B（2056.75 KB）</td>
<td><code>build/bs_hmi_base_s3.bin</code></td>
</tr>
<tr>
<td><code>.flash.text</code></td>
<td>1,359,624 B</td>
<td>代码（IROM）</td>
</tr>
<tr>
<td><code>.flash.rodata</code></td>
<td>653,092 B</td>
<td>只读数据（DROM）</td>
</tr>
<tr>
<td><code>.iram0.text</code></td>
<td>69,423 B</td>
<td>内部 RAM 代码</td>
</tr>
<tr>
<td><code>.iram0.vectors</code></td>
<td>1,028 B</td>
<td>中断向量</td>
</tr>
<tr>
<td><code>.dram0.data</code></td>
<td>22,544 B</td>
<td>内部 RAM 数据</td>
</tr>
<tr>
<td><code>.dram0.bss</code></td>
<td>30,816 B</td>
<td>内部 RAM 零初始化</td>
</tr>
<tr>
<td><code>.ext_ram.bss</code></td>
<td>122,436 B</td>
<td>PSRAM 零初始化段</td>
</tr>
</tbody>
</table>
<p>出处：<code>build/bs_hmi_base_s3.map</code> 输出段统计（解析脚本 <code>build/analyze_map.py</code>）</p>
<h3 id="124-组件级-flash-占用-top实测归因">1.2.4 组件级 flash 占用 Top（实测归因）</h3>
<table>
<thead>
<tr>
<th>组件</th>
<th style="text-align:right">flash.text</th>
<th style="text-align:right">flash.rodata</th>
<th style="text-align:right">合计</th>
</tr>
</thead>
<tbody>
<tr>
<td>lvgl</td>
<td style="text-align:right">230,740</td>
<td style="text-align:right">136,141</td>
<td style="text-align:right">366,881</td>
</tr>
<tr>
<td>esp_wifi</td>
<td style="text-align:right">227,570</td>
<td style="text-align:right">43,950</td>
<td style="text-align:right">272,685</td>
</tr>
<tr>
<td>esp_app_format</td>
<td style="text-align:right">479</td>
<td style="text-align:right">227,504</td>
<td style="text-align:right"><strong>227,983</strong>（见下方说明）</td>
</tr>
<tr>
<td>esp-fs-webserver</td>
<td style="text-align:right">42,028</td>
<td style="text-align:right">166,617</td>
<td style="text-align:right">208,645</td>
</tr>
<tr>
<td>lwip</td>
<td style="text-align:right">109,692</td>
<td style="text-align:right">17,483</td>
<td style="text-align:right">127,175</td>
</tr>
<tr>
<td>arduino-esp32</td>
<td style="text-align:right">69,777</td>
<td style="text-align:right">23,189</td>
<td style="text-align:right">92,966</td>
</tr>
<tr>
<td>elf_ext</td>
<td style="text-align:right">5,588</td>
<td style="text-align:right">87,232</td>
<td style="text-align:right">92,820</td>
</tr>
<tr>
<td>lcd_ui</td>
<td style="text-align:right">21,070</td>
<td style="text-align:right">43,490</td>
<td style="text-align:right">64,560</td>
</tr>
<tr>
<td>mbedtls</td>
<td style="text-align:right">50,024</td>
<td style="text-align:right">12,240</td>
<td style="text-align:right">62,344</td>
</tr>
<tr>
<td>wpa_supplicant</td>
<td style="text-align:right">54,085</td>
<td style="text-align:right">1,980</td>
<td style="text-align:right">56,065</td>
</tr>
<tr>
<td>mdns</td>
<td style="text-align:right">39,907</td>
<td style="text-align:right">5,449</td>
<td style="text-align:right">45,356</td>
</tr>
<tr>
<td>esp_hw_support</td>
<td style="text-align:right">22,918</td>
<td style="text-align:right">9,070</td>
<td style="text-align:right">42,375</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>关于 <code>esp_app_format</code> 的 227,983 B</strong>：该数字挂在 <code>esp_app_desc.c.obj</code> 名下，但该源文件仅 5,394 B（<code>[idf_path]//components/esp_app_format/esp_app_desc.c</code>）。实际读取固件 rodata 后确认，这是<strong>全工程 <code>.rodata.str1.1</code> 合并字符串池</strong>（SHF_MERGE 段的 map 归属特性）。池内容实测：227,496 B / 7,746 条字符串，其中日志格式串合计 62,477 B（<code>E (%lu)</code> 978 条、<code>W (%lu)</code> 74 条、<code>I (%lu)</code> 138 条、<code>[%6u][E]</code> 170 条、<code>I (%d)</code> 101 条）、<code>ESP_ERR_*</code> 223 条、LVGL 断言串（<code>lv_obj_*</code> 137 条、<code>lv_style_*</code> 111 条）、断言文件路径（<code>//IDF/components/*</code>）78 条共 6,648 B。
出处：<code>build/bs_hmi_base_s3.map:115809-115810</code>（<code>.rodata.__esp_system_init_fn_init_show_app_info.str1.1</code> = <code>0x378a8</code>）、ELF <code>.flash.rodata</code> 起始内容解析。</p>
</blockquote>
<h2 id="13-elf-动态加载层elf_loader">1.3 ELF 动态加载层（elf_loader）</h2>
<h3 id="131-内存分配策略决定性">1.3.1 内存分配策略（决定性）</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// components/elf_loader/src/esp_elf_adapter.c:29-51
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="o">*</span><span class="nf">esp_elf_malloc</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">n</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">exec</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="cp">#ifdef CONFIG_ELF_LOADER_LOAD_PSRAM
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>    <span class="n">caps</span> <span class="o">=</span> <span class="n">MALLOC_CAP_SPIRAM</span> <span class="o">|</span> <span class="n">MALLOC_CAP_8BIT</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="cp">#else
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>    <span class="n">caps</span> <span class="o">=</span> <span class="n">MALLOC_CAP_EXEC</span> <span class="o">/</span> <span class="n">MALLOC_CAP_8BIT</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>    <span class="n">caps</span> <span class="o">|=</span> <span class="n">MALLOC_CAP_CACHE_ALIGNED</span><span class="p">;</span>   <span class="c1">// IDF &gt;= 5.3
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">return</span> <span class="nf">heap_caps_malloc</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">caps</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>因为基座开了 <code>CONFIG_ELF_LOADER_LOAD_PSRAM=y</code>，<strong><code>.so</code> 的 text 与 data（含 bss）全部从 PSRAM 分配</strong>。</p>
<h3 id="132-加载流程">1.3.2 加载流程</h3>
<table>
<thead>
<tr>
<th>步骤</th>
<th>行为</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>打开</td>
<td>读整个 <code>.so</code> 文件到 PSRAM（<code>size</code> 字节一块）</td>
<td><code>esp_elf.c:127-131</code></td>
</tr>
<tr>
<td>解密</td>
<td>若注册了 <code>esp_elf_decrypt_cb</code>，原地解密 <code>ELFC</code> 格式（AES-256-CTR）</td>
<td><code>esp_elf.c:53, 148-153</code></td>
</tr>
<tr>
<td>保留 payload</td>
<td><code>file-&gt;payload = pbuf; file-&gt;size = size;</code></td>
<td><code>esp_elf.c:155-156</code></td>
</tr>
<tr>
<td>分配代码</td>
<td><code>elf-&gt;ptext = esp_elf_malloc(text_size, true)</code></td>
<td><code>esp_elf.c:425</code></td>
</tr>
<tr>
<td>分配数据</td>
<td><code>elf-&gt;pdata = esp_elf_malloc(DATA+RODATA+BSS+DRLRO, false)</code>（<strong>一整块</strong>）</td>
<td><code>esp_elf.c:432-442</code></td>
</tr>
<tr>
<td>段拷贝</td>
<td>各节按 <code>sec[].size</code> 拷入 <code>ptext</code>/<code>pdata</code></td>
<td><code>esp_elf.c:445-512</code></td>
</tr>
<tr>
<td>释放文件缓冲</td>
<td>relocate 成功后立即 <code>esp_elf_close(&amp;file)</code></td>
<td><code>dlmod.c:251</code></td>
</tr>
<tr>
<td>执行入口</td>
<td><code>dlsym(handle, &quot;app_main&quot;)</code> → <code>elf_task_create()</code> 起任务</td>
<td><code>elf_so_loader.c:247-283</code></td>
</tr>
</tbody>
</table>
<p><strong>要点</strong>：<code>.so</code> 文件缓冲只是<strong>加载期峰值</strong>，不常驻（<code>dlmod.c:251</code>）。<code>lua_engine.so</code> 当前 257,972 B，即单次加载峰值约 252 KB PSRAM。</p>
<h3 id="133-任务与栈">1.3.3 任务与栈</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// components/elf_ext/src/elf_task_api.c:111,115
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">core_id</span><span class="p">,</span> <span class="n">MALLOC_CAP_SPIRAM</span> <span class="o">|</span> <span class="n">MALLOC_CAP_8BIT</span>   <span class="c1">// .so 入口任务栈默认放 PSRAM
</span></span></span></code></pre></div><p>出处：<code>elf_ext/include/elf_task_api.h:58</code>（文档：&ldquo;默认用 PSRAM (MALLOC_CAP_SPIRAM) 分配任务栈&rdquo;）</p>
<h3 id="134-崩溃保护">1.3.4 崩溃保护</h3>
<p><code>elf_so_loader.c:166-170</code>：<code>s_dynamic_loading_enabled</code> 为假时拒绝加载（crash loop protection）。</p>
<h2 id="14-符号与宿主能力导出elf_ext">1.4 符号与宿主能力导出（elf_ext）</h2>
<h3 id="141-机制">1.4.1 机制</h3>
<p>基座在<strong>编译期</strong>从指定静态库用 <code>nm</code> 抽取符号，生成 <code>generated/&lt;name&gt;_syms.c</code>，由 <code>elf_sym_register.c</code> 在启动时注册进 ELF 符号表。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// components/elf_ext/src/elf_tab_syms.c:188-192（部分）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">ESP_ELFSYM_EXPORT</span><span class="p">(</span><span class="n">heap_caps_malloc</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"><span class="nf">ESP_ELFSYM_EXPORT</span><span class="p">(</span><span class="n">heap_caps_calloc</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"><span class="nf">ESP_ELFSYM_EXPORT</span><span class="p">(</span><span class="n">heap_caps_get_free_size</span><span class="p">),</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// components/elf_ext/src/elf_sym_register.c:55
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">(</span><span class="kt">esp_elf_symbol_table_t</span> <span class="o">*</span><span class="p">)</span><span class="n">s_tables</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
</span></span></code></pre></div><p>符号表宏与容器：<code>so_build/lua_engine/elf_api/include/private/elf_symbol.h:24-34</code>（<code>ESP_ELFSYM_EXPORT</code> / <code>esp_elfsym</code> / <code>ESP_ELFSYM_END</code>）</p>
<h3 id="142-符号表清单21-张">1.4.2 符号表清单（21 张）</h3>
<p>出处：<code>components/elf_ext/CMakeLists.txt:74-95</code></p>
<pre tabindex="0"><code>gpio, uart, lfs, log, freertos, wifi, netif, event, nvs, lvgl, lcd,
libgcc, libm, newlib, ping, mdns, i2c, mcpwm, syshal, vfs
</code></pre><p>生成方式：<code>components/elf_ext/CMakeLists.txt:97-160</code>（<code>symbols.py -t l -i &lt;lib.a&gt; -of gen_&lt;name&gt;_syms.c</code>）
过滤机制：<code>components/elf_ext/tools/filter_syms.py</code>（支持 <code>--drop-pattern</code>，如对 netif 过滤 <code>esp_netif_action_</code>、<code>_unsafe$</code>、<code>_api$</code> 等）</p>
<h3 id="143-关键特性">1.4.3 关键特性</h3>
<table>
<thead>
<tr>
<th>特性</th>
<th>说明</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>白名单裁剪</strong></td>
<td>只有清单里的库 + 过滤规则通过的符号才导出</td>
<td><code>CMakeLists.txt:74-95</code>、<code>filter_syms.py</code></td>
</tr>
<tr>
<td><strong>编译期确定</strong></td>
<td>新增宿主 API 需重跑 CMake 生成 + 重编基座</td>
<td>同上</td>
</tr>
<tr>
<td>符号可插拔解析</td>
<td><code>elf_set_symbol_resolver</code> 支持自定义 resolver</td>
<td><code>elf_api/include/private/elf_symbol.h:66-124</code></td>
</tr>
<tr>
<td>运行时注册</td>
<td><code>esp_elf_register_symbol</code> / <code>esp_elf_unregister_symbol</code> / <code>esp_elf_find_symbol</code></td>
<td><code>elf_api/include/esp_elf.h:155-177</code></td>
</tr>
</tbody>
</table>
<h2 id="15-lua-运行时层lua_engineso">1.5 Lua 运行时层（lua_engine.so）</h2>
<h3 id="151-组成">1.5.1 组成</h3>
<p>构建源集合（<code>so_build/lua_engine/CMakeLists.txt:160-188</code>）：</p>
<table>
<thead>
<tr>
<th>分组</th>
<th>来源</th>
</tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td><code>main/*.c</code></td>
</tr>
<tr>
<td>Lua 解释器</td>
<td><code>components/georgik__lua/lua/*.c</code>（排除 <code>lua.c</code> / <code>onelua.c</code>）</td>
</tr>
<tr>
<td>引擎</td>
<td><code>components/lua_engine/src/*.c</code></td>
</tr>
<tr>
<td>引擎核心</td>
<td><code>components/lua_engine_core/src/*.c</code></td>
</tr>
<tr>
<td>I2C 驱动</td>
<td><code>components/espressif__i2c_bus/i2c_bus_v2.c</code></td>
</tr>
<tr>
<td>内置模块</td>
<td><code>lua_mods/lua_module_{storage,json,i2c,gpio,mcpwm,esp_heap,system,crc16,shared_memory}/src/*.c</code></td>
</tr>
</tbody>
</table>
<p>Lua 版本：<strong>5.5</strong>（<code>so_build/lua_engine/components/georgik__lua/lua/lua.h:20-22</code>：<code>LUA_VERSION_MAJOR_N 5</code> / <code>MINOR 5</code> / <code>RELEASE 0</code>）</p>
<h3 id="152-引擎能力源码事实">1.5.2 引擎能力（源码事实）</h3>
<table>
<thead>
<tr>
<th>能力</th>
<th>位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>PSRAM 分配器</td>
<td><code>components/lua_engine/src/lua_runtime.c:183-223</code></td>
<td><code>lua_psram_allocator</code>，<code>MALLOC_CAP_SPIRAM</code></td>
</tr>
<tr>
<td>Lua 状态创建</td>
<td><code>lua_runtime.c:699</code></td>
<td><code>lua_newstate(lua_psram_allocator, ...)</code></td>
</tr>
<tr>
<td>输出缓冲</td>
<td><code>lua_runtime.c:684</code>（<code>LUA_OUTPUT_BUFFER_SIZE</code>）、<code>lua_async.c:286</code>（<code>LUA_OUTPUT_BUF_SIZE</code>）</td>
<td>PSRAM</td>
</tr>
<tr>
<td>异步作业</td>
<td><code>components/lua_engine/src/lua_async.c</code></td>
<td>作业槽位、互斥组、状态机、停止请求</td>
</tr>
<tr>
<td>启动日志</td>
<td><code>components/lua_engine/src/lua_bootlog.c</code></td>
<td>4 KB 缓冲 + vprintf hook 捕获 E 级日志 + 文件轮转</td>
</tr>
<tr>
<td>自启动</td>
<td><code>components/lua_engine/src/lua_autorun.c</code></td>
<td>解析 <code>autorun.ini</code>（<code>delay</code> / <code>loadui</code> / 脚本指令）</td>
</tr>
<tr>
<td>脚本管理</td>
<td><code>lua_script.c:186,216</code></td>
<td>列表读写在 PSRAM</td>
</tr>
<tr>
<td>字节码</td>
<td><code>lua_bytecode.c:65</code></td>
<td>校验缓冲显式用内部 RAM</td>
</tr>
<tr>
<td>模块注册表</td>
<td><code>lua_engine_core.c:20-29</code></td>
<td><code>s_modules[32]</code></td>
</tr>
<tr>
<td>共享内存绑定</td>
<td><code>lua_mods/lua_module_shared_memory/src/lua_module_shared_memory_lua.c:820-831</code></td>
<td>导出 <code>get/create/read/write/list/wait_for/read_typed/write_typed/layout/read_struct/write_struct</code></td>
</tr>
<tr>
<td>模块清单</td>
<td><code>components/lua_engine/src/lua_modules.c:468</code></td>
<td><code>shared_memory</code> 模块描述：&ldquo;读写与基座共享的内存区域（bat_ch_data 等电池模拟器数据结构）&rdquo;</td>
</tr>
</tbody>
</table>
<h3 id="153-静态数据落点">1.5.3 静态数据落点</h3>
<p><code>.so</code> 的 <code>.data/.rodata/.bss/.data.rel.ro</code> 被 <code>esp_elf_malloc(..., false)</code> 整块分配到 <strong>PSRAM</strong>（见 1.3.1），因此：</p>
<ul>
<li><code>s_jobs[LUA_ASYNC_MAX_JOBS]</code> 4,480 B → PSRAM</li>
<li><code>g_log_buffer</code> 4,112 B → PSRAM</li>
<li><code>instructions[20]</code> 1,680 B → PSRAM</li>
<li>全部 <code>.bss</code> 11,612 B / <code>.data</code> 2,696 B → PSRAM</li>
</ul>
<blockquote>
<p><strong>注意</strong>：源码中这些变量标注了 <code>EXT_RAM_BSS_ATTR</code>（<code>lua_async.c:95-98</code>、<code>lua_bootlog.c:87,613</code>），但该宏在本 <code>.so</code> 编译环境中展开为空（<code>so_build/lua_engine/build/config/sdkconfig.h</code> 中不存在 <code>CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY</code>），所以落的是普通 <code>.bss</code>。<strong>当前不影响结果</strong>（loader 统一放 PSRAM），但语义上名不副实。</p>
</blockquote>
<p><strong>刻意保留在内部 RAM 的少数</strong>（有源码注释依据）：</p>
<table>
<thead>
<tr>
<th>位置</th>
<th>内容</th>
<th>依据</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>lua_async.c:1256-1257</code></td>
<td><code>s_job_lock_buf</code>（<code>StaticSemaphore_t</code> + 128 B）</td>
<td>注释：&ldquo;必须在 init 时用 heap_caps_malloc(MALLOC_CAP_INTERNAL) 显式分配&rdquo;</td>
</tr>
<tr>
<td><code>lua_async.c:1273-1274</code></td>
<td><code>s_slot_sem_buf</code></td>
<td>同上</td>
</tr>
<tr>
<td><code>lua_bootlog.c:54-55</code></td>
<td>fs 互斥量缓冲</td>
<td><code>MALLOC_CAP_INTERNAL</code></td>
</tr>
<tr>
<td><code>lua_bytecode.c:65</code></td>
<td>字节码校验缓冲</td>
<td><code>MALLOC_CAP_INTERNAL</code></td>
</tr>
<tr>
<td><code>lua_autorun.c:447</code></td>
<td>auto_start 任务栈</td>
<td>注释：&ldquo;必须从内部RAM分配栈&rdquo;</td>
</tr>
</tbody>
</table>
<h3 id="154-编译与裁剪现状">1.5.4 编译与裁剪现状</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl"><span class="c"># so_build/lua_engine/CMakeLists.txt:150-152
</span></span></span><span class="line"><span class="cl"><span class="c"># -Os：手工调用编译器绕过了 IDF 默认编译选项，不加优化会按 -O0 编译，
</span></span></span><span class="line"><span class="cl"><span class="c">#      导致 .text/.rela.dyn/.got 显著膨胀（见 release 目录 .so 体积分析）。
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="nb">set</span><span class="p">(</span><span class="s">so_compile_flags</span> <span class="s">-c</span> <span class="s">-fPIC</span> <span class="s">-Os</span> <span class="s">-ffunction-sections</span> <span class="s">-fdata-sections</span><span class="p">)</span><span class="err">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl"><span class="c"># so_build/lua_engine/CMakeLists.txt:222-226
</span></span></span><span class="line"><span class="cl"><span class="c"># .xt.prop / .xt.lit 是 Xtensa relaxation 元数据（非 ALLOC），链接完成后
</span></span></span><span class="line"><span class="cl"><span class="c"># 无任何作用，占成品 .so 约 1/3 体积，直接移除（PT_LOAD 内容不受影响）。
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="err">COMMAND</span> <span class="err">${CMAKE_STRIP_SO}</span> <span class="err">--strip-unneeded</span> <span class="err">-R</span> <span class="err">.comment</span> <span class="err">-R</span> <span class="err">.note
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    <span class="err">-R</span> <span class="err">.xt.prop</span> <span class="err">-R</span> <span class="err">.xt.lit
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    <span class="err">${so_output}
</span></span></span></code></pre></div><p>其它 <code>.so</code> 工程（<code>bs_link_hmi</code>、<code>ui_mirror</code>、<code>terminal</code>、<code>bs_link_scpi</code>、<code>bs_hmi_320x240</code>）在同一次优化中做了相同改动（各自 <code>CMakeLists.txt</code> 的 <code>so_compile_flags</code> 与 strip 命令）。</p>
<h2 id="16-共享内存数据通道">1.6 共享内存数据通道</h2>
<h3 id="161-组件实现基座侧">1.6.1 组件实现（基座侧）</h3>
<table>
<thead>
<tr>
<th>能力</th>
<th>API</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>创建区域（幂等）</td>
<td><code>shared_mem_create</code></td>
<td><code>components/shared_memory/src/shared_memory.c:105-165</code></td>
</tr>
<tr>
<td>查询区域</td>
<td><code>shared_mem_get</code></td>
<td><code>shared_memory.c:167-177</code></td>
</tr>
<tr>
<td>等待区域</td>
<td><code>shared_mem_wait_for</code></td>
<td><code>shared_memory.h:150-158</code></td>
</tr>
<tr>
<td>登记字段布局</td>
<td><code>shared_mem_set_layout</code></td>
<td><code>shared_memory.c:348-372</code>（<strong>深拷贝到 PSRAM</strong>）</td>
</tr>
<tr>
<td>查询字段布局</td>
<td><code>shared_mem_get_layout</code></td>
<td><code>shared_memory.c:375-382</code></td>
</tr>
<tr>
<td>销毁</td>
<td><code>shared_mem_destroy</code></td>
<td><code>shared_memory.c:207</code>（<strong>全工程无调用点</strong>，见下）</td>
</tr>
</tbody>
</table>
<h3 id="162-布局登记链路">1.6.2 布局登记链路</h3>
<figure>
<svg width="760" height="470" viewBox="0 0 760 470" xmlns="http://www.w3.org/2000/svg">
<defs><linearGradient id="d2-bg" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#111827"/><stop offset="100%" stop-color="#1f2937"/></linearGradient><marker id="d2-ar" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#38bdf8"/></marker></defs>
<rect width="760" height="470" fill="url(#d2-bg)" rx="16"/><text x="380.0" y="34" text-anchor="middle" fill="#facc15" font-family="Arial,sans-serif" font-size="18" font-weight="bold">布局登记链路</text><rect x="120" y="60" width="520" height="60" rx="10" fill="#172554" stroke="#60a5fa" stroke-width="2"/><text x="380" y="97" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">bs_hmi_1ch_{480x272,320x240}/main/main.c</text><path d="M380 120 L380 160" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d2-ar)"/><rect x="120" y="160" width="520" height="60" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="380" y="197" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">create_shared_regions()　→　shared_mem_create × 7</text><path d="M380 220 L380 260" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d2-ar)"/><rect x="120" y="260" width="520" height="60" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="380" y="297" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">bat_state_layout_register()　（state_layout.c:103-132）</text><path d="M380 320 L380 360" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d2-ar)"/><rect x="120" y="360" width="520" height="60" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="380" y="397" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">shared_mem_set_layout(region, fields, count)　× 7 个区域</text><figcaption style="text-align:center;color:#888;font-size:12px;margin-top:8px;">图 1.2　布局登记链路：main.c 入口 → 创建 7 个共享内存区域 → 逐个注册布局 → 字段落表。</figcaption>
</svg>
</figure>
出处：`so_build/bs_hmi_1ch_480x272/main/main.c:58-70`、`so_build/bs_hmi_1ch_480x272/main/state_layout.c:103-132`
<p>已登记的 7 个区域与字段数：<code>bat_ch_data</code>(9)、<code>bat_ch_cfg</code>(10)、<code>bat_dev_state</code>(7)、<code>bat_ota_state</code>(12)、<code>bat_pending_fw</code>(4)、<code>bat_fps</code>(1)、<code>bat_mode_slots</code>(6)
出处：<code>state_layout.c:27-117</code></p>
<h3 id="163-lua-侧读取路径">1.6.3 Lua 侧读取路径</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// lua_module_shared_memory_lua.c:573-592
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">shared_mem_region_t</span><span class="o">*</span> <span class="n">region</span> <span class="o">=</span> <span class="nf">shared_mem_get</span><span class="p">(</span><span class="n">name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="nf">shared_mem_get_layout</span><span class="p">(</span><span class="n">region</span><span class="p">,</span> <span class="n">out_fields</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">count</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="nf">lua_pushnil</span><span class="p">(</span><span class="n">L</span><span class="p">);</span> <span class="nf">lua_pushfstring</span><span class="p">(</span><span class="n">L</span><span class="p">,</span> <span class="s">&#34;No layout registered for &#39;%s&#39;&#34;</span><span class="p">,</span> <span class="n">name</span><span class="p">);</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> <span class="p">}</span>
</span></span></code></pre></div><p><strong>关键约束</strong>：<code>layout</code> / <code>read_struct</code> / <code>write_struct</code> 依赖<strong>已有登记</strong>；Lua 侧没有 <code>set_layout</code> API（<code>lua_module_shared_memory_lua.c:820-831</code> 的导出清单中无登记接口）。因此若设备上未运行带 <code>state_layout.c</code> 的 HMI <code>.so</code>，这三个接口必然返回 <code>nil</code>。</p>
<p><code>shared_mem_destroy</code> 在整个 <code>bs_hmi_base_s3/</code> 内<strong>只有定义、没有调用</strong>（检索结果），<code>shared_mem_create</code> 同名幂等（<code>shared_memory.c:127-136</code>），所以区域一旦创建，其 <code>layout</code> 不会被销毁路径清掉。</p>
<h2 id="17-包分发与加密">1.7 包分发与加密</h2>
<table>
<thead>
<tr>
<th>项</th>
<th>实现</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>加密格式</td>
<td><code>[4B &quot;ELFC&quot;] [16B IV] [AES-256-CTR 数据]</code></td>
<td><code>so_build/lua_engine/CMakeLists.txt:242-246</code></td>
</tr>
<tr>
<td>加密工具</td>
<td><code>so_build/lua_engine/tools/encrypt_so.py</code></td>
<td>同上</td>
</tr>
<tr>
<td>解密时机</td>
<td><code>esp_elf_open()</code> 中原地解密</td>
<td><code>so_build/lua_engine/CMakeLists.txt:245</code>、<code>components/elf_loader/src/esp_elf.c:53,148-153</code></td>
</tr>
<tr>
<td>解密密钥注册</td>
<td><code>elf_so_crypt.c</code> 启动时注册</td>
<td><code>components/elf_ext/src/elf_so_crypt.c:109</code></td>
</tr>
<tr>
<td>发布产物</td>
<td>调试期 <code>.so</code> 明文；正式 <code>.epm</code> 加密</td>
<td><code>so_build/lua_engine/CMakeLists.txt:232-254</code></td>
</tr>
<tr>
<td>加密后仍未启用</td>
<td>该段 CMake 代码当前被注释</td>
<td><code>so_build/lua_engine/CMakeLists.txt:248-254</code></td>
</tr>
</tbody>
</table>
<p>LFS 分发：<code>lfs_storage</code> 分区 7 MB（<code>partitions.csv:5</code>），<code>.so</code>/脚本/资源经该分区下发（<code>multi-partition-lfs</code> 组件）。</p>
<h2 id="18-关键指标实测">1.8 关键指标实测</h2>
<h3 id="181-lua_engineso-优化前后">1.8.1 <code>lua_engine.so</code> 优化前后</h3>
<table>
<thead>
<tr>
<th>阶段</th>
<th style="text-align:right">文件大小</th>
<th style="text-align:right">PT_LOAD memsz 合计</th>
</tr>
</thead>
<tbody>
<tr>
<td>原始（默认 -O0，含 Xtensa 元数据）</td>
<td style="text-align:right">553,048 B（540.1 KB）</td>
<td style="text-align:right">392,208 B（383.0 KB）</td>
</tr>
<tr>
<td>+ <code>-Os</code></td>
<td style="text-align:right">385,060 B（376.0 KB）</td>
<td style="text-align:right">268,784 B（262.5 KB）</td>
</tr>
<tr>
<td>+ 移除 <code>.xt.prop</code> / <code>.xt.lit</code></td>
<td style="text-align:right"><strong>257,972 B（251.9 KB）</strong></td>
<td style="text-align:right">268,784 B（262.5 KB）</td>
</tr>
<tr>
<td>累计变化</td>
<td style="text-align:right"><strong>-295,076 B（-53.4%）</strong></td>
<td style="text-align:right"><strong>-123,424 B（-31.5%）</strong></td>
</tr>
</tbody>
</table>
<h3 id="182-当前-so-段构成257972-b">1.8.2 当前 <code>.so</code> 段构成（257,972 B）</h3>
<table>
<thead>
<tr>
<th>段</th>
<th style="text-align:right">字节</th>
<th style="text-align:right">占比</th>
<th>属性</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>.text</code></td>
<td style="text-align:right">162,062</td>
<td style="text-align:right">62.8%</td>
<td>ALLOC（代码）</td>
</tr>
<tr>
<td><code>.rela.dyn</code></td>
<td style="text-align:right">31,944</td>
<td style="text-align:right">12.4%</td>
<td>ALLOC（动态重定位 2,662 项）</td>
</tr>
<tr>
<td><code>.rodata</code></td>
<td style="text-align:right">26,835</td>
<td style="text-align:right">10.4%</td>
<td>ALLOC</td>
</tr>
<tr>
<td><code>.dynstr</code></td>
<td style="text-align:right">8,820</td>
<td style="text-align:right">3.4%</td>
<td>ALLOC</td>
</tr>
<tr>
<td><code>.dynsym</code></td>
<td style="text-align:right">8,720</td>
<td style="text-align:right">3.4%</td>
<td>ALLOC（545 个动态符号）</td>
</tr>
<tr>
<td><code>.got.loc</code></td>
<td style="text-align:right">6,104</td>
<td style="text-align:right">2.4%</td>
<td>ALLOC</td>
</tr>
<tr>
<td><code>.rela.plt</code></td>
<td style="text-align:right">5,364</td>
<td style="text-align:right">2.1%</td>
<td>ALLOC</td>
</tr>
<tr>
<td><code>.hash</code></td>
<td style="text-align:right">4,272</td>
<td style="text-align:right">1.7%</td>
<td>ALLOC</td>
</tr>
<tr>
<td><code>.data.rel.ro</code></td>
<td style="text-align:right">2,632</td>
<td style="text-align:right">1.0%</td>
<td>ALLOC</td>
</tr>
<tr>
<td><code>.bss</code></td>
<td style="text-align:right">11,632</td>
<td style="text-align:right">0（不占文件）</td>
<td>ALLOC</td>
</tr>
<tr>
<td>其余（<code>.dynamic</code>/<code>.data</code>/<code>.got</code>/<code>.xtensa.info</code>/<code>.shstrtab</code>）</td>
<td style="text-align:right">587</td>
<td style="text-align:right">0.2%</td>
<td>—</td>
</tr>
</tbody>
</table>
<p>PT_LOAD 两段：<code>off=0 filesz=254,272 memsz=254,272 (R+X)</code>、<code>off=254,272 filesz=2,876 memsz=14,512 (RW)</code></p>
<h3 id="183--os-后各模块体积code--rodata--data--198001-b">1.8.3 <code>-Os</code> 后各模块体积（code + rodata + data = 198,001 B）</h3>
<table>
<thead>
<tr>
<th>模块</th>
<th style="text-align:right">新值</th>
<th style="text-align:right">旧值（-O0）</th>
<th style="text-align:right">降幅</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lua 解释器（<code>georgik__lua/lua</code>）</td>
<td style="text-align:right">124,034</td>
<td style="text-align:right">202,588</td>
<td style="text-align:right">-38.8%</td>
</tr>
<tr>
<td>lua_engine 引擎</td>
<td style="text-align:right">39,981</td>
<td style="text-align:right">56,216</td>
<td style="text-align:right">-28.9%</td>
</tr>
<tr>
<td>i2c_bus 驱动</td>
<td style="text-align:right">6,295</td>
<td style="text-align:right">10,281</td>
<td style="text-align:right">-38.8%</td>
</tr>
<tr>
<td>9 个内置模块合计</td>
<td style="text-align:right">25,828</td>
<td style="text-align:right">35,378</td>
<td style="text-align:right">-27.0%</td>
</tr>
<tr>
<td>engine_core + main</td>
<td style="text-align:right">1,863</td>
<td style="text-align:right">2,562</td>
<td style="text-align:right">-27.3%</td>
</tr>
</tbody>
</table>
<h3 id="184-静态对象清单从-o-符号表统计so-已-strip">1.8.4 静态对象清单（从 <code>.o</code> 符号表统计，<code>.so</code> 已 strip）</h3>
<table>
<thead>
<tr>
<th>符号</th>
<th style="text-align:right">大小</th>
<th>来源</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>s_jobs</code></td>
<td style="text-align:right">4,480</td>
<td><code>lua_async.c:96</code></td>
</tr>
<tr>
<td><code>g_log_buffer</code></td>
<td style="text-align:right">4,112</td>
<td><code>lua_bootlog.c:87</code></td>
</tr>
<tr>
<td><code>instructions[20]</code></td>
<td style="text-align:right">1,680</td>
<td><code>lua_autorun.c:63</code></td>
</tr>
<tr>
<td><code>script_list[256]</code></td>
<td style="text-align:right">256</td>
<td><code>lua_bootlog.c:613</code></td>
</tr>
<tr>
<td><code>s_modules[32]</code></td>
<td style="text-align:right">256</td>
<td><code>lua_engine_core.c:27</code></td>
</tr>
<tr>
<td><code>s_base_dir</code></td>
<td style="text-align:right">256</td>
<td><code>lua_engine_main.c</code></td>
</tr>
<tr>
<td><code>s_i2c_bus</code></td>
<td style="text-align:right">184</td>
<td><code>i2c_bus_v2.c</code></td>
</tr>
<tr>
<td><code>.bss</code> 合计 / <code>.data</code> 合计</td>
<td style="text-align:right">11,612 / 2,696</td>
<td>—</td>
</tr>
</tbody>
</table>
<h2 id="19-elf_loader-基座架构特征总结">1.9 elf_loader 基座架构特征总结</h2>
<table>
<thead>
<tr>
<th>特征</th>
<th>描述</th>
<th>依据</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>单一执行基座</strong></td>
<td>所有扩展必须编译成 ELF <code>.so</code>，由 <code>elf_loader</code> 加载</td>
<td>1.1 节</td>
</tr>
<tr>
<td><strong>层级组合</strong></td>
<td>Lua 运行在 <code>lua_engine.so</code> 内（Lua VM 是 <code>.so</code> 的内容）</td>
<td>1.5.1</td>
</tr>
<tr>
<td><strong>符号层抽象</strong></td>
<td>宿主能力以编译期生成的 C 符号白名单表达</td>
<td>1.4</td>
</tr>
<tr>
<td><strong>编译期耦合</strong></td>
<td>新增宿主 API 需重新生成符号表并重编基座</td>
<td>1.4.3</td>
</tr>
<tr>
<td><strong>单向调用</strong></td>
<td><code>.so</code> → 基座（<code>app_main</code> 入口 + 符号调用）；无基座 → <code>.so</code> 内部函数的反向调用通道</td>
<td><code>elf_so_loader.c:247-283</code>、1.4</td>
</tr>
<tr>
<td><strong>PSRAM 优先</strong></td>
<td><code>.so</code> 的 text/data/bss 全部 PSRAM 分配；任务栈默认 PSRAM</td>
<td>1.3.1、1.3.3</td>
</tr>
<tr>
<td><strong>端到端加密</strong></td>
<td><code>.epm</code> = AES-256-CTR，加载时原地解密</td>
<td>1.7</td>
</tr>
<tr>
<td><strong>有状态隔离缺失</strong></td>
<td><code>lua_engine</code> 单实例 + 作业槽位模型，无&quot;多 app&quot;概念</td>
<td><code>lua_async.c</code> 作业模型（1.5.2）</td>
</tr>
<tr>
<td><strong>跨实例数据通道</strong></td>
<td>共享内存 + 字段布局（登记制）</td>
<td>1.6</td>
</tr>
</tbody>
</table>
<hr>
<h1 id="2-esp-brookesia-架构">2. ESP-Brookesia 架构</h1>
<blockquote>
<p>以下内容全部来自 <code>so_build/ref/</code> 下的源码。</p>
</blockquote>
<h2 id="21-组件全景">2.1 组件全景</h2>
<h3 id="211-组件与版本16-个目录">2.1.1 组件与版本（16 个目录）</h3>
<table>
<thead>
<tr>
<th>组件</th>
<th>版本</th>
<th>CHANGELOG 最新</th>
<th>职责</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>brookesia_lib_utils</code></td>
<td>0.8.2</td>
<td>2026-07-22</td>
<td>基础工具：TaskScheduler(Boost.Asio)、Log、StateMachine、PluginRegistry、signal/slot、describe_helpers</td>
</tr>
<tr>
<td><code>brookesia_service_manager</code></td>
<td>0.8.2</td>
<td>2026-07-22</td>
<td>服务框架：ServiceBase + Function/Event Registry + 绑定 + 拓扑排序</td>
</tr>
<tr>
<td><code>brookesia_service_helper</code></td>
<td>0.8.5</td>
<td>2026-09-10</td>
<td>纯头文件契约层（CRTP 类型安全包装）</td>
</tr>
<tr>
<td><code>brookesia_service_wifi</code></td>
<td>0.8.2</td>
<td>2026-07-27</td>
<td>WiFi 服务实现（服务模板范例）</td>
</tr>
<tr>
<td><code>brookesia_agent_manager</code></td>
<td>0.8.2</td>
<td>2026-07-27</td>
<td>Agent 生命周期/状态机/多后端选择</td>
</tr>
<tr>
<td><code>brookesia_runtime_manager</code></td>
<td>0.8.2</td>
<td>2026-07-27</td>
<td>运行时门面 + IRuntimeBackend 抽象</td>
</tr>
<tr>
<td><code>brookesia_runtime_elf</code></td>
<td>0.8.2</td>
<td>2026-07-27</td>
<td>ELF 后端（复用 IDF <code>elf_loader</code>）</td>
</tr>
<tr>
<td><code>brookesia_runtime_lua</code></td>
<td>0.8.2</td>
<td>2026-07-27</td>
<td>Lua 后端（PUC-Lua 5.5）</td>
</tr>
<tr>
<td><code>brookesia_runtime_js</code></td>
<td>0.8.3</td>
<td>2026-08-05</td>
<td>JS 后端（QuickJS-NG 0.14）</td>
</tr>
<tr>
<td><code>brookesia_runtime_wasm</code></td>
<td>0.8.2</td>
<td>2026-07-27</td>
<td>WASM 后端（WAMR）</td>
</tr>
<tr>
<td><code>brookesia_system_core</code></td>
<td>0.8.4</td>
<td>2026-08-31</td>
<td>App/GUI/Runtime/Storage 系统框架、<code>.bpk</code> 包、验签、安装</td>
</tr>
<tr>
<td><code>brookesia_hal_interface</code></td>
<td>0.8.2</td>
<td>2026-07-20</td>
<td>HAL 抽象（Device/Interface）</td>
</tr>
<tr>
<td><code>brookesia_hal_adaptor</code></td>
<td>0.8.4</td>
<td>2026-08-25</td>
<td>HAL 板级实现（按 Kconfig 条件编译）</td>
</tr>
<tr>
<td><code>brookesia_hal_boards</code></td>
<td>0.8.0</td>
<td>2026-06-28</td>
<td>板级 YAML 配置集</td>
</tr>
<tr>
<td><code>esp-brookesia</code></td>
<td><strong>0.5.0</strong></td>
<td>2025-05-30</td>
<td><strong>旧线</strong>：LVGL 9.2 + Phone 系统 UI</td>
</tr>
<tr>
<td><code>wasm-micro-runtime</code></td>
<td>2.4.0~1</td>
<td>—</td>
<td>WAMR（Espressif fork）</td>
</tr>
</tbody>
</table>
<p><strong>批次判断</strong>：14 个 <code>brookesia_*</code> 均含共同的 <code>v0.8.0 - 2026-06-28</code> 基线条目，互引 <code>0.8.*</code>，属同一 v0.8 训练线；patch 号差异（0.8.0~0.8.5）是各自独立迭代。</p>
<h3 id="212-依赖关系图源码确认">2.1.2 依赖关系图（源码确认）</h3>
<figure>
<svg width="980" height="710" viewBox="0 0 980 710" xmlns="http://www.w3.org/2000/svg">
<defs><linearGradient id="d3-bg" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#111827"/><stop offset="100%" stop-color="#1f2937"/></linearGradient><marker id="d3-ar" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#38bdf8"/></marker></defs>
<rect width="980" height="710" fill="url(#d3-bg)" rx="16"/><text x="490.0" y="34" text-anchor="middle" fill="#facc15" font-family="Arial,sans-serif" font-size="18" font-weight="bold">Brookesia 组件依赖关系（源码确认）</text><rect x="290" y="55" width="400" height="100" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="490" y="80" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">外部依赖（组件管理器拉取）</text><text x="310" y="104" text-anchor="start" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">esp-boost 0.6.* / cmake_utilities / elf_loader 1.*</text><text x="310" y="122" text-anchor="start" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">quickjs-ng 0.14 / georgik/lua 5.5.* / zlib 1.3.*</text><text x="310" y="140" text-anchor="start" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">esp_board_manager 0.5.*</text><rect x="60" y="215" width="240" height="70" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="180" y="247" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">lib_utils</text><text x="180" y="268" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">（idf 6.0~6.2）</text><rect x="370" y="215" width="240" height="70" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="490" y="247" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">service_manager</text><rect x="680" y="215" width="240" height="70" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="800" y="247" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">hal_interface</text><rect x="370" y="335" width="240" height="60" rx="10" fill="#172554" stroke="#60a5fa" stroke-width="2"/><text x="490" y="372" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">runtime_manager</text><rect x="680" y="335" width="240" height="60" rx="10" fill="#172554" stroke="#60a5fa" stroke-width="2"/><text x="800" y="372" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">service_helper</text><path d="M490 285 L490 335" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><path d="M300 250 L300 365 L370 365" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><path d="M800 285 L800 335" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><path d="M610 365 L680 365" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><path d="M490 395 L490 425" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><line x1="145" y1="425" x2="790" y2="425" stroke="#38bdf8" stroke-width="2"/><path d="M145 425 L145 445" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><rect x="45" y="445" width="200" height="80" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="145" y="478" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">runtime_elf</text><path d="M360 425 L360 445" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><rect x="260" y="445" width="200" height="80" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="360" y="478" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">runtime_lua</text><path d="M575 425 L575 445" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><rect x="475" y="445" width="200" height="80" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="575" y="478" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">runtime_js</text><path d="M790 425 L790 445" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><rect x="690" y="445" width="200" height="80" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="790" y="478" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">runtime_wasm</text><line x1="145" y1="540" x2="790" y2="540" stroke="#38bdf8" stroke-width="2"/><path d="M145 525 L145 540" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><path d="M360 525 L360 540" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><path d="M575 525 L575 540" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><path d="M790 525 L790 540" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><path d="M490 540 L490 595" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><rect x="370" y="595" width="240" height="65" rx="10" fill="#172554" stroke="#60a5fa" stroke-width="2"/><text x="490" y="625" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">system_core</text><text x="490" y="646" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">（应用包 / 生命周期）</text><text x="490" y="695" text-anchor="middle" fill="#94a3b8" font-family="Arial,sans-serif" font-size="11">（gui_interface / service_storage / service_usb 缺失）</text><path d="M920 365 L920 585 L930 585" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d3-ar)"/><rect x="720" y="560" width="210" height="60" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="825" y="597" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">agent_manager</text><text x="825" y="645" text-anchor="middle" fill="#94a3b8" font-family="Arial,sans-serif" font-size="11">（service_sntp 缺失）</text><figcaption style="text-align:center;color:#888;font-size:12px;margin-top:8px;">图 2.1　Brookesia 组件依赖关系（源码确认）：lib_utils / service_manager / hal_interface 支撑 runtime_manager 与四个对等后端。</figcaption>
</svg>
</figure>
<p><strong>缺失的第一方组件</strong>（被引用但 <code>ref/</code> 中不存在，必须联网拉取）：</p>
<table>
<thead>
<tr>
<th>组件</th>
<th>引用方</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>brookesia_service_sntp</code></td>
<td>agent_manager (private)</td>
<td><code>brookesia_agent_manager/idf_component.yml:5-7</code></td>
</tr>
<tr>
<td><code>brookesia_gui_interface</code></td>
<td>system_core (public)</td>
<td><code>brookesia_system_core/idf_component.yml:2-4</code></td>
</tr>
<tr>
<td><code>brookesia_service_storage</code></td>
<td>system_core / service_wifi (public)</td>
<td><code>brookesia_system_core/idf_component.yml:11-13</code>、<code>brookesia_service_wifi/idf_component.yml:2-4</code></td>
</tr>
<tr>
<td><code>brookesia_service_usb</code></td>
<td>system_core (private)</td>
<td><code>brookesia_system_core/idf_component.yml:14-16</code></td>
</tr>
</tbody>
</table>
<h2 id="22-运行时层runtime_manager">2.2 运行时层（runtime_manager）</h2>
<h3 id="221-核心接口">2.2.1 核心接口</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// brookesia_runtime_manager/include/brookesia/runtime_manager/backend.hpp:19-62
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">IRuntimeBackend</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="nc">Attributes</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">virtual</span> <span class="kt">void</span> <span class="nf">set_native_modules</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">NativeModule</span><span class="o">&gt;</span> <span class="n">modules</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">init</span><span class="p">()</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">virtual</span> <span class="kt">void</span> <span class="nf">deinit</span><span class="p">()</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">load_app</span><span class="p">(</span><span class="n">AppId</span> <span class="n">id</span><span class="p">,</span> <span class="k">const</span> <span class="n">AppConfig</span> <span class="o">&amp;</span><span class="n">config</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">unload_app</span><span class="p">(</span><span class="n">AppId</span> <span class="n">id</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">start_app</span><span class="p">(</span><span class="n">AppId</span> <span class="n">id</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">stop_app</span><span class="p">(</span><span class="n">AppId</span> <span class="n">id</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="n">NativeValue</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">call_function</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">AppId</span> <span class="n">id</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string_view</span> <span class="n">module_name</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string_view</span> <span class="n">function_name</span><span class="p">,</span> <span class="k">const</span> <span class="n">NativeArgs</span> <span class="o">&amp;</span><span class="n">args</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">virtual</span> <span class="n">AppState</span> <span class="nf">get_app_state</span><span class="p">(</span><span class="n">AppId</span> <span class="n">id</span><span class="p">)</span> <span class="k">const</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">protected</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">IRuntimeBackend</span><span class="p">(</span><span class="n">BackendType</span> <span class="n">type</span><span class="p">,</span> <span class="n">Attributes</span> <span class="n">attributes</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">Attributes</span> <span class="n">attributes_</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">BackendType</span> <span class="n">type_</span> <span class="o">=</span> <span class="n">BackendType</span><span class="o">::</span><span class="n">Unknown</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><h3 id="222-数据模型">2.2.2 数据模型</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// types.hpp:22-29
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">enum</span> <span class="k">class</span> <span class="nc">BackendType</span> <span class="p">{</span> <span class="n">Unknown</span><span class="p">,</span> <span class="n">Lua</span><span class="p">,</span> <span class="n">JavaScript</span><span class="p">,</span> <span class="n">Wasm</span><span class="p">,</span> <span class="n">Elf</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="c1">// types.hpp:31-38
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">enum</span> <span class="k">class</span> <span class="nc">AppState</span> <span class="p">{</span> <span class="n">Unloaded</span><span class="p">,</span> <span class="n">Loaded</span><span class="p">,</span> <span class="n">Running</span><span class="p">,</span> <span class="n">Stopped</span><span class="p">,</span> <span class="n">Error</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="c1">// types.hpp:60-67
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">struct</span> <span class="nc">AppConfig</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">BackendType</span> <span class="n">type</span> <span class="o">=</span> <span class="n">BackendType</span><span class="o">::</span><span class="n">Unknown</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">app_path</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">entry</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">resource_dir</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">arguments</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><h3 id="223-注册与选择">2.2.3 注册与选择</h3>
<table>
<thead>
<tr>
<th>机制</th>
<th>实现</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>后端注册表</td>
<td><code>lib_utils::PluginRegistry&lt;IRuntimeBackend&gt;</code></td>
<td><code>backend.hpp:64</code></td>
</tr>
<tr>
<td>自动发现</td>
<td><code>Runtime::init()</code> 遍历注册表</td>
<td><code>src/runtime.cpp:60-85</code></td>
</tr>
<tr>
<td>后端选择</td>
<td>按 <code>BackendType</code> 查表；Unknown + 单后端时用唯一后端</td>
<td><code>src/runtime.cpp:26-43</code></td>
</tr>
<tr>
<td>后端自注册</td>
<td>各后端用 <code>-u &lt;symbol&gt;</code> + 插件注册宏</td>
<td><code>runtime_elf/cmake/esp_platform.cmake:18-24</code>、<code>runtime_lua/...:13-19</code>、<code>runtime_js/...:18-24</code>、<code>runtime_wasm/...:18-24</code></td>
</tr>
</tbody>
</table>
<h3 id="224-宿主桥接">2.2.4 宿主桥接</h3>
<table>
<thead>
<tr>
<th>机制</th>
<th>实现</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>宿主模块容器</td>
<td><code>NativeModule</code> / <code>NativeValue</code> / <code>NativeArgs</code></td>
<td><code>types.hpp:40-67</code></td>
</tr>
<tr>
<td>默认 Host Bridge</td>
<td>内建 <code>brookesia</code> 模块，5 个函数：<code>current_app_context</code> / <code>finish_app</code> / <code>attach_app_context</code> / <code>detach_app_context</code> / <code>print</code></td>
<td><code>src/host_bridge.cpp:196-225</code></td>
</tr>
<tr>
<td>模块来源</td>
<td>遍历 <code>RuntimeFunctionProviderRegistry</code> 自动收集（插件注册）</td>
<td><code>src/function_bridge.cpp:94-125</code></td>
</tr>
<tr>
<td>注册宏</td>
<td><code>BROOKESIA_RUNTIME_FUNCTION_PROVIDER_REGISTER_WITH_SYMBOL</code></td>
<td><code>function_bridge.hpp:73-76</code></td>
</tr>
<tr>
<td>App 上下文隔离</td>
<td><code>thread_local std::optional&lt;AppId&gt; current_app_id</code> + RAII <code>AppContextGuard</code></td>
<td><code>function_bridge.cpp:24, 212-258</code></td>
</tr>
</tbody>
</table>
<h3 id="225-职责边界关键">2.2.5 职责边界（关键）</h3>
<p><code>brookesia_runtime_manager/docs/main.md:3-24</code> 明确：</p>
<blockquote>
<p><code>brookesia_runtime_manager</code> 只负责 runtime backend 的 app 生命周期和 native host bridge。
<code>.bpk</code> 解包、发布验签与 app package manifest 解析均在 <code>system/brookesia_system_core</code>。</p>
</blockquote>
<p>即：<strong>运行时管理器不认识包格式、不做验签、不解 manifest</strong>。</p>
<h2 id="23-四个后端">2.3 四个后端</h2>
<h3 id="231-后端能力对照源码确认">2.3.1 后端能力对照（源码确认）</h3>
<table>
<thead>
<tr>
<th>后端</th>
<th>底层引擎</th>
<th>宿主模块注入</th>
<th><code>call_function</code></th>
<th>异步宿主函数</th>
<th>中断</th>
<th>加密</th>
</tr>
</thead>
<tbody>
<tr>
<td>ELF</td>
<td>IDF <code>elf_loader</code>（<code>esp_elf_*</code>）</td>
<td><strong>空操作</strong>（只记日志）</td>
<td><strong>不支持</strong></td>
<td>—</td>
<td><strong>不支持</strong>（同步执行）</td>
<td>无</td>
</tr>
<tr>
<td>Lua</td>
<td>PUC-Lua 5.5（<code>georgik/lua</code>）</td>
<td>全局 table + <code>lua_pushcclosure</code></td>
<td>支持</td>
<td><strong>不支持</strong></td>
<td>不支持</td>
<td>无</td>
</tr>
<tr>
<td>JS</td>
<td>QuickJS-NG 0.14</td>
<td><code>JS_NewCFunctionMagic</code></td>
<td>支持</td>
<td><strong>支持（Promise）</strong></td>
<td>不支持</td>
<td>无</td>
</tr>
<tr>
<td>WASM</td>
<td>WAMR 2.4.0</td>
<td>单桩 <code>(ii)i</code> + JSON + attachment</td>
<td>支持</td>
<td>—</td>
<td>不支持</td>
<td>无</td>
</tr>
</tbody>
</table>
<p>出处：</p>
<ul>
<li>ELF：<code>runtime_elf/src/backend.cpp:101-104</code>（<code>set_native_modules</code> 无操作）、<code>:266-281</code>（<code>call_function</code> 不支持）、<code>:258-261</code>（不可中断）、<code>:160-183</code>（<code>esp_elf_init</code>+<code>esp_elf_relocate</code>）、<code>:233-235</code>（<code>esp_elf_request</code>）</li>
<li>Lua：<code>runtime_lua/src/backend.cpp:93-104</code>（闭包注入）、<code>:74-76</code>（异步不支持）、<code>:229-237</code>（<code>luaL_dofile</code>）、<code>:185-190</code>（<code>luaL_newstate</code>+<code>luaL_openlibs</code>）</li>
<li>JS：<code>runtime_js/src/backend.cpp:481-503</code>（CFunc magic）、<code>:412-479</code>（Promise 异步）、<code>:681-701</code>（<code>JS_NewRuntime</code>/<code>JS_SetMemoryLimit</code>）、<code>:188-224</code>（app 生命周期 hook）</li>
<li>WASM：<code>runtime_wasm/src/backend.cpp:627-651</code>（单桩注册）、<code>:601-610</code>（结果句柄）、<code>:656-735</code>（加载流程）、<code>:494-518</code>（PSRAM 分配器）、<code>:682-683</code>（64 KB 栈 / 256 KB 堆）</li>
</ul>
<h3 id="232-各后端细节">2.3.2 各后端细节</h3>
<p><strong>ELF 后端</strong></p>
<ul>
<li>委托给 IDF 官方 <code>elf_loader</code>（<code>idf_component.yml:5-7</code>：<code>espressif/elf_loader: 1.*</code>）</li>
<li>relocate 前用 <code>BROOKESIA_THREAD_CONFIG_GUARD({ .stack_in_ext = false; })</code> 强制内部栈，注释说明&quot;因为 relocate 会操作 flash&quot;（<code>backend.cpp:169-176</code>）</li>
<li>文件读取走 Storage 服务（<code>backend.cpp:38-59</code>），非直接 <code>fopen</code></li>
<li>PC 平台直接 <code>FATAL_ERROR</code>（<code>cmake/pc_platform.cmake:4</code>）</li>
</ul>
<p><strong>Lua 后端</strong></p>
<ul>
<li>每个 app 一个 <code>lua_State</code> + <code>luaL_openlibs</code>（<code>backend.cpp:185-190</code>）</li>
<li>宿主模块注入：把每个函数用 <code>lua_pushlightuserdata</code> + <code>lua_pushcclosure</code> 包成闭包挂到全局表（<code>backend.cpp:93-104</code>）</li>
<li>PC 侧找 Lua 5.4（<code>pkg_check_modules(LUA54 REQUIRED lua5.4)</code>，<code>cmake/pc_platform.cmake:24</code>），与 IDF 侧 5.5 不一致</li>
</ul>
<p><strong>JS 后端</strong></p>
<ul>
<li>QuickJS-NG 0.14，支持 ES module 与全局脚本（<code>backend.cpp:764-769</code>）</li>
<li>内存上限硬编码 <code>16 * 1024 * 1024</code>（<code>backend.cpp:42-47</code>），不可通过 Kconfig 调整</li>
<li>唯一提供 app 级生命周期 hook 的后端：<code>on_install / on_start / on_stop / on_pause / on_resume / on_uninstall / on_action / on_event / on_timer</code>（<code>backend.cpp:188-224</code>）</li>
<li>异步宿主函数用 <code>JS_NewPromiseCapability</code> + <code>TaskScheduler</code>（组 <code>RuntimeJsAsync</code>）resolve（<code>backend.cpp:412-479</code>）</li>
<li>无 QuickJS 时有 fallback 后端（<code>backend.cpp:878-1014</code>）</li>
</ul>
<p><strong>WASM 后端</strong></p>
<ul>
<li>加载流程（<code>backend.cpp:656-735</code>）：<code>read_wasm_file</code> → <code>register_wamr_brookesia_imports</code> → <code>wasm_runtime_load</code> → <code>wasm_runtime_set_wasi_args</code> → <code>wasm_runtime_instantiate(64KB, 256KB)</code> → <code>wasm_application_execute_main</code></li>
<li>宿主桥接：模块名固定 <code>&quot;env&quot;</code>，所有函数共用桩 <code>wamr_dynamic_import</code>，签名统一 <code>(ii)i</code>，通过 <code>wasm_runtime_get_function_attachment</code> 区分（<code>backend.cpp:520-523, 620, 627-651</code>）</li>
<li>符号名约定：<code>&lt;sanitized_module&gt;_&lt;sanitized_function&gt;</code>（<code>private/import_descriptor.hpp:69-77</code>）</li>
<li>结果回传：<code>brookesia_result_len</code> / <code>brookesia_result_copy</code> / <code>brookesia_result_free</code>，结果池最多 64 条（<code>backend.cpp:601-610</code>、<code>private/host_utils.hpp:21-54</code>）</li>
<li>运行时内存与线性内存都指向 PSRAM（<code>backend.cpp:494-518, 781-793</code>）</li>
</ul>
<h2 id="24-服务层service_manager--helper--agent">2.4 服务层（service_manager + helper + agent）</h2>
<h3 id="241-servicebase">2.4.1 ServiceBase</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// brookesia_service_manager/include/brookesia/service_manager/service/base.hpp:136-175
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">struct</span> <span class="nc">Attributes</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>                 <span class="c1">// RPC 稳定标识
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">description</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">version</span><span class="p">;</span>              <span class="c1">// v0.8.1 起强制非空
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">dependencies</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">lib_utils</span><span class="o">::</span><span class="n">TaskSchedulerStartConfig</span><span class="o">&gt;</span> <span class="n">task_scheduler_config</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">SchedulerType</span> <span class="n">scheduler_type</span> <span class="o">=</span> <span class="n">SchedulerType</span><span class="o">::</span><span class="n">Main</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">bool</span> <span class="n">bindable</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>子类覆写：<code>get_function_schemas()</code> / <code>get_event_schemas()</code> / <code>get_function_handlers()</code>（<code>base.hpp:228, 252, 536</code>）；生命周期钩子 <code>on_init/on_deinit/on_start/on_stop</code>（<code>base.hpp:446-477</code>）</p>
<h3 id="242-关键机制">2.4.2 关键机制</h3>
<table>
<thead>
<tr>
<th>机制</th>
<th>实现</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>服务注册</td>
<td><code>ServiceRegistry = lib_utils::PluginRegistry&lt;ServiceBase&gt;</code> + 静态注册宏</td>
<td><code>manager.hpp:36</code>、<code>lib_utils/plugin.hpp:37-47, 415</code></td>
</tr>
<tr>
<td>自动装配</td>
<td><code>add_all_registered_services()</code> + 拓扑排序（Kahn）</td>
<td><code>manager.cpp:818-845</code>、<code>manager.cpp:750-816</code></td>
</tr>
<tr>
<td>函数调用</td>
<td><code>FunctionValue</code> variant（bool/double/string/object/array/RawBuffer）</td>
<td><code>function/definition.hpp:49</code></td>
</tr>
<tr>
<td>Schema</td>
<td><code>FunctionSchema{name, description, parameters, require_scheduler, default_timeout_ms, return_value}</code></td>
<td><code>function/definition.hpp:147-154</code></td>
</tr>
<tr>
<td>同步调用</td>
<td><code>call_function_sync</code>（<code>boost::promise</code> + <code>wait_for</code>）</td>
<td><code>service/base.cpp:416, 491-518</code></td>
</tr>
<tr>
<td>事件</td>
<td><code>lib_utils::signal</code> + <code>EventSchema</code> + <code>EventMonitor</code></td>
<td><code>event/definition.hpp:70,75,121-126</code>、<code>helper/base.hpp:982-1244</code></td>
</tr>
<tr>
<td>无订阅者跳过</td>
<td><code>publish_event</code> 前检查 <code>has_subscribers</code></td>
<td><code>service/base.cpp:781, 804-807</code></td>
</tr>
<tr>
<td>线程模型</td>
<td>每服务 3 个串行任务组（<code>&lt;svc&gt;_call/_event/_request</code>）</td>
<td><code>service/base.cpp:1077-1133</code></td>
</tr>
<tr>
<td>绑定模型</td>
<td>RAII <code>ServiceBinding</code> + 引用计数，ref_count 归零时 <code>stop()</code></td>
<td><code>manager.hpp:44</code>、<code>manager.cpp:435, 569</code></td>
</tr>
<tr>
<td><strong>跨进程</strong></td>
<td><strong>v0.8.0 已移除 TCP RPC</strong></td>
<td><code>service_manager/CHANGELOG.md</code> v0.8.0 条目</td>
</tr>
</tbody>
</table>
<h3 id="243-service_helper契约层">2.4.3 service_helper（契约层）</h3>
<ul>
<li>纯头文件，0 个 <code>.cpp</code>，约 8.5k 行</li>
<li>核心 CRTP 基类 <code>template &lt;typename Derived&gt; class Base</code>（<code>helper/base.hpp:77</code>），要求 <code>Derived</code> 提供 <code>FunctionId</code>/<code>EventId</code> 枚举、<code>get_name()</code>、schema（<code>helper/base.hpp:32-40</code>）</li>
<li>类型安全调用：<code>call_function_sync&lt;ReturnType&gt;(FunctionId, Args...)</code>（<code>helper/base.hpp:679</code>）</li>
<li><code>get_name()</code> 是稳定 RPC 标识，改名属于破坏性变更（<code>service_helper/README.md:11-13</code>）</li>
</ul>
<h3 id="244-service_wifi服务模板">2.4.4 service_wifi（服务模板）</h3>
<p>可复用要点（<code>service_wifi/src/service_wifi.cpp</code>、<code>service_wifi.hpp</code>）：</p>
<ol>
<li>属性在构造函数注入（<code>service_wifi.hpp:66-96</code>）</li>
<li><code>get_function_schemas()</code> 直接返回 helper 的 schema（<code>:122-132</code>）</li>
<li>handler 用 <code>BROOKESIA_SERVICE_HELPER_FUNC_HANDLER_N</code> 逐条绑定（<code>:133-205</code>）</li>
<li>业务函数返回 <code>std::expected&lt;T, std::string&gt;</code></li>
<li>底部静态注册 + CMake <code>-u</code>（<code>service_wifi.cpp:1880-1885</code>、<code>CMakeLists.txt:32-38</code>）</li>
</ol>
<h3 id="245-agent_manager">2.4.5 agent_manager</h3>
<table>
<thead>
<tr>
<th>项</th>
<th>内容</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>Agent 抽象</td>
<td><code>class Base : public service::ServiceBase</code>，构造时 <code>bindable=false</code></td>
<td><code>agent_manager/base.hpp:88, 132-138</code></td>
</tr>
<tr>
<td>生命周期钩子</td>
<td><code>on_activate/on_startup/on_shutdown/on_sleep/on_wakeup</code> + 可选钩子</td>
<td><code>base.hpp:159-181, 188-263</code></td>
</tr>
<tr>
<td>Manager</td>
<td>20 个函数（SetAgentInfo/SetTargetAgent/TriggerGeneralAction/Suspend/Resume/…）</td>
<td><code>manager.hpp:131-215</code></td>
</tr>
<tr>
<td>状态机</td>
<td><code>GeneralState</code>：TimeSyncing/Ready/Activating/Activated/Starting/Started/Sleeping/Slept/WakingUp/Stopping</td>
<td><code>service_helper/agent/manager.hpp:141-153</code></td>
</tr>
<tr>
<td>后端</td>
<td>Coze / OpenAI / XiaoZhi —— <strong>ref 中只有 helper 契约，无实现体</strong></td>
<td><code>service_helper/agent/{coze,openai,xiaozhi}.hpp</code></td>
</tr>
<tr>
<td>MCP 接入</td>
<td>XiaoZhi helper：<code>AddMCP_ToolsWithServiceFunction</code> / <code>AddMCP_ToolsWithCustomFunction</code> / <code>RemoveMCP_Tools</code></td>
<td><code>service_helper/agent/xiaozhi.hpp:31-37, 66-104</code></td>
</tr>
<tr>
<td>测试</td>
<td><strong>无 test_apps 目录</strong></td>
<td>目录列举</td>
</tr>
</tbody>
</table>
<h2 id="25-系统层system_core">2.5 系统层（system_core）</h2>
<h3 id="251-定位">2.5.1 定位</h3>
<p><code>brookesia_system_core/README.md:7</code>：</p>
<blockquote>
<p>the app, GUI, runtime, storage, timer, and service bridge framework for products.</p>
</blockquote>
<p>依赖（<code>system_core/idf_component.yml:1-28</code>）：<code>brookesia_gui_interface</code>(缺)、<code>brookesia_runtime_manager</code>、<code>brookesia_service_helper</code>、<code>brookesia_service_storage</code>(缺)、<code>brookesia_service_usb</code>(缺)、<code>zlib ^1.3.0</code></p>
<h3 id="252-bpk-包格式">2.5.2 <code>.bpk</code> 包格式</h3>
<table>
<thead>
<tr>
<th>项</th>
<th>内容</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>容器</td>
<td>ZIP，根含 <code>manifest.json</code>，签名材料在 <code>META-INF/</code></td>
<td><code>src/app/package.cpp:39-46</code></td>
</tr>
<tr>
<td>解包目标</td>
<td><code>&lt;install_dir&gt;/&lt;manifest.package.id&gt;/</code>（确定性路径）</td>
<td><code>package.cpp:887-890</code></td>
</tr>
<tr>
<td>安全校验</td>
<td>跳过 <code>META-INF/</code>；逐条检查 <code>is_safe_relative_path</code>（防 <code>../</code>）</td>
<td><code>package.cpp:897-906</code></td>
</tr>
<tr>
<td>命名约定</td>
<td><code>&lt;package.id&gt;.&lt;debug|release&gt;.&lt;version&gt;.bpk</code></td>
<td><code>package.cpp:887-889</code></td>
</tr>
</tbody>
</table>
<h3 id="253-manifest-字段完整">2.5.3 manifest 字段（完整）</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// include/brookesia/system_core/app/types.hpp:200-245
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">struct</span> <span class="nc">AppManifest</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">id</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">localized_names</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">version</span> <span class="o">=</span> <span class="s">&#34;0.1.0&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">AppKind</span> <span class="n">kind</span> <span class="o">=</span> <span class="n">AppKind</span><span class="o">::</span><span class="n">Native</span><span class="p">;</span>        <span class="c1">// Native / Runtime
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="n">visible</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">bool</span> <span class="n">preload_dom</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">icon_id</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">supported_systems</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">icon_path</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">runtime</span><span class="o">::</span><span class="n">BackendType</span> <span class="n">runtime_type</span> <span class="o">=</span> <span class="n">runtime</span><span class="o">::</span><span class="n">BackendType</span><span class="o">::</span><span class="n">Unknown</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">app_path</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">entry</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">resource_dir</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">arguments</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">AppManifestService</span><span class="o">&gt;</span> <span class="n">services</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>JSON 层级：顶层 <code>package</code> / <code>runtime</code> / <code>services</code>（<code>package.cpp:672-700</code>）</p>
<ul>
<li><code>package</code>：<code>id</code>(必填)、<code>name</code>(对象形式 <code>{&quot;en&quot;:&quot;...&quot;}</code>, 必填)、<code>version</code>(必填)、<code>visible</code>、<code>systems</code></li>
<li><code>runtime</code>：<code>type</code>(必填)、<code>entry</code>(必填)、<code>resource_dir</code>、<code>arguments</code></li>
<li><code>services[]</code>：<code>name</code>(必填)、<code>version</code>(必填)、<code>component</code></li>
</ul>
<h3 id="254-验签">2.5.4 验签</h3>
<table>
<thead>
<tr>
<th>项</th>
<th>内容</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>算法</td>
<td>RSA-PSS / SHA-256，覆盖 <code>META-INF/hash.json</code> + 逐成员 SHA-256</td>
<td><code>include/brookesia/system_core/package.hpp:56-69</code></td>
</tr>
<tr>
<td>签名材料</td>
<td><code>META-INF/hash.json</code>、<code>META-INF/signature.sig</code></td>
<td><code>src/package_release_verify.cpp:42-45</code></td>
</tr>
<tr>
<td>公钥来源</td>
<td>文件系统 PEM（<code>mbedtls_pk_parse_public_key</code>）</td>
<td><code>package_release_verify.cpp:551-558</code></td>
</tr>
<tr>
<td>开关</td>
<td><code>CONFIG_BROOKESIA_SYSTEM_CORE_ENABLE_PACKAGE_RELEASE_VERIFY</code> 默认 y</td>
<td><code>Kconfig:90-107</code></td>
</tr>
<tr>
<td><strong>载荷加密</strong></td>
<td><code>CONFIG_BROOKESIA_SYSTEM_CORE_ENABLE_PACKAGE_PAYLOAD_ENCRYPTION</code> 默认 n，帮助文本写明 <strong>&ldquo;Not implemented&rdquo;</strong></td>
<td><code>Kconfig:90-107</code></td>
</tr>
<tr>
<td>工具</td>
<td><code>tools/app_pack.py</code>（<code>pack|sign --private-key</code>）——<strong>不在 ref 中</strong>【待核实】</td>
<td><code>package_release_verify.cpp:455-457</code> 引用</td>
</tr>
</tbody>
</table>
<h3 id="255-安装卸载">2.5.5 安装/卸载</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// include/brookesia/system_core/system/system.hpp:158-175
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="n">AppId</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">install_app</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">IApp</span><span class="o">&gt;</span> <span class="n">app</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="n">AppId</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">install_runtime_app</span><span class="p">(</span><span class="k">const</span> <span class="n">AppManifest</span> <span class="o">&amp;</span><span class="n">manifest</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="n">AppId</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">install_runtime_app_package</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string_view</span> <span class="n">package_path</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">replace_existing</span> <span class="o">=</span> <span class="nb">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">install_registered_apps</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">expected</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">uninstall_app</span><span class="p">(</span><span class="n">AppId</span> <span class="n">app_id</span><span class="p">);</span>
</span></span></code></pre></div><ul>
<li><strong>无独立 update API</strong>：更新 = <code>install_runtime_app_package(..., replace_existing=true)</code></li>
<li>安装含回滚（<code>src/app/manager.cpp:393-482</code>）</li>
<li>启动时扫描已解包目录并安装（<code>src/app/package_scan.cpp:30-119</code>）</li>
<li><strong>不存在 &ldquo;App Store&rdquo; 组件</strong>（<code>ref/</code> 全境检索仅命中 <code>esp-brookesia/README.md</code> 规划文字）</li>
</ul>
<h2 id="26-hal-层">2.6 HAL 层</h2>
<table>
<thead>
<tr>
<th>层</th>
<th>形态</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>hal_interface</code></td>
<td>抽象：<code>Device</code> / <code>Interface</code> / <code>InterfaceHandle&lt;T&gt;</code></td>
<td><code>device.hpp:48-131</code>、<code>interface.hpp:51-80</code></td>
</tr>
<tr>
<td>接口类型</td>
<td>audio / bluetooth / display / network / power / storage / system / video / wifi</td>
<td><code>interfaces.hpp:13-36</code></td>
</tr>
<tr>
<td><code>hal_adaptor</code></td>
<td>板级实现，按 Kconfig 条件编译（36 个 <code>.cpp</code>）</td>
<td><code>CMakeLists.txt:117-265</code></td>
</tr>
<tr>
<td><code>hal_boards</code></td>
<td>纯 YAML 配置（<code>board_info.yaml</code> / <code>board_devices.yaml</code> / <code>board_peripherals.yaml</code> / <code>sdkconfig.defaults.board</code>）</td>
<td><code>boards/**/</code></td>
</tr>
</tbody>
</table>
<p><strong>与 LVGL 解耦</strong>（源码确认）：<code>hal_interface/idf_component.yml:1-14</code> 仅依赖 <code>brookesia_lib_utils</code>；<code>hal_adaptor</code> 依赖列表无 LVGL；display 仅提供 panel/touch/backlight 原生接口。</p>
<p><strong>ESP32-S3 板子</strong>（<code>boards/**/board_info.yaml</code>）：<code>esp_box_3</code>、<code>esp32_s3_korvo2_v3</code>、<code>waveshare/esp32_s3_touch_amoled_{1_75c,1_8,2_16}</code>、<code>rymcu/rymcu_bigsmart</code></p>
<h2 id="27-旧线-esp-brookesia-050">2.7 旧线 esp-brookesia 0.5.0</h2>
<table>
<thead>
<tr>
<th>项</th>
<th>内容</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>版本/日期</td>
<td>0.5.0 / 2025-05-30</td>
<td><code>esp-brookesia/CHANGELOG.md:3</code></td>
</tr>
<tr>
<td>依赖</td>
<td><code>esp-lib-utils 0.2.*</code>、<code>lvgl/lvgl 9.2.*</code>、<code>idf &gt;=5.3</code></td>
<td><code>esp-brookesia/idf_component.yml:2-17</code></td>
</tr>
<tr>
<td>内容</td>
<td>LVGL 封装 + Phone 系统 UI（app_launcher / gesture / navigation_bar / recents_screen / status_bar + 多分辨率 stylesheet）</td>
<td><code>src/systems/phone/widgets/**</code></td>
</tr>
<tr>
<td>资源规模</td>
<td>壁纸：720×720 8.9 MB、480×480 3.96 MB、240×240 1.0 MB；字体 24 个文件合计约 2.5 MB</td>
<td><code>src/systems/phone/assets/**</code></td>
</tr>
<tr>
<td>示例镜像</td>
<td>&gt;2.3 MB（boot 日志 <code>size=1c5f04h</code> + <code>76e50h</code>）</td>
<td><code>examples/phone_s3_box_3/README.md:65-69</code></td>
</tr>
<tr>
<td>与 0.8 关系</td>
<td><strong>无依赖关系</strong>，属不同代</td>
<td>依赖图核对</td>
</tr>
</tbody>
</table>
<h2 id="28-wamr-在-esp-idf--esp32-s3-上的集成事实">2.8 WAMR 在 ESP-IDF / ESP32-S3 上的集成事实</h2>
<table>
<thead>
<tr>
<th>项</th>
<th>结论</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>支持芯片</td>
<td><code>esp32, esp32s3, esp32c3, esp32c6, esp32p4, esp32c5</code></td>
<td><code>wasm-micro-runtime/idf_component.yml:28-34</code></td>
</tr>
<tr>
<td>IDF 约束</td>
<td><code>&gt;=5.1</code></td>
<td>同文件 <code>:2</code></td>
</tr>
<tr>
<td>AOT 默认</td>
<td><code>WAMR_ENABLE_AOT=y</code></td>
<td><code>build-scripts/esp-idf/wamr/Kconfig:13-15</code></td>
</tr>
<tr>
<td>解释器默认</td>
<td><code>WAMR_ENABLE_INTERP=y</code> + <code>WAMR_INTERP_MODE=Fast</code></td>
<td><code>Kconfig:17-19, 23-32</code></td>
</tr>
<tr>
<td>libc 默认</td>
<td>libc-builtin=y、libc-wasi=y</td>
<td><code>Kconfig:50-56</code></td>
</tr>
<tr>
<td>JIT</td>
<td><strong>ESP-IDF 不提供</strong>（Kconfig 无 JIT 项；Fast JIT codegen 仅 x86-64）</td>
<td><code>build-scripts/esp-idf/wamr/Kconfig</code>、<code>core/iwasm/fast-jit/iwasm_fast_jit.cmake:97-101</code></td>
</tr>
<tr>
<td>架构分支</td>
<td>xtensa → <code>WAMR_BUILD_TARGET=XTENSA</code>；riscv → RISCV32_ILP32F</td>
<td><code>build-scripts/esp-idf/wamr/CMakeLists.txt:7-17</code></td>
</tr>
<tr>
<td><strong>AOT 代码落点</strong></td>
<td>S3 开 PSRAM → <code>WASM_MEM_DUAL_BUS_MIRROR=1</code> → <code>MALLOC_CAP_SPIRAM</code>（<strong>PSRAM</strong>）+ ibus 镜像；否则 <code>MALLOC_CAP_EXEC</code>（内部 RAM）</td>
<td><code>core/shared/platform/esp-idf/shared_platform.cmake:18-22</code>、<code>core/shared/platform/esp-idf/espidf_memmap.c:20-51</code></td>
</tr>
<tr>
<td>XIP 模式</td>
<td>AOT ELF 支持 <code>E_TYPE_XIP</code>，<code>is_indirect_mode</code> 时不 mmap/copy text，就地执行</td>
<td><code>core/iwasm/aot/aot_loader.c:260-263, 4283-4291, 4349-4350</code></td>
</tr>
<tr>
<td>xtensa 重定位限制</td>
<td>仅 <code>R_XTENSA_32</code> / <code>R_XTENSA_SLOT0_OP</code>；<code>l32r</code> 越界需 <code>wamrc --size-level=0</code></td>
<td><code>core/iwasm/aot/arch/aot_reloc_xtensa.c:8-9, 272-280</code></td>
</tr>
<tr>
<td>内存模型</td>
<td>分配器三选一：Pool / Allocator / System；brookesia 用 <code>Alloc_With_Allocator</code> → PSRAM</td>
<td><code>core/iwasm/include/wasm_export.h:169-200</code>、<code>runtime_wasm/src/backend.cpp:781-793</code></td>
</tr>
<tr>
<td>全局堆池</td>
<td>默认关闭；ESP-IDF 上不支持（示例 <code>#error</code>）</td>
<td><code>core/config.h:376-379</code>、<code>external_examples/968944e8/esp-idf/main/main.c:45-52</code></td>
</tr>
<tr>
<td>体积参考（官方 README）</td>
<td>fast-interp 58.9 KB / classic 56.3 KB / AOT 29.4 KB / libc-wasi 21.4 KB / libc-builtin 3.7 KB</td>
<td><code>wasm-micro-runtime/README.md:25-29</code></td>
</tr>
</tbody>
</table>
<h2 id="29-落地门槛">2.9 落地门槛</h2>
<h3 id="291-idf-版本决定性">2.9.1 IDF 版本（决定性）</h3>
<table>
<thead>
<tr>
<th>文件:行</th>
<th>约束</th>
<th>影响</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>brookesia_lib_utils/idf_component.yml:8</code></td>
<td><strong><code>idf: '&gt;=6.0,&lt;=6.2'</code></strong></td>
<td>几乎所有第一方组件的传递依赖，5.5.4 直接求解失败</td>
</tr>
<tr>
<td><code>esp-brookesia/idf_component.yml:5</code></td>
<td><code>idf: '&gt;=5.3'</code></td>
<td>仅旧线可用</td>
</tr>
<tr>
<td><code>wasm-micro-runtime/idf_component.yml:2</code></td>
<td><code>idf: '&gt;=5.1'</code></td>
<td>可单独用于 5.5.4</td>
</tr>
</tbody>
</table>
<p>其余 0.8 组件（service_manager / service_helper / service_wifi / agent_manager / runtime_* / system_core / hal_*）的 <code>idf_component.yml</code> <strong>均未声明 IDF 约束</strong>，其下限由 <code>lib_utils</code> 决定。</p>
<h3 id="292-其它门槛">2.9.2 其它门槛</h3>
<table>
<thead>
<tr>
<th>门槛</th>
<th>内容</th>
<th>出处</th>
</tr>
</thead>
<tbody>
<tr>
<td>Boost</td>
<td><code>esp-boost 0.6.*</code>（Boost thread/system/chrono/json）</td>
<td><code>lib_utils/idf_component.yml:5-7</code>、<code>service_manager/Kconfig:2-6</code></td>
</tr>
<tr>
<td>C++ 标准</td>
<td>runtime_*/system_core 强制 <code>cxx_std_23</code>；使用 <code>std::expected</code>（<code>runtime_elf/src/backend.cpp:38</code> 等）、<code>std::span</code></td>
<td>各 <code>cmake/esp_platform.cmake</code></td>
</tr>
<tr>
<td>pthread wrap</td>
<td><code>-Wl,--wrap=pthread_mutex_init</code> / <code>--wrap=pthread_mutex_destroy</code>，<strong>INTERFACE 传播</strong></td>
<td><code>lib_utils/cmake/esp_platform.cmake:12-18</code></td>
</tr>
<tr>
<td>插件符号保留</td>
<td><code>-u &lt;symbol&gt;</code>（后端、服务、HAL 设备共十余处）</td>
<td>各 <code>CMakeLists.txt</code> / <code>cmake/esp_platform.cmake</code></td>
</tr>
<tr>
<td>强制 mbedtls</td>
<td>system_core 在 ESP 恒追加 <code>mbedtls</code>（验签用）</td>
<td><code>system_core/cmake/esp_platform.cmake:4-6</code></td>
</tr>
<tr>
<td>运行期打补丁</td>
<td>hal_adaptor 用 <code>git apply</code> 给 <code>media_lib_sal</code> 打 IDF 6 TLS 补丁，需要 git</td>
<td><code>hal_adaptor/CMakeLists.txt:26-99, 284-295</code></td>
</tr>
<tr>
<td>运行时 RAM</td>
<td>默认主调度器 3 worker × 64 KB 栈（≈192 KB 内部 RAM）+ 每服务 3 个串行任务组</td>
<td><code>system_core/include/brookesia/system_core/macro_configs.h:108-140</code>、<code>service/base.cpp:1077-1133</code></td>
</tr>
</tbody>
</table>
<h3 id="293-缺失组件需联网拉取">2.9.3 缺失组件（需联网拉取）</h3>
<p><code>brookesia_service_sntp</code>、<code>brookesia_gui_interface</code>、<code>brookesia_service_storage</code>、<code>brookesia_service_usb</code>（出处见 2.1.2）</p>
<h2 id="210-brookesia-特征总结">2.10 Brookesia 特征总结</h2>
<table>
<thead>
<tr>
<th>特征</th>
<th>描述</th>
<th>依据</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>对等后端</strong></td>
<td>ELF/Lua/JS/WASM 四个平级运行时，各自实现同一接口</td>
<td>2.2、2.3</td>
</tr>
<tr>
<td><strong>后端层抽象</strong></td>
<td>语言差异由后端吸收；宿主能力用与语言无关的 <code>NativeModule</code> 元数据描述</td>
<td>2.2.4</td>
</tr>
<tr>
<td><strong>反向调用</strong></td>
<td>宿主可通过 <code>call_function(app_id, module, fn, args)</code> 进入 app 内部（ELF 后端除外）</td>
<td>2.3.1</td>
</tr>
<tr>
<td><strong>App 隔离</strong></td>
<td><code>AppId</code> + <code>thread_local</code> 上下文 + RAII guard</td>
<td>2.2.4</td>
</tr>
<tr>
<td><strong>编译期装配</strong></td>
<td>插件注册表 + <code>-u</code> 符号，<code>Runtime::init()</code> 自动发现；基座不硬编码后端</td>
<td>2.2.3</td>
</tr>
<tr>
<td><strong>包/运行时解耦</strong></td>
<td><code>.bpk</code> + manifest 由 system_core 解析，运行时只收 <code>AppConfig</code></td>
<td>2.2.5</td>
</tr>
<tr>
<td><strong>验签不加密</strong></td>
<td>RSA-PSS 完整性/来源验证默认开；<strong>载荷加密未实现</strong></td>
<td>2.5.4</td>
</tr>
<tr>
<td><strong>进程内服务框架</strong></td>
<td>schema 校验 + 依赖拓扑 + 引用计数绑定 + 事件 await；<strong>v0.8.0 移除跨进程 RPC</strong></td>
<td>2.4.2</td>
</tr>
<tr>
<td><strong>MCP 桥</strong></td>
<td>服务函数可直接暴露为 MCP 工具（经 XiaoZhi helper）</td>
<td>2.4.5</td>
</tr>
<tr>
<td><strong>快速演进</strong></td>
<td>0.8.x 内多次 Breaking Change（删 RPC、强制 version、隐藏 Impl）</td>
<td>各 CHANGELOG</td>
</tr>
<tr>
<td><strong>HAL 与 GUI 解耦</strong></td>
<td>HAL 三层不依赖 LVGL</td>
<td>2.6</td>
</tr>
</tbody>
</table>
<hr>
<h1 id="3-对比分析">3. 对比分析</h1>
<h2 id="31-根本差异抽象放在哪一层">3.1 根本差异：抽象放在哪一层</h2>
<table>
<thead>
<tr>
<th></th>
<th>elf_loader 基座</th>
<th>Brookesia</th>
</tr>
</thead>
<tbody>
<tr>
<td>抽象单元</td>
<td><strong>符号</strong>（<code>esp_elfsym</code> 数组 + 白名单）</td>
<td><strong>后端</strong>（<code>IRuntimeBackend</code> 实现）</td>
</tr>
<tr>
<td>语言差异处理方</td>
<td><code>.so</code> 内部自己消化（<code>lua_module_*</code> 绑定）</td>
<td>后端实现吸收（Lua 闭包 / JS CFunc / WASM 单桩）</td>
</tr>
<tr>
<td>宿主能力描述</td>
<td>编译期 C 符号名 → 地址</td>
<td>运行期 <code>NativeModule</code> 元数据</td>
</tr>
<tr>
<td>新增语言</td>
<td>必须编成新的 <code>.so</code></td>
<td>加一个后端组件 + 链接项</td>
</tr>
<tr>
<td>新增宿主 API</td>
<td>重生成符号表 + 重编基座</td>
<td>加一个 Provider + <code>-u</code> 符号</td>
</tr>
</tbody>
</table>
<h2 id="32-分层图对照">3.2 分层图对照</h2>
<p><strong>elf_loader 基座（层级式）</strong></p>
<figure>
<svg width="700" height="440" viewBox="0 0 700 440" xmlns="http://www.w3.org/2000/svg">
<defs><linearGradient id="d4-bg" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#111827"/><stop offset="100%" stop-color="#1f2937"/></linearGradient><marker id="d4-ar" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#38bdf8"/></marker></defs>
<rect width="700" height="440" fill="url(#d4-bg)" rx="16"/><text x="350.0" y="34" text-anchor="middle" fill="#facc15" font-family="Arial,sans-serif" font-size="18" font-weight="bold">elf_loader 基座：分层结构</text><rect x="200" y="55" width="300" height="60" rx="10" fill="#172554" stroke="#60a5fa" stroke-width="2"/><text x="350" y="92" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">基座固件</text><path d="M350 115 L350 150" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d4-ar)"/><rect x="120" y="150" width="460" height="70" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="350" y="182" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">elf_loader（唯一执行基座）</text><text x="350" y="204" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">+ elf_ext 符号白名单</text><path d="M350 220 L180 262" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d4-ar)"/><path d="M350 220 L415 262" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d4-ar)"/><path d="M350 220 L565 262" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d4-ar)"/><rect x="40" y="262" width="280" height="110" rx="10" fill="#172554" stroke="#60a5fa" stroke-width="2"/><text x="180" y="294" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">lua_engine.so</text><text x="180" y="318" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">内含 Lua VM</text><text x="180" y="340" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">执行 .lua（作业模型）</text><rect x="345" y="262" width="150" height="70" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="420" y="294" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">ui_mirror.so</text><text x="420" y="314" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">WebSocket 镜像</text><rect x="515" y="262" width="150" height="70" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="590" y="294" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">bs_link_hmi.so</text><text x="590" y="314" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">总线 / OTA</text><figcaption style="text-align:center;color:#888;font-size:12px;margin-top:8px;">图 3.1　elf_loader 基座分层：单一 ELF 执行基座 + 符号白名单，脚本由 .so 内的解释器执行。</figcaption>
</svg>
</figure>
<p><strong>Brookesia（对等式）</strong></p>
<figure>
<svg width="700" height="490" viewBox="0 0 700 490" xmlns="http://www.w3.org/2000/svg">
<defs><linearGradient id="d5-bg" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#111827"/><stop offset="100%" stop-color="#1f2937"/></linearGradient><marker id="d5-ar" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#38bdf8"/></marker></defs>
<rect width="700" height="490" fill="url(#d5-bg)" rx="16"/><text x="350.0" y="34" text-anchor="middle" fill="#facc15" font-family="Arial,sans-serif" font-size="18" font-weight="bold">Brookesia：分层结构</text><rect x="130" y="55" width="440" height="65" rx="10" fill="#172554" stroke="#60a5fa" stroke-width="2"/><text x="350" y="84" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">system_core</text><text x="350" y="105" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">.bpk / manifest / 验签 / 安装</text><path d="M350 120 L350 155" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d5-ar)"/><rect x="110" y="155" width="480" height="70" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="350" y="187" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">Runtime</text><text x="350" y="208" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">AppId / 生命周期 / app 上下文 / host bridge</text><path d="M350 225 L103 268" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d5-ar)"/><rect x="28" y="268" width="150" height="80" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="103" y="300" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">RuntimeELF</text><text x="103" y="324" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">esp_elf loader</text><path d="M350 225 L267 268" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d5-ar)"/><rect x="192" y="268" width="150" height="80" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="267" y="300" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">RuntimeLua</text><text x="267" y="324" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">每 app 一个 lua_State</text><path d="M350 225 L431 268" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d5-ar)"/><rect x="356" y="268" width="150" height="80" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="431" y="300" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">RuntimeJS</text><text x="431" y="324" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">QuickJS</text><path d="M350 225 L595 268" stroke="#38bdf8" stroke-width="2" fill="none" marker-end="url(#d5-ar)"/><rect x="520" y="268" width="150" height="80" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="595" y="300" text-anchor="middle" fill="#e5e7eb" font-family="Arial,sans-serif" font-size="14">RuntimeWasm</text><text x="595" y="324" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">WAMR</text><rect x="70" y="385" width="560" height="45" rx="10" fill="#0f172a" stroke="#38bdf8" stroke-width="2"/><text x="350" y="413" text-anchor="middle" fill="#cbd5e1" font-family="Arial,sans-serif" font-size="12">Native 模块由插件注册，统一以 NativeModule 元数据注入各后端</text><figcaption style="text-align:center;color:#888;font-size:12px;margin-top:8px;">图 3.2　Brookesia 分层：system_core 管理应用包（.bpk / manifest / 验签），Runtime 之上是四个对等后端，共享同一套宿主契约。</figcaption>
</svg>
</figure>
<h2 id="33-逐维度对比">3.3 逐维度对比</h2>
<table>
<thead>
<tr>
<th>维度</th>
<th>elf_loader 基座</th>
<th>Brookesia</th>
<th>证据</th>
</tr>
</thead>
<tbody>
<tr>
<td>执行基座</td>
<td>单一（ELF）</td>
<td>四个对等</td>
<td>1.1 / 2.1</td>
</tr>
<tr>
<td>语言扩展方式</td>
<td>新编 <code>.so</code></td>
<td>加后端组件</td>
<td>1.4 / 2.2.3</td>
</tr>
<tr>
<td>宿主能力导出</td>
<td>编译期符号白名单 + <code>nm</code> 生成</td>
<td>运行期 <code>NativeModule</code> 元数据 + 后端翻译</td>
<td>1.4 / 2.2.4</td>
</tr>
<tr>
<td>宿主→app 反向调用</td>
<td>无</td>
<td>有（<code>call_function</code>，ELF 后端不支持）</td>
<td>1.4 / 2.3.1</td>
</tr>
<tr>
<td>app 生命周期管理</td>
<td><code>.so</code> 入口任务；Lua 走作业模型</td>
<td><code>AppState</code> 状态机 + 可选 hook（JS 最全）</td>
<td>1.3.2 / 2.2.2、2.3.2</td>
</tr>
<tr>
<td>多实例隔离</td>
<td>无（单引擎 + 作业槽）</td>
<td><code>AppId</code> + thread-local 上下文</td>
<td>1.5.2 / 2.2.4</td>
</tr>
<tr>
<td>包格式</td>
<td><code>.so</code>/<code>.epm</code>（加密）+ 明文 <code>.lua</code>（两套）</td>
<td><code>.bpk</code>（ZIP + manifest，统一容器）</td>
<td>1.7 / 2.5.2-2.5.3</td>
</tr>
<tr>
<td>完整性/来源验证</td>
<td>无（仅加密）</td>
<td>RSA-PSS/SHA-256 验签（默认开）</td>
<td>1.7 / 2.5.4</td>
</tr>
<tr>
<td>载荷加密</td>
<td><strong>AES-256-CTR（已实现）</strong></td>
<td>官方<strong>未实现</strong></td>
<td>1.7 / 2.5.4</td>
</tr>
<tr>
<td>跨实例/跨进程通道</td>
<td><strong>共享内存 + 字段布局（已实现）</strong></td>
<td>v0.8.0 已移除 TCP RPC，仅进程内</td>
<td>1.6 / 2.4.2</td>
</tr>
<tr>
<td>服务框架</td>
<td>claw agent（Lua + skill，运行期加载）</td>
<td>ServiceBase + schema + 拓扑 + 事件 await（编译期注册）</td>
<td>【待核实】 / 2.4</td>
</tr>
<tr>
<td>事件机制</td>
<td>需自建</td>
<td><code>lib_utils::signal</code> + <code>EventMonitor</code>（schema 校验，可 await）</td>
<td>— / 2.4.2</td>
</tr>
<tr>
<td>依赖拓扑/引用计数</td>
<td>无</td>
<td>有（Kahn 排序 + ref_count 绑定）</td>
<td>— / 2.4.2</td>
</tr>
<tr>
<td>LLM 工具接入</td>
<td>skill 即工具</td>
<td>MCP 工具 = 服务函数封装</td>
<td>【待核实】 / 2.4.5</td>
</tr>
<tr>
<td>沙箱能力</td>
<td>无（native 同地址空间）</td>
<td>JS / WASM 强隔离</td>
<td>1.1 / 2.3</td>
</tr>
<tr>
<td>代码体积控制</td>
<td>已做（-Os + 段裁剪，-53.4%）</td>
<td>每后端一套运行时，体积叠加</td>
<td>1.8 / 2.3.1</td>
</tr>
<tr>
<td>运行内存策略</td>
<td>全 PSRAM（loader 决定）</td>
<td>全 PSRAM（WAMR 分配器决定）</td>
<td>1.3.1 / 2.3.2</td>
</tr>
<tr>
<td>IDF 要求</td>
<td>5.5.4（现状）</td>
<td><strong>6.0~6.2</strong></td>
<td><code>_run_build.bat:4</code> / 2.9.1</td>
</tr>
<tr>
<td>语言标准</td>
<td>C（<code>.so</code> 全 C）</td>
<td>C++23 + Boost</td>
<td>1.5.1 / 2.9.2</td>
</tr>
</tbody>
</table>
<h2 id="34-lua-层的定位差异重点">3.4 Lua 层的定位差异（重点）</h2>
<table>
<thead>
<tr>
<th></th>
<th>elf_loader 基座上的 <code>lua_engine</code></th>
<th>Brookesia <code>runtime_lua</code></th>
</tr>
</thead>
<tbody>
<tr>
<td>形态</td>
<td>常驻引擎（单实例）</td>
<td>每 app 一个 <code>lua_State</code></td>
</tr>
<tr>
<td>脚本角色</td>
<td><strong>作业（job）</strong>：异步、互斥组、状态查询、输出捕获、停止请求</td>
<td><strong>app 本体</strong>：<code>luaL_dofile</code> 执行一次</td>
</tr>
<tr>
<td>内置能力</td>
<td>i2c/mcpwm/storage/json/gpio/crc16/system/esp_heap/shared_memory 9 个模块</td>
<td>无内置模块，全靠宿主注入</td>
</tr>
<tr>
<td>异步</td>
<td>有（<code>lua_async</code>）</td>
<td><strong>不支持异步 native 函数</strong></td>
</tr>
<tr>
<td>生命周期</td>
<td>作业状态机（<code>lua_job_record_t.status</code>）</td>
<td><code>AppState</code>（Unloaded→Loaded→Running→Stopped/Error）</td>
</tr>
<tr>
<td>Lua 版本</td>
<td><strong>5.5</strong></td>
<td><strong>5.5</strong>（同一个 <code>georgik/lua</code> 组件）</td>
</tr>
<tr>
<td>定位类比</td>
<td>更接近 <strong>system_core</strong>（应用服务器/运行时容器）</td>
<td>脚本容器（与 JS/WASM 平级的第四种后端）</td>
</tr>
</tbody>
</table>
<blockquote>
<p>Lua 版本相同这一点值得注意：两个方案底层用的是同一份 Lua 源码（<code>georgik__lua/lua/lua.h:20-22</code> 与 <code>runtime_lua/idf_component.yml:5-7</code> 的 <code>georgik/lua 5.5.*</code>）。差异全在<strong>宿主层设计</strong>，不在语言实现。</p>
</blockquote>
<h2 id="35-双方强项弱项清单">3.5 双方强项/弱项清单</h2>
<h3 id="elf_loader-基座架构强项有依据">elf_loader 基座架构强项（有依据）</h3>
<table>
<thead>
<tr>
<th>强项</th>
<th>依据</th>
</tr>
</thead>
<tbody>
<tr>
<td>ELF 加载链路内聚（加载+重定位+解密+白名单+执行）</td>
<td><code>components/elf_loader/src/esp_elf.c</code>、<code>components/elf_ext/**</code></td>
</tr>
<tr>
<td>端到端加密（AES-256-CTR + <code>ELFC</code> 容器）</td>
<td><code>so_build/lua_engine/CMakeLists.txt:242-254</code>、<code>esp_elf.c:148-153</code></td>
</tr>
<tr>
<td>宿主符号<strong>裁剪</strong>（白名单 + drop-pattern 过滤）</td>
<td><code>elf_ext/CMakeLists.txt:74-95</code>、<code>tools/filter_syms.py</code></td>
</tr>
<tr>
<td>Lua 作业模型（异步/互斥/状态/停止/输出捕获）</td>
<td><code>components/lua_engine/src/lua_async.c</code></td>
</tr>
<tr>
<td>共享内存 + 字段布局（跨 <code>.so</code> 数据通道）</td>
<td><code>components/shared_memory/**</code>、<code>lua_module_shared_memory_lua.c</code></td>
</tr>
<tr>
<td>内置硬件模块（9 个）</td>
<td><code>so_build/lua_engine/CMakeLists.txt:170-178</code></td>
</tr>
<tr>
<td><code>.so</code> 体积优化已落地（-53.4%）</td>
<td>1.8.1</td>
</tr>
</tbody>
</table>
<h3 id="elf_loader-基座架构弱项有依据">elf_loader 基座架构弱项（有依据）</h3>
<table>
<thead>
<tr>
<th>弱项</th>
<th>依据</th>
</tr>
</thead>
<tbody>
<tr>
<td>无反向调用（基座无法调 app 内函数）</td>
<td>1.4</td>
</tr>
<tr>
<td>无沙箱（native 同地址空间，崩溃即整机）</td>
<td>1.3</td>
</tr>
<tr>
<td>无统一包格式/验签（两套分发路径）</td>
<td>1.7</td>
</tr>
<tr>
<td>无多 app 隔离</td>
<td>1.5.2</td>
</tr>
<tr>
<td>新增宿主 API 需重编基座（编译期耦合）</td>
<td>1.4.3</td>
</tr>
</tbody>
</table>
<h3 id="brookesia-强项有依据">Brookesia 强项（有依据）</h3>
<table>
<thead>
<tr>
<th>强项</th>
<th>依据</th>
</tr>
</thead>
<tbody>
<tr>
<td>统一后端抽象 + 插件化</td>
<td>2.2</td>
</tr>
<tr>
<td>反向调用 + app 上下文隔离</td>
<td>2.2.4、2.3.1</td>
</tr>
<tr>
<td><code>.bpk</code> 统一包 + RSA-PSS 验签</td>
<td>2.5.2-2.5.4</td>
</tr>
<tr>
<td>服务框架工程化（schema/拓扑/引用计数/事件 await）</td>
<td>2.4.2</td>
</tr>
<tr>
<td>JS/WASM 沙箱后端</td>
<td>2.3.2</td>
</tr>
<tr>
<td>MCP 工具接入</td>
<td>2.4.5</td>
</tr>
<tr>
<td>HAL 三层与 GUI 解耦、S3 板级配置齐全</td>
<td>2.6</td>
</tr>
</tbody>
</table>
<h3 id="brookesia-弱项有依据">Brookesia 弱项（有依据）</h3>
<table>
<thead>
<tr>
<th>弱项</th>
<th>依据</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>IDF 6.0~6.2 硬门槛</strong></td>
<td>2.9.1</td>
</tr>
<tr>
<td>缺 4 个第一方组件（离线不可构建）</td>
<td>2.1.2</td>
</tr>
<tr>
<td>载荷加密未实现</td>
<td>2.5.4</td>
</tr>
<tr>
<td>跨进程 RPC 已移除</td>
<td>2.4.2</td>
</tr>
<tr>
<td>ELF 后端能力弱于 elf_loader 基座（无 host call/无加密/不可中断）</td>
<td>2.3.1</td>
</tr>
<tr>
<td>0.8.x 频繁 Breaking Change</td>
<td>各 CHANGELOG</td>
</tr>
<tr>
<td>Boost + C++23 + 192 KB 内部 RAM 开销</td>
<td>2.9.2</td>
</tr>
<tr>
<td>无 App Store 实体（仅安装原语）</td>
<td>2.5.5</td>
</tr>
</tbody>
</table>
<hr>
<h1 id="4-可借鉴项与验证计划">4. 可借鉴项与验证计划</h1>
<h2 id="41-零成本借鉴只读源码不改架构">4.1 零成本借鉴（只读源码，不改架构）</h2>
<table>
<thead>
<tr>
<th>借鉴项</th>
<th>参考出处</th>
<th>用途</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>IRuntimeBackend</code> 接口形态</td>
<td><code>runtime_manager/include/brookesia/runtime_manager/backend.hpp:19-62</code></td>
<td>给现有 <code>.so</code> 与 Lua 加统一抽象层</td>
</tr>
<tr>
<td><code>AppState</code> 状态机</td>
<td><code>types.hpp:31-38</code></td>
<td>统一 app/作业状态表达</td>
</tr>
<tr>
<td><code>NativeModule</code>/<code>NativeValue</code> 元数据</td>
<td><code>types.hpp:40-67</code></td>
<td>替代/包装现有编译期符号白名单</td>
</tr>
<tr>
<td><code>.bpk</code> manifest 字段表</td>
<td><code>system_core/include/brookesia/system_core/app/types.hpp:200-245</code></td>
<td>设计自有包格式</td>
</tr>
<tr>
<td>RSA-PSS 验签方案（hash.json + 逐成员 SHA-256）</td>
<td><code>system_core/src/package_release_verify.cpp:24-45, 551-558</code></td>
<td>与现有 AES 加密叠加，补&quot;来源可信&quot;</td>
</tr>
<tr>
<td>服务依赖拓扑排序（Kahn）</td>
<td><code>service_manager/src/service/manager.cpp:750-816</code></td>
<td>服务/模块依赖管理</td>
</tr>
<tr>
<td>schema 校验 + <code>FunctionValue</code> 变体</td>
<td><code>service_manager/include/brookesia/service_manager/function/definition.hpp:49, 147-154</code></td>
<td>服务接口契约化</td>
</tr>
<tr>
<td>JS 后端 Promise 异步桥接</td>
<td><code>runtime_js/src/backend.cpp:412-479</code></td>
<td>优化 <code>lua_async</code> 的宿主回调设计</td>
</tr>
<tr>
<td>Lua 后端闭包注入</td>
<td><code>runtime_lua/src/backend.cpp:93-104</code></td>
<td>优化 Lua 模块绑定写法</td>
</tr>
<tr>
<td>WASM 单桩 + attachment 桥接</td>
<td><code>runtime_wasm/src/backend.cpp:520-523, 627-651</code></td>
<td>未来接 WASM 时的绑定方案</td>
</tr>
<tr>
<td>WAMR AOT 落 PSRAM 配置</td>
<td><code>wasm-micro-runtime/core/shared/platform/esp-idf/shared_platform.cmake:18-22</code>、<code>espidf_memmap.c:20-51</code></td>
<td>引入 WAMR 的关键配置依据</td>
</tr>
</tbody>
</table>
<h2 id="42-需要实测验证的">4.2 需要实测验证的</h2>
<table>
<thead>
<tr>
<th>验证项</th>
<th>方法</th>
<th>预期要回答的问题</th>
</tr>
</thead>
<tbody>
<tr>
<td>WAMR 单独引入（不碰 IDF 6）</td>
<td>依赖 <code>wasm-micro-runtime</code>（idf ≥5.1），照 <code>runtime_wasm/src/backend.cpp:656-735</code> 写加载器</td>
<td>固件增量 / 执行耗时 / PSRAM 峰值 / 加载耗时</td>
</tr>
<tr>
<td>AOT vs interp 在 S3 上的实际表现</td>
<td>用 <code>wamrc</code> 编译同一模块，分别加载</td>
<td>AOT 落 PSRAM 后的 icache 影响、相对 native <code>.so</code> 与 Lua 的比值</td>
</tr>
<tr>
<td>每实例内存默认值是否过大</td>
<td>对比 brookesia 默认 64 KB 栈/256 KB 堆（<code>backend.cpp:682-683</code>）与示例 32 KB/32 KB（<code>external_examples/.../main.c:76-77</code>）</td>
<td>合理的最小配置</td>
</tr>
<tr>
<td><code>.bpk</code> 验签与现有 AES 加密的叠加可行性</td>
<td>参考 <code>package_release_verify.cpp</code> 实现独立验签函数</td>
<td>是否需要在既有 <code>.epm</code> 外层再加签名清单</td>
</tr>
</tbody>
</table>
<h2 id="43-不建议直接采用的部分">4.3 不建议直接采用的部分</h2>
<table>
<thead>
<tr>
<th>项</th>
<th>原因</th>
<th>依据</th>
</tr>
</thead>
<tbody>
<tr>
<td>整体迁移到 Brookesia v0.8</td>
<td>IDF 需升到 6.0~6.2；缺 4 个组件；与自研体系重叠度高</td>
<td>2.9</td>
</tr>
<tr>
<td>替换现有 ELF 加载器为官方 ELF 后端</td>
<td>官方后端无加密、无宿主符号注册、不支持 <code>call_function</code>、不可中断</td>
<td>2.3.1</td>
</tr>
<tr>
<td>用 <code>runtime_lua</code> 替换 <code>lua_engine</code></td>
<td>官方不支持异步 native 函数、无内置硬件模块、每 app 一 state</td>
<td>2.3.2、3.4</td>
</tr>
<tr>
<td>采用编译期静态注册（<code>-u</code> 符号）</td>
<td>会破坏 claw agent 的运行期脚本/技能加载范式</td>
<td>2.2.3</td>
</tr>
<tr>
<td>移除共享内存改用服务框架</td>
<td>v0.8.0 已移除跨进程 RPC，服务框架仅进程内</td>
<td>2.4.2</td>
</tr>
<tr>
<td>使用旧线 <code>esp-brookesia</code> 0.5.0</td>
<td>与 0.8 不同代；UI 资源 MB 级；无 <code>.bpk</code> 能力</td>
<td>2.7</td>
</tr>
</tbody>
</table>
<hr>
<h1 id="5-附录">5. 附录</h1>
<h2 id="51-依据索引">5.1 依据索引</h2>
<h3 id="elf_loader-基座架构">elf_loader 基座架构</h3>
<table>
<thead>
<tr>
<th>主题</th>
<th>关键文件</th>
</tr>
</thead>
<tbody>
<tr>
<td>基座配置</td>
<td><code>bs_hmi_base_s3/sdkconfig</code>、<code>sdkconfig.defaults</code>、<code>partitions.csv</code>、<code>_run_build.bat</code></td>
</tr>
<tr>
<td>固件体积归因</td>
<td><code>build/bs_hmi_base_s3.map</code>、<code>build/analyze_map.py</code>（本次新增的分析脚本）</td>
</tr>
<tr>
<td>ELF 加载</td>
<td><code>components/elf_loader/src/esp_elf.c</code>、<code>esp_elf_adapter.c</code>、<code>src/dlso/dlmod.c</code></td>
</tr>
<tr>
<td>符号导出</td>
<td><code>components/elf_ext/CMakeLists.txt</code>、<code>src/elf_sym_register.c</code>、<code>src/elf_tab_syms.c</code>、<code>tools/filter_syms.py</code></td>
</tr>
<tr>
<td><code>.so</code> 调度/加载</td>
<td><code>components/elf_ext/src/elf_so_loader.c</code>、<code>src/elf_task_api.c</code></td>
</tr>
<tr>
<td>加密</td>
<td><code>so_build/lua_engine/tools/encrypt_so.py</code>、<code>components/elf_ext/src/elf_so_crypt.c</code></td>
</tr>
<tr>
<td>Lua 引擎</td>
<td><code>so_build/lua_engine/CMakeLists.txt</code>、<code>components/lua_engine/src/*.c</code>、<code>components/georgik__lua/lua/*.c</code></td>
</tr>
<tr>
<td>Lua 模块</td>
<td><code>so_build/lua_engine/lua_mods/lua_module_*/src/*.c</code></td>
</tr>
<tr>
<td>共享内存</td>
<td><code>components/shared_memory/src/shared_memory.c</code>、<code>include/shared_memory.h</code>、<code>lua_mods/lua_module_shared_memory/src/*.c</code></td>
</tr>
<tr>
<td>布局登记</td>
<td><code>so_build/bs_hmi_1ch_480x272/main/state_layout.c</code>、<code>main/main.c</code>；<code>so_build/bs_hmi_1ch_320x240/main/*</code></td>
</tr>
<tr>
<td><code>.so</code> 体积分析</td>
<td><code>so_build/lua_engine/build/analyze_so_syms.py</code>（本次新增）</td>
</tr>
<tr>
<td>claw agent</td>
<td><code>doc/so_lua_claw_integration_plan.md</code>【待核实：实现代码位置】</td>
</tr>
</tbody>
</table>
<h3 id="brookesia">Brookesia</h3>
<table>
<thead>
<tr>
<th>主题</th>
<th>关键文件</th>
</tr>
</thead>
<tbody>
<tr>
<td>后端接口</td>
<td><code>ref/brookesia_runtime_manager/include/brookesia/runtime_manager/{backend,types,runtime,host_bridge,function_bridge}.hpp</code></td>
</tr>
<tr>
<td>运行时实现</td>
<td><code>ref/brookesia_runtime_manager/src/{runtime,host_bridge,function_bridge}.cpp</code>、<code>docs/main.md</code></td>
</tr>
<tr>
<td>ELF 后端</td>
<td><code>ref/brookesia_runtime_elf/src/backend.cpp</code>、<code>idf_component.yml</code></td>
</tr>
<tr>
<td>Lua 后端</td>
<td><code>ref/brookesia_runtime_lua/src/backend.cpp</code>、<code>idf_component.yml</code></td>
</tr>
<tr>
<td>JS 后端</td>
<td><code>ref/brookesia_runtime_js/src/backend.cpp</code>、<code>idf_component.yml</code></td>
</tr>
<tr>
<td>WASM 后端</td>
<td><code>ref/brookesia_runtime_wasm/src/backend.cpp</code>、<code>src/private/{import_descriptor,host_utils,native_call_utils}.hpp</code></td>
</tr>
<tr>
<td>WAMR</td>
<td><code>ref/wasm-micro-runtime/build-scripts/esp-idf/wamr/{Kconfig,CMakeLists.txt}</code>、<code>core/shared/platform/esp-idf/*</code>、<code>core/iwasm/aot/*</code>、<code>README.md</code></td>
</tr>
<tr>
<td>服务框架</td>
<td><code>ref/brookesia_service_manager/include/brookesia/service_manager/service/base.hpp</code>、<code>src/service/{base,manager}.cpp</code>、<code>include/brookesia/service_manager/helper/base.hpp</code></td>
</tr>
<tr>
<td>服务契约</td>
<td><code>ref/brookesia_service_helper/include/brookesia/service_helper/**</code></td>
</tr>
<tr>
<td>WiFi 服务范例</td>
<td><code>ref/brookesia_service_wifi/{include,src}/**</code></td>
</tr>
<tr>
<td>Agent</td>
<td><code>ref/brookesia_agent_manager/include/brookesia/agent_manager/{base,manager,state_machine}.hpp</code>、<code>ref/brookesia_service_helper/include/brookesia/service_helper/agent/*.hpp</code></td>
</tr>
<tr>
<td>系统层</td>
<td><code>ref/brookesia_system_core/include/brookesia/system_core/app/{types,package}.hpp</code>、<code>src/app/package.cpp</code>、<code>src/package_release_verify.cpp</code>、<code>Kconfig</code></td>
</tr>
<tr>
<td>HAL</td>
<td><code>ref/brookesia_hal_interface/include/brookesia/hal_interface/**</code>、<code>ref/brookesia_hal_adaptor/CMakeLists.txt</code>、<code>ref/brookesia_hal_boards/boards/**</code></td>
</tr>
<tr>
<td>旧线</td>
<td><code>ref/esp-brookesia/{README.md,CMakeLists.txt,CHANGELOG.md,idf_component.yml,src/systems/phone/**}</code></td>
</tr>
<tr>
<td>依赖与版本</td>
<td>各组件 <code>idf_component.yml</code>、<code>CHANGELOG.md</code></td>
</tr>
</tbody>
</table>
<h2 id="52-待核实清单">5.2 待核实清单</h2>
<table>
<thead>
<tr>
<th>编号</th>
<th>事项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Q1</td>
<td>claw agent 的实现代码位置与能力边界</td>
<td>目前仅见规划文档 <code>doc/so_lua_claw_integration_plan.md</code> 与 skills 目录，未做代码级核对</td>
</tr>
<tr>
<td>Q2</td>
<td><code>so_build/</code> 下 <code>.so</code> 工程的完整清单</td>
<td>已确认 <code>lua_engine</code> / <code>bs_link_hmi</code> / <code>bs_link_scpi</code> / <code>ui_mirror</code> / <code>terminal</code>；<code>bs_hmi_320x240</code> 与 <code>bs_hmi_1ch_{480x272,320x240}</code> 的目录关系需最终核对</td>
</tr>
<tr>
<td>Q3</td>
<td><code>esp-brookesia-toolkit</code> 的 <code>tools/app_pack.py</code></td>
<td>system_core 引用但不在 <code>ref/</code> 中</td>
</tr>
<tr>
<td>Q4</td>
<td><code>brookesia_gui_interface</code> 的实现</td>
<td>system_core 的 public 依赖，未获取</td>
</tr>
<tr>
<td>Q5</td>
<td>WAMR 在 S3 上 AOT 的实测数据</td>
<td>只有配置层面的源码依据，无实测</td>
</tr>
<tr>
<td>Q6</td>
<td><code>esp_elf</code> 组件版本与上游 <code>elf_loader</code> 1.* 的关系</td>
<td>本仓库 <code>components/elf_loader</code> 与 <code>ref/brookesia_runtime_elf/idf_component.yml:5-7</code> 所依赖的 <code>espressif/elf_loader</code> 是否同源同版本，未核对</td>
</tr>
<tr>
<td>Q7</td>
<td>基座固件的日志/断言裁剪收益</td>
<td>曾改配置但构建受阻后已回退（<code>sdkconfig</code> 当前为原始值，见 1.2.1），收益未测出</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="文档变更记录">文档变更记录</h2>
<table>
<thead>
<tr>
<th>版本</th>
<th>日期</th>
<th>变更</th>
</tr>
</thead>
<tbody>
<tr>
<td>v1.1</td>
<td>2026-09-19</td>
<td>术语调整：&ldquo;我方架构&rdquo; → &ldquo;elf_loader 基座架构&rdquo;，并补充命名说明（1 章开头）</td>
</tr>
<tr>
<td>v1.0</td>
<td>2026-09-19</td>
<td>首版：整合本次运行时架构研究（elf_loader 基座 + Brookesia + 对比 + 借鉴项）</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="-相关阅读">📚 相关阅读</h2>
<ul>
<li><a href="https://tech-snippets.xyz/posts/esp32s3-native-wasm-lua-pi-benchmark-2026/">ESP32-S3 三种执行方式效率对比：原生 / WebAssembly / Lua 的 1000 位圆周率对决</a> —— 同一算法三种执行方式的实测性能差距：原生 427ms、WASM 11.4×、Lua 63.9×</li>
</ul>
]]></content:encoded></item></channel></rss>