<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Yvain Zhang</title>
    <description>架构师的成长之路和自我修养。记录系统设计与架构实践，以及阅读和生活中的思考。</description>
    <link>https://xidianedu.cc/</link>
    <atom:link href="https://xidianedu.cc/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Thu, 05 Nov 2026 02:43:41 +0000</pubDate>
    <lastBuildDate>Thu, 05 Nov 2026 02:43:41 +0000</lastBuildDate>
    <generator>Jekyll v3.9.0</generator>
    
      <item>
        <title>从 buffer 的寿命谈平台设计</title>
        <description>&lt;p&gt;把 buffer 的地址送进队列，提交函数返回后就把它归还给池。如果消费者稍后才使用这个地址，期间另一份请求已经覆写了内存，消费者看到的内容就会变。队列正常、线程也在运行，数据仍然可能错。&lt;/p&gt;

&lt;p&gt;这个问题的起点很小，却会牵出一串平台设计问题：队列保存了什么，谁拥有对象，哪一层算完成，出错时谁回收，停止时还欠哪些通知。我把相关机制和实验整理成了 &lt;a href=&quot;/tech/platform/&quot;&gt;平台架构实践&lt;/a&gt;，沿着这些关联继续展开。&lt;/p&gt;

&lt;h2 id=&quot;先把接口的寿命说清楚&quot;&gt;先把接口的寿命说清楚&lt;/h2&gt;

&lt;p&gt;借用、复制与转移会形成不同的责任。借用要求调用者保留对象到规定的完成点；复制可以让原 buffer 更早复用，但需要额外内存与拷贝；转移则要说明成功和失败各由谁释放。&lt;/p&gt;

&lt;p&gt;锁能保护一次访问，接口还需要定义整个异步过程的寿命。&lt;a href=&quot;/tech/linux/mechanisms/03-fd-lifetime/&quot;&gt;fd 与对象寿命&lt;/a&gt;和&lt;a href=&quot;/tech/linux/mechanisms/07-concurrency-ownership/&quot;&gt;队列与所有权&lt;/a&gt;分别用对象关系和执行时序说明这件事。&lt;/p&gt;

&lt;h2 id=&quot;提交成功之后还有几层状态&quot;&gt;“提交成功”之后还有几层状态&lt;/h2&gt;

&lt;p&gt;示例 SDK 提交时复制 payload，并先返回排队 ticket。owner 后续决定接受或拒绝；被接受的请求再进入完成、超时、取消或失败。取消事件进入队列，也不保证抢先于响应。&lt;/p&gt;

&lt;p&gt;这些层次决定了统计、错误处理和停止义务。公平处理预算可以限制一轮事件的工作量，但停止时仍需处理剩余 ticket 的结果通知。&lt;a href=&quot;/tech/linux/cases/01-stop-drain/&quot;&gt;停止收尾案例&lt;/a&gt;给出受控的队列场景与两套守恒关系。&lt;/p&gt;

&lt;h2 id=&quot;再连接到运行时和平台预算&quot;&gt;再连接到运行时和平台预算&lt;/h2&gt;

&lt;p&gt;同一套接受、完成与恢复语义，可以由 Linux 的线程、epoll、eventfd 实现，也可以由 FreeRTOS 的任务、队列与通知实现。共同契约放在哪里、平台机制保留在哪里，会影响移植和验证范围。&lt;a href=&quot;/tech/platform/design/03-linux-freertos/&quot;&gt;双运行时章节&lt;/a&gt;沿着这个问题比较两端实现。&lt;/p&gt;

&lt;p&gt;扩大在途额度还会影响吞吐、排队、尾延迟和停止时间；缩小逻辑额度也不自动缩小固定结构占用。&lt;a href=&quot;/tech/platform/design/06-resource-budget/&quot;&gt;资源预算&lt;/a&gt;把这些约束放到同一张账里，再比较候选方案。&lt;/p&gt;

&lt;p&gt;专题中的章节由具体问题扩展，阅读索引按知识依赖组织。可以从一个案例进入，再追到相关机制；也可以从 C、fd、IO、进程和事件顺着读。&lt;/p&gt;

&lt;p&gt;Linux 的机制与实验整理在 &lt;a href=&quot;/tech/linux/&quot;&gt;Linux 系统实践&lt;/a&gt;，任务、队列与退出整理在 &lt;a href=&quot;/tech/rtos/Practice/&quot;&gt;FreeRTOS 工程实践&lt;/a&gt;。接口契约、预算和跨系统取舍在平台设计中继续展开。&lt;/p&gt;

&lt;p&gt;实验使用独立 Linux 工具容器、FreeRTOS POSIX port 和专用 QEMU 软件设备。源码、命令和结果范围分别见&lt;a href=&quot;/tech/platform/reference/source/&quot;&gt;下载页&lt;/a&gt;、&lt;a href=&quot;/tech/platform/guide/environment/&quot;&gt;环境准备&lt;/a&gt;和&lt;a href=&quot;/tech/platform/reference/verification/&quot;&gt;验证记录&lt;/a&gt;。&lt;/p&gt;
</description>
        <pubDate>Sun, 04 Oct 2026 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/2026/10/04/platform-architecture-practice/</link>
        <guid isPermaLink="true">https://xidianedu.cc/2026/10/04/platform-architecture-practice/</guid>
        
        <category>Linux</category>
        
        <category>系统架构</category>
        
        <category>异步 IO</category>
        
        
      </item>
    
      <item>
        <title>Audio System Atlas：音频系统笔记导读</title>
        <description>&lt;p&gt;我把音频相关的笔记整理成了 &lt;a href=&quot;/tech/audio/&quot;&gt;Audio System Atlas&lt;/a&gt;，按信号、数据、时钟和电源组织，记录各层的工作原理与排查方法。涉及具体芯片的配置，仍需要对照器件手册。&lt;/p&gt;

&lt;h2 id=&quot;这套专题覆盖什么&quot;&gt;这套专题覆盖什么？&lt;/h2&gt;

&lt;p&gt;13 个模块串起音频架构、数字接口、模拟 Codec、时钟、DMA/FIFO、DSP、低功耗、Linux/Android、无线音频、测量调试、系统集成、RTOS 和流式语音；另有跨主题分析、案例与实验。&lt;/p&gt;

&lt;p&gt;各章尽量说明约束、计算方法、负责的软硬件层，以及验证时需要记录什么。&lt;/p&gt;

&lt;h2 id=&quot;三条阅读路线&quot;&gt;三条阅读路线&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;阅读主线&lt;/strong&gt;：从&lt;a href=&quot;/tech/audio/00-Overview/&quot;&gt;总览&lt;/a&gt;建立信号链，再按接口→时钟→缓冲→算法→操作系统阅读。每层都区分 sample、frame、slot 和 byte。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;调试主线&lt;/strong&gt;：从 &lt;a href=&quot;/tech/audio/Case-Studies/06-pcm-clock-buffer-evidence/&quot;&gt;PCM、时钟与缓冲证据链&lt;/a&gt;入手，先算流量与期限，再对齐 XRUN、调度和硬件状态。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;验证主线&lt;/strong&gt;：先看&lt;a href=&quot;/tech/audio/00-Overview/01-review-and-evidence-map/&quot;&gt;掌握标准与证据地图&lt;/a&gt;，选择熟悉的链路，检查假设、取舍、失败条件和验证方法。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;值得深入的几个问题&quot;&gt;值得深入的几个问题&lt;/h2&gt;

&lt;p&gt;音频平均带宽很小，为什么仍会被 DDR 竞争打断？缩小 period 降低的是哪段延迟，又增加了多少通知开销？常开音频的电源轨功率，为什么不能直接换算整机续航？用户打断语音时，为什么取消网络响应还不等于可以清空 DMA 队列？&lt;/p&gt;

&lt;p&gt;对应章节分别讨论服务期限、尾延迟、能量积分和资源所有权。定点 LMS 实验还包括舍入、饱和和累加范围的测试，方便检查数值实现。&lt;/p&gt;

&lt;h2 id=&quot;如何理解当前质量与证据边界&quot;&gt;如何理解当前质量与证据边界？&lt;/h2&gt;

&lt;p&gt;专题区分基础原理、教学参数、模拟案例与可运行实验。教学计算不等于器件实测，示例寄存器与伪代码不能直接移植到目标芯片；实验通过也不代表整套产品完成验证。&lt;/p&gt;

&lt;p&gt;目前仍缺少可公开、带完整测试条件的示波器、逻辑分析仪和 AP 原始记录。测量章节已列出采集清单，后续逐步补充。&lt;/p&gt;

&lt;p&gt;如果刚接触音频，可以先读&lt;a href=&quot;/2022/07/24/digital-audio-basics/&quot;&gt;数字音频基础与处理流程&lt;/a&gt;，再进入 &lt;a href=&quot;/tech/audio/&quot;&gt;Audio System Atlas&lt;/a&gt;。&lt;/p&gt;
</description>
        <pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/2026/09/08/audio-system-atlas/</link>
        <guid isPermaLink="true">https://xidianedu.cc/2026/09/08/audio-system-atlas/</guid>
        
        <category>音频</category>
        
        <category>嵌入式</category>
        
        <category>系统架构</category>
        
        
      </item>
    
      <item>
        <title>具身智能的快慢控制环：实时控制与 VLA 推理如何协作</title>
        <description>&lt;h2 id=&quot;1-物理世界的残酷法则为什么纯软件-agent-无法直接驱动机器人&quot;&gt;1. 模型推理与电机控制的时间要求不同&lt;/h2&gt;

&lt;p&gt;软件任务中的错误也可能造成严重后果。机器人还多了一层物理约束：执行器有惯性，接触过程会产生力，动作发出后不能简单撤销。&lt;/p&gt;

&lt;p&gt;因此，在&lt;strong&gt;具身智能（Embodied Intelligence）&lt;/strong&gt;系统中，需要分别考虑：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;运动约束&lt;/strong&gt;：速度、加速度和力矩必须在机构允许的范围内。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;接触控制&lt;/strong&gt;：碰撞或插接时，控制延迟和过冲可能损伤工件与机构。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;故障响应&lt;/strong&gt;：通信中断、感知失效或模型输出异常时，控制器应有明确的减速、停止或其他安全状态。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;VLA（Vision-Language-Action）模型的动作更新周期通常与电机电流环不同，推理时延也取决于模型、硬件和部署方式。若上层只能约 10Hz 更新动作，就需要底层控制器持续执行反馈控制和插值；不能据此推断所有机器人都会失稳，也不能把模型动作输出直接等同于 PWM。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-解法双速率软硬件控制架构-dual-rate-architecture&quot;&gt;2. 解法：双速率软硬件控制架构 (Dual-Rate Architecture)&lt;/h2&gt;

&lt;p&gt;一种便于讨论的方案，是把较慢的感知与规划和较快的反馈控制分开。下图用 5~20Hz 与 100Hz~1kHz 举例说明分工；它们不是统一指标，电机电流环还可能以更高频率独立运行。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ┌─────────────────────────────────────────────────────────────┐
 │           SLOW COGNITIVE LOOP (慢认知环 · 5Hz ~ 20Hz)         │
 │   - Host: Linux SoC / NPU / Jetson (高算力计算域)           │
 │   - Model: VLA 多模态大模型 (Vision-Language-Action)         │
 │   - Duties: 场景理解、目标位姿估计、动作或轨迹段生成         │
 └──────────────────────────────┬──────────────────────────────┘
                                │
                                │ 共享内存或通信链路
                                │ 下发动作目标，附时间戳、有效期与序号
                                ▼
 ┌─────────────────────────────────────────────────────────────┐
 │           FAST REFLEX LOOP (快反射环 · 100Hz ~ 1kHz)        │
 │   - Host: 裸机固件 / RTOS (FreeRTOS/Zephyr) / 专用 DSP/FPGA │
 │   - Control: 轨迹插值、运动学解算、力矩或阻抗控制           │
 │   - Duties: 本地反馈、限幅、碰撞检测；对接驱动器和急停       │
 └──────────────────────────────┬──────────────────────────────┘
                                │
                                ▼
 ┌─────────────────────────────────────────────────────────────┐
 │        ACTUATORS &amp;amp; SENSORS (物理执行器与传感器硬同步)       │
 │   - 伺服关节电机、力矩传感器、编码器与相机                  │
 └─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-快环fast-reflex-loop确定性硬实时反射&quot;&gt;3. 快环（Fast Reflex Loop）：确定性硬实时反射&lt;/h2&gt;

&lt;h3 id=&quot;31-运行环境与指标&quot;&gt;3.1 运行环境与指标&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;宿主平台&lt;/strong&gt;：Cortex-M7 / Cortex-R52 / 专用实时 DSP / FPGA。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;操作系统&lt;/strong&gt;：裸机、RTOS（FreeRTOS、Zephyr、RT-Thread）或经实时性验证的其他平台。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;执行频率&lt;/strong&gt;：本文以 100Hz~1kHz（周期 1ms~10ms）的运动或力控环举例，具体数值由机构与控制带宽决定。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;实时指标&lt;/strong&gt;：先给出最坏执行时间和抖动预算，再在目标平台测量。例如 $10\mu\text{s}$ 可作为某个项目的抖动目标，不能由 RTOS 名称直接保证。关键路径应避免未受控的动态分配、阻塞通信和不可预测的网络等待。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;32-核心算法栈&quot;&gt;3.2 核心算法栈&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;电机 FOC（磁场定向控制）&lt;/strong&gt;：调节电机的 $I_d, I_q$ 电流分量。电流环通常放在驱动器侧，频率与外层运动控制分别设定。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;逆运动学（IK, Inverse Kinematics）与插值&lt;/strong&gt;：将上层位姿目标转换为关节目标，再进行轨迹插值与速度、加速度限幅。解算时间取决于机构和算法，需要纳入周期预算。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;笛卡尔阻抗控制（Impedance Control）&lt;/strong&gt;：
\(F_{\text{ext}} = K_p (x_{\text{target}} - x) + K_d (\dot{x}_{\text{target}} - \dot{x}) + M (\ddot{x}_{\text{target}} - \ddot{x})\)
该式示意目标位姿与实际位姿之间的虚拟弹簧、阻尼和惯性关系。降低刚度可以增加接触顺应性，但仍需正确的力估计、参数整定和运动限制，不能保证任意轨迹误差下都不损伤机构。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;急停与看门狗（E-Stop &amp;amp; Watchdog）&lt;/strong&gt;：超力、通信失联和执行异常应触发预设的故障处理。若用 300ms 作为上层失联阈值，需根据速度、停止距离与任务风险验证；停止、保持或制动也不能统一等同于“锁轴”。&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-慢环slow-cognitive-loop端侧多模态语义认知&quot;&gt;4. 慢环（Slow Cognitive Loop）：端侧多模态语义认知&lt;/h2&gt;

&lt;h3 id=&quot;41-运行环境与指标&quot;&gt;4.1 运行环境与指标&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;宿主平台&lt;/strong&gt;：端侧高算力 Linux SoC（如搭载专用 NPU 的 SoC、NVIDIA Jetson Orin、端侧 GPU）。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;运行框架&lt;/strong&gt;：按模型算子和硬件支持选择 ONNX Runtime、TensorRT 等推理工具；LLM 部分也可考虑相应服务框架。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;执行频率&lt;/strong&gt;：本文以 5Hz~20Hz（周期 50ms~200ms）举例，实际需要测量端到端时延和最坏情况。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;42-核心职责与模型演进&quot;&gt;4.2 核心职责与模型演进&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;多模态场景理解与 3D 点云处理&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;融合 RGB 相机与激光雷达/结构光深度相机的数据。&lt;/li&gt;
      &lt;li&gt;进行三维语义分割、物体类别识别与 6D 位姿估计（SE(3) Pose Estimation）。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;VLA / 视觉动作策略推理&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;可接收自然语言指令（如“把桌上的红色芯片放入托盘”）与视觉观察，输入形式因模型而异。&lt;/li&gt;
      &lt;li&gt;动作接口可能是末端位姿增量、关节目标或动作片段，夹爪指令与其他参数也需按模型定义适配。例如 &lt;a href=&quot;https://github.com/openvla/openvla&quot;&gt;OpenVLA 示例&lt;/a&gt;输出 7 自由度动作，并接入现有机器人控制栈；不能概括为所有模型都输出路标点和阻抗参数。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;模型量化与端侧加速&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;可评估 INT8 / FP8 量化、注意力优化和动作分块，但要核对硬件支持与动作精度。KV Cache 的存放位置受容量和架构限制，不能默认全部驻留片上 SRAM；优化收益应以目标板卡上的实测为准。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-跨域通信与软硬件协同底座&quot;&gt;5. 跨域通信与软硬件协同底座&lt;/h2&gt;

&lt;p&gt;快环与慢环可能位于同一 SoC 的不同核心，也可能分布在不同板卡上。通信设计要先区分图像、点云等大数据和体积较小的控制指令；后者更关心时效、顺序和失联处理。&lt;/p&gt;

&lt;h3 id=&quot;51-零拷贝跨域共享内存-zero-copy-ipc-via-dma-buf--uio&quot;&gt;5.1 零拷贝跨域共享内存 (Zero-Copy IPC via dma-buf / UIO)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：同一设备中的图像或张量缓冲区，在多个处理模块间传递时可能有较高拷贝开销。控制目标通常较小，不一定需要共享完整点云。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Linux 侧机制&lt;/strong&gt;：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dma-buf&lt;/code&gt; 用于设备驱动间共享缓冲区及同步；&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UIO&lt;/code&gt; 提供设备内存映射与中断的用户态访问方式，二者不是可互换的跨芯片通信协议。参见 &lt;a href=&quot;https://docs.kernel.org/driver-api/dma-buf.html&quot;&gt;dma-buf 文档&lt;/a&gt;和 &lt;a href=&quot;https://docs.kernel.org/driver-api/uio-howto.html&quot;&gt;UIO 文档&lt;/a&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;跨域条件&lt;/strong&gt;：Linux 与 RTOS 共享内存还需约定地址映射、缓存一致性、缓冲区所有权和通知机制。是否能减少拷贝、是否要求物理连续内存，取决于硬件与驱动实现。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;52-微内核实时中间件-zenoh--micro-ros&quot;&gt;5.2 面向受限设备的通信中间件&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;可根据现有 ROS 2 集成、传输链路和资源预算选择 micro-ROS 或 Zenoh-Pico 等方案。micro-ROS 常用的 Micro XRCE-DDS 通过客户端与 Agent 接入 DDS，并不等于微控制器直接运行 Cyclone DDS。见 &lt;a href=&quot;https://github.com/micro-ROS/micro-ros.github.io/blob/master/_docs/concepts/middleware/Micro_XRCE-DDS/index.md&quot;&gt;micro-ROS 中间件说明&lt;/a&gt;。&lt;/li&gt;
  &lt;li&gt;中间件开销只是端到端时延的一部分。序列化、调度、链路和排队都需测量，不能从协议名称推导“纳秒级保证”。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;53-传感器纳秒级硬件时间戳硬同步-hardware-ptp-sync&quot;&gt;5.3 时间戳对齐与硬件触发&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;相机与编码器的采样时间不一致，会给运动中的位姿融合引入误差。误差大小取决于运动速度、曝光过程和时间偏差，5ms 并非统一的失效阈值。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;PTP（IEEE 1588）&lt;/strong&gt;可用于对齐设备时钟，GPIO 触发与硬件锁存可用于关联采样事件。时钟同步精度、触发延迟和实际采样时刻需要分别标定；带纳秒分辨率的时间戳不代表纳秒级同步精度。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;6-典型实战案例高精度芯片引脚插拔与装配&quot;&gt;6. 用芯片插接说明快慢环分工&lt;/h2&gt;

&lt;p&gt;下面是一个流程示例，用来说明接口职责，并非已验证的产线方案：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;慢环感知与规划&lt;/strong&gt;：相机观察插座位置，感知与规划模块生成接近目标；如使用 VLA，也需把输出转换为控制栈支持的动作形式。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;快环执行&lt;/strong&gt;：假设运动控制以 1kHz 更新，控制器进行轨迹插值和速度限幅，驱动器完成更底层的电流控制。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;接触阶段&lt;/strong&gt;：力传感器反馈进入本地控制环，按预设阈值进行顺应调整或停止。是否允许 X/Y 搜索，以及搜索距离和接触力，要根据引脚与插座结构验证。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;状态确认&lt;/strong&gt;：上层结合图像、力或行程等反馈判断插接是否完成，确认后再推进任务。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这种分工让上层推理延迟不直接阻塞底层反馈控制。它能否满足精度和安全要求，还需通过控制稳定性分析、目标平台测量和故障测试来判断。&lt;/p&gt;
</description>
        <pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/geek/embodied/</link>
        <guid isPermaLink="true">https://xidianedu.cc/geek/embodied/</guid>
        
        <category>具身智能</category>
        
        <category>RTOS</category>
        
        <category>嵌入式</category>
        
        <category>VLA</category>
        
        <category>机器人</category>
        
        <category>系统架构</category>
        
        
      </item>
    
      <item>
        <title>Agent 运行时设计笔记：控制循环、参数校验与外部验收</title>
        <description>&lt;h2 id=&quot;1-为什么问答式-llm-无法解决真实工程任务&quot;&gt;1. 让模型输出接上环境反馈&lt;/h2&gt;

&lt;p&gt;模型可以根据输入给出代码和排查建议，但如果没有工具反馈，就无法直接确认文件是否修改、代码是否编译通过，或设备是否处于预期状态。多轮对话可以由应用保存历史，运行状态也需要应用维护。&lt;/p&gt;

&lt;p&gt;在代码重构、固件调试或网络排障中，运行时需要处理几个问题：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;环境反馈&lt;/strong&gt;：把编译、测试或设备查询结果返回给模型，区分建议与已验证事实。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;执行状态&lt;/strong&gt;：记录任务进度、失败原因和下一步动作，限制重复调用和无进展的重试。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;副作用与权限&lt;/strong&gt;：明确工具可访问的路径、可执行的动作，以及哪些操作需要授权或恢复方案。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;本文把 Agent 运行时按目标、上下文、决策、执行、观察和状态更新六个阶段拆开讨论。有限状态机（FSM）可用于规定允许的转移；下面的代码则演示较简化的顺序控制循环，并未实现完整的状态转移表。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ┌──────────────────────────────────────────────────────────────┐
 │               AUTONOMOUS RUNTIME CONTROL LOOP                │
 └──────────────────────────────────────────────────────────────┘
           │
           ▼
   [01. 根目标规范化]  ──&amp;gt; 注入 Step/Token 预算、只读环境约束
           │
           ▼
   [02. 上下文装配]    ──&amp;gt; 前缀缓存 (Prefix Cache) 对齐 + 注意力预算裁剪
           │
           ▼
   [03. 决策推理]      ──&amp;gt; LLM 产生结构化 Tool Call 或完成声明
           │
     ┌─────┴─────────────────────┐
     ▼                           ▼
[Tool Call 命中]           [任务收敛判定]
     │                           │
     ▼                           ▼
[04. 沙箱受控执行]          [最终断言评估]
  - 权限与隔离边界            - 单元测试与构建检查
  - 超时心跳熔断              - 产物完整性验证
  - 破坏性命令拦截                 │
     │                           ▼
     ▼                    [成功终结退出]
[05. 观察提取与清洗]
  - 提取 Exit Code 与 Trace
  - 日志截断与脱敏
     │
     ▼
[06. 状态更新与 Reflexion] ──&amp;gt; 回写工作记忆，策略微调，进入下一轮
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-核心架构三大硬约束公理-runtime-axioms&quot;&gt;2. 三个运行时设计问题&lt;/h2&gt;

&lt;p&gt;设计执行循环时，可以先明确工具范围、状态来源和失败恢复方式。&lt;/p&gt;

&lt;h3 id=&quot;公理一约束优于自由-constraint-over-freedom&quot;&gt;一：限制工具范围与执行预算&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;用 JSON Schema 或 Pydantic 等校验工具参数，在执行前返回类型、必填字段或范围错误。通过校验的参数仍可能在业务语义上不合适。&lt;/li&gt;
  &lt;li&gt;设定 &lt;strong&gt;Step Budget（最大步数限制，如 25 步）&lt;/strong&gt;、Token 和时间预算。预算耗尽时返回未完成状态，而不是继续无上限重试。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;公理二状态显式化-explicit-state-representation&quot;&gt;二：显式记录环境状态&lt;/h3&gt;
&lt;p&gt;运行时可以维护以下状态，并将本轮需要的部分提供给模型：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;当前激活的工作路径&lt;/strong&gt;（Working Directory）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;当前已修改但未提交的文件清单&lt;/strong&gt;（Dirty File List）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;当前步骤消耗与剩余步数&lt;/strong&gt;（Step Counter）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;环境检查的关键断言结果&lt;/strong&gt;（Assertion Status）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;状态应来自实际工具查询或运行时记录，不能只沿用模型的描述。放在动态上下文区域可避免频繁改变静态前缀。&lt;/p&gt;

&lt;h3 id=&quot;公理三工具原子化与回滚守卫-atomic--rollback-guard&quot;&gt;三：定义失败后的恢复方式&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;文件修改可以先创建快照，失败后恢复该步骤触及的文件。恢复时要保留用户原有改动；外部设备写入或网络操作不一定可回滚。&lt;/li&gt;
  &lt;li&gt;命令执行需要持续读取输出、设置超时并回收进程。交互程序可使用 PTY，普通构建也可使用管道；PTY 本身不是安全沙箱。&lt;/li&gt;
  &lt;li&gt;区分可重复执行的幂等操作与有副作用的操作，避免重试时重复提交或写入。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-六阶段状态机执行流详解&quot;&gt;3. 六阶段状态机执行流详解&lt;/h2&gt;

&lt;h3 id=&quot;stage-1-目标规范化-goal--constraints-initialization&quot;&gt;Stage 1: 目标规范化 (Goal &amp;amp; Constraints Initialization)&lt;/h3&gt;
&lt;p&gt;接收用户指令，记录任务目标、验收要求和初始环境信息：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;工作区绝对路径（Workspace Root）&lt;/li&gt;
  &lt;li&gt;权限安全模式（Safe / Approval / Bypass）&lt;/li&gt;
  &lt;li&gt;初始环境快照（Git HEAD Commit）&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;stage-2-上下文装配与预算裁剪-context-assembly&quot;&gt;Stage 2: 上下文装配与预算裁剪 (Context Assembly)&lt;/h3&gt;
&lt;p&gt;上下文装配阶段组织模型请求中的消息：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;稳定前缀（Stable Prefix）&lt;/strong&gt;：包含系统提示词、工具声明和静态规范。保持一致有利于前缀缓存复用，但实际命中还取决于服务的缓存规则。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;近期历史（Recent History）&lt;/strong&gt;：按任务保留最近几轮工具交互，例如 3~4 轮；窗口大小需要结合上下文预算调整。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;历史摘要（Compact Summary）&lt;/strong&gt;：提取较早步骤中的决定、错误与修复记录，例如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[COMPACT: Step 1-3 compile failed with C2065, fixed in Step 4]&lt;/code&gt;。完整记录另存，必要时回查。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;stage-3-模型决策与参数路由-inference--tool-routing&quot;&gt;Stage 3: 模型决策与参数路由 (Inference &amp;amp; Tool Routing)&lt;/h3&gt;
&lt;p&gt;调用模型生成输出。输出通常分为两类：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Tool Use&lt;/strong&gt;：模型识别出需要调用工具获取信息或修改系统。运行时提取 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool_name&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tool_args&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Final Message&lt;/strong&gt;：模型认为任务已达成，输出总结性报告。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;stage-4-沙箱隔离执行-sandboxed-execution&quot;&gt;Stage 4: 沙箱隔离执行 (Sandboxed Execution)&lt;/h3&gt;
&lt;p&gt;工具分发器先校验权限和参数，再执行动作。下面只是流程示意，命令模式匹配不能代替操作系统隔离：&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dispatch_command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeout_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 1. 检查已列出的危险命令模式；可执行文件白名单需另行实现
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;cmd_line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pat&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DANGEROUS_PATTERNS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SECURITY_BLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Security Guard: Dangerous command blocked.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 2. 独立会话进程组隔离运行 (start_new_session=True 或 os.setsid)
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 3. 管道数据超时轮询读取防死锁，超时触发整组 killpg 级联终止
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;stage-5-观察清洗与确定性断言-observation--assertion&quot;&gt;Stage 5: 观察清洗与确定性断言 (Observation &amp;amp; Assertion)&lt;/h3&gt;
&lt;p&gt;工具执行后，可以从长日志中提取本轮需要的信息：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;剥离无用的进度条文本（如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[===&amp;gt;    ] 34%&lt;/code&gt;）。&lt;/li&gt;
  &lt;li&gt;提取非零退出码和包含 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;error:&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fatal:&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;panic&lt;/code&gt; 的核心错误堆栈。&lt;/li&gt;
  &lt;li&gt;运行针对性检查：例如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python -m py_compile&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc -fsyntax-only&lt;/code&gt;。语法检查只能说明对应检查通过，功能正确性还需测试或其他验收。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;stage-6-状态流转与-reflexion-反思-state-transition&quot;&gt;Stage 6: 状态流转与 Reflexion 反思 (State Transition)&lt;/h3&gt;
&lt;p&gt;将清洗后的结构化观察回写进会话记忆：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;若观察表明操作成功，推进子任务进度表。&lt;/li&gt;
  &lt;li&gt;若操作失败，可以要求模型说明下一轮排查依据：
    &lt;blockquote&gt;
      &lt;p&gt;“上一步失败的原因是什么？当前的假设错在哪里？下一步应当如何调整策略？”&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-控制循环参考骨架实现python-核心状态机与进程安全守卫&quot;&gt;4. 控制循环参考骨架实现：Python 核心状态机与进程安全守卫&lt;/h2&gt;

&lt;p&gt;本节代码展示参数检查、历史裁剪、子进程调用和外部验收如何接到同一循环。它是参考骨架，需要补上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llm_client&lt;/code&gt;、工具注册和验收器才能使用。&lt;/p&gt;

&lt;p&gt;阅读时有几个实现边界要分清：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max_tokens&lt;/code&gt; 尚未参与实际计数；&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prune()&lt;/code&gt; 丢弃较早历史并插入固定提示，并没有生成内容摘要；参数检查只覆盖部分字段类型，不是完整 JSON Schema 校验。进程组便于终止同组进程，但不限制文件或网络权限，脱离该组的后代也不在清理范围内。管道 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll()&lt;/code&gt; 的超时不等于整个接收过程都有同样的期限。代码依赖 Unix 进程机制，其他启动方式需要调整。&lt;/p&gt;

&lt;p&gt;实际部署还需补充权限隔离、输出限制、完整超时处理和任务状态持久化，不能把示例中的命令正则当作安全边界。&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
Minimal Autonomous Agent Runtime Skeleton (可终止进程执行与契约校验参考实现)
Author: Yvain Zhang
Architecture: ReAct FSM + Context Budget + Schema Validation + Process Watchdog + External Verifier
Note: 用于阅读控制流程；权限隔离、完整预算与超时处理需另行实现。
&quot;&quot;&quot;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;re&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;signal&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;multiprocessing&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mp&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dataclasses&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataclass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Enum&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Callable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Enum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;SUCCESS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SUCCESS&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;FAILURE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FAILURE&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;TIMEOUT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;TIMEOUT&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;VALIDATION_ERROR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;VALIDATION_ERROR&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;SECURITY_BLOCK&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SECURITY_BLOCK&quot;&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataclass&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataclass&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ToolSpec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# JSON Schema 格式参数契约
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Callable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[...,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;is_destructive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sanitize_timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout_val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;30.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;300.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;校验并归一化超时参数，防止 null、非法字符串或负值导致看门狗崩溃&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeout_val&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default_sec&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout_val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default_sec&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default_sec&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validate_schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;轻量级参数契约校验器：先验证 args 为字典对象，再检查必填项与字段类型，拦截非法入参&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;参数对象为空 (null)，预期为包含工具入参的 JSON 字典对象&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;参数格式非法: 预期为字典 (JSON Object)，实际传入 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;缺少必填参数 &apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;type_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;integer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;number&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;boolean&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;expected_type_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;expected_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected_type_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_type_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;integer&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;参数 &apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos; 应为 integer，不能传入 bool&quot;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_type&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;参数 &apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos; 类型错误: 预期 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected_type_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;，实际为 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ContextBudgetManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;按近期轮数裁剪历史；未实现 Token 计数或历史内容摘要&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_tokens&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;128000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keep_recent_turns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_tokens&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_tokens&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keep_recent_turns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keep_recent_turns&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keep_recent_turns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 保持前缀不可变 (System Prompt + 根目标)，最大化 Prefix Cache 命中
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;recent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keep_recent_turns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;compact_summary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[SYSTEM COMPACT: 前序探索步骤已折叠。请专注于当前激活的任务分支与测试断言。]&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compact_summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recent&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_kill_process_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;尝试终止 worker 及同组进程；不覆盖脱离该进程组的后代&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;parent_pgid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getpgrp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 1. 尝试向 worker 建立的独立进程组发送 SIGTERM（优雅终止）
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 若 worker 的 os.setsid() 成功，其 PGID 等于 pid
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent_pgid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;killpg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SIGTERM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ProcessLookupError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PermissionError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 兜底直接向 worker 进程发送 SIGTERM
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;terminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 给予短暂优雅退出窗口
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.05&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 2. 再向该进程组发送 SIGKILL
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 同组内忽略 SIGTERM 的后代进程也会收到该信号
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent_pgid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;killpg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SIGKILL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ProcessLookupError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PermissionError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 兜底对 worker 发送 SIGKILL
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_alive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.05&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ToolDispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;部分参数类型校验、进程组执行与超时检查示例；未实现权限沙箱&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolSpec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dangerous_patterns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;\brm\s+-rf\s+/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IGNORECASE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;\bmkfs(\.\w+)?\b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IGNORECASE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;\bdd\s+if=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IGNORECASE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;:\(\)\{.*\}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# fork bomb
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolSpec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeout_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;30.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allow_destructive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FAILURE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;未注册的工具: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# 1. 契约校验：在调用前拦截 null、非对象或缺失必填项的参数
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;schema_err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validate_schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;schema_err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VALIDATION_ERROR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;参数契约校验失败: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;schema_err&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# 2. 超时参数归一化与破坏性操作安全检查
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;clean_timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sanitize_timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_destructive&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allow_destructive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SECURITY_BLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;126&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;安全阻断: 工具 &apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos; 涉及破坏性操作，未获显式授权。&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pat&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dangerous_patterns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SECURITY_BLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;126&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;安全阻断: 检测到高危指令模式 &apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# 3. 在 worker 进程中执行工具，并尝试建立独立进程组
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fork&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hasattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fork&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;parent_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;child_conn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_worker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# 脱离父会话成为独立 Process Group Leader，使后续派生的 shell/子命令归入同组
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setsid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_worker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;child_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 父进程关闭子端，防止句柄泄露
&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# 等待管道可读；后续 recv 的完整读取还需单独处理超时与输出上限
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clean_timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# 等待超时：尝试终止 worker 及其同组进程
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;_kill_process_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;parent_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TIMEOUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;124&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;工具执行超时 (超过 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clean_timeout&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; 秒)，已尝试终止工具进程及其同进程组内的子进程。&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# 管道就绪后立即读取排空数据，解除 worker 端 send 阻塞，随后回收进程
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;parent_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_alive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;_kill_process_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SUCCESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FAILURE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;EOFError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;parent_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_kill_process_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FAILURE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exitcode&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;工具进程异常退出 (exit code: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exitcode&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;)，未接收到返回数据。&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;parent_conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_kill_process_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FAILURE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AutonomousRunner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Agent 主控制循环：感知 -&amp;gt; 推理 -&amp;gt; 执行 -&amp;gt; 观察 -&amp;gt; 外部独立验收&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;llm_client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolDispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;verifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Callable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_steps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;llm_client&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dispatcher&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dispatcher&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;verifier&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 外部验收器，检查结果是否符合任务要求
&lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;budget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ContextBudgetManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_steps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_steps&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;execute_goal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;goal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;system_prompt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;system_prompt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;目标任务: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;goal&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;规则: 请逐步执行。只有当客观验收断言真正通过后，任务方可结束。&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_steps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# 1. 缓存对齐与上下文裁剪装配
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;active_context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;budget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prune&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;# 2. 大模型决策推理
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;generate_decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active_context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;# 3. 模型声明完成后，调用外部验收器；未配置时返回未验证状态
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;is_complete&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verifier&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SUCCESS_UNVERIFIED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&quot;steps&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&quot;output&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;final_summary&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&quot;warning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;未配置独立验证器，结果未经验收断言&quot;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

                &lt;span class=&quot;c1&quot;&gt;# 运行外部独立断言器（如 make test / pytest / 物理硬件状态查询）
&lt;/span&gt;                &lt;span class=&quot;n&quot;&gt;verify_res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;verify_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ToolStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SUCCESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SUCCESS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;steps&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;output&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;final_summary&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;c1&quot;&gt;# 将验收失败结果加入上下文，进入下一轮修正
&lt;/span&gt;                    &lt;span class=&quot;n&quot;&gt;obs_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                        &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[第 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; 步独立验收失败] 退出码: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verify_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
                        &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;断言报错: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verify_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;verify_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
                        &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;系统判定: 任务尚未完成，模型不可提前声明成功。请根据客观报错修正并重新执行。&quot;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)})&lt;/span&gt;
                    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obs_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;# 4. 工具分发执行
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;tool_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tool_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tool_args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tool_args&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 保留原始值，交由 dispatcher 严格校验
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;timeout_sec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;timeout_sec&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;30.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tool_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tool_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tool_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeout_sec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;# 5. 观察清洗与结构化记忆追加
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;obs_preview&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tool_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tool_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[无标准输出]&quot;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;obs_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[第 &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; 步观察] 状态: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tool_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, 返回码: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tool_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exit_code&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;输出截取: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obs_preview&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tool_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;obs_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;错误跟踪: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tool_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;

            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)})&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obs_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;BUDGET_EXHAUSTED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;steps&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_steps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;超出最大步数预算，系统未能在限制步数内收敛。&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-总结与工程落地建议&quot;&gt;5. 从小范围任务开始验证&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;限制初始范围&lt;/strong&gt;：可先选择只读排查、测试运行或单文件修复，检查循环是否能正确处理成功、失败和预算耗尽。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;按任务定义验收&lt;/strong&gt;：编译和测试的 exit 0 是证据之一，还要确认检查覆盖了任务要求，并记录未验证部分。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;按复用需求组织工具&lt;/strong&gt;：需要被多个客户端调用的工具可用 MCP 暴露，本地函数也适合小范围实验。&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Tue, 25 Aug 2026 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/geek/runtime/</link>
        <guid isPermaLink="true">https://xidianedu.cc/geek/runtime/</guid>
        
        <category>AI</category>
        
        <category>Agent</category>
        
        <category>系统架构</category>
        
        <category>运行时</category>
        
        <category>Python</category>
        
        
      </item>
    
      <item>
        <title>上下文工程笔记：前缀缓存、长上下文与记忆分层</title>
        <description>&lt;h2 id=&quot;1-范式跃迁从-prompt-engineering-到-context-engineering&quot;&gt;1. 从提示词到整轮任务的上下文&lt;/h2&gt;

&lt;p&gt;给模型写清楚目标、约束和示例，是提示词工程的一部分。任务进入多轮执行后，还会增加工具输出、修改记录、环境状态和历史决策。此时需要考虑的不只是某一句提示词，而是每次请求应该带上哪些信息。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;上下文工程（Context Engineering）&lt;/strong&gt;关注这些信息的选择、排序、压缩和更新。它包含提示词设计，也涉及检索、工具接口和运行时状态管理。本文按这几个问题整理一种实现思路。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;维度&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;提示词设计&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;多轮上下文管理&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;组织对象&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;指令、约束、Few-shot 示例&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;当前状态、历史消息、检索结果、工具输出&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;常见调整&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;澄清歧义，补充必要示例&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;分配 Token 预算，压缩日志，保留相关证据&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;验证方式&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;检查回答是否满足要求&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;同时检查任务完成情况、时延与成本&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;相互关系&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;是模型输入的一部分&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;决定提示词和其他信息如何一起进入请求&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-物理成本attention-机制与-kv-cache-的底层制约&quot;&gt;2. 物理成本：Attention 机制与 KV Cache 的底层制约&lt;/h2&gt;

&lt;p&gt;上下文长度会影响计算量和缓存占用，需要先区分预填充（Prefill）与逐 Token 解码（Decode）。&lt;/p&gt;

&lt;h3 id=&quot;21-计算复杂度与内存墙&quot;&gt;2.1 计算复杂度与内存墙&lt;/h3&gt;
&lt;p&gt;对于标准稠密自注意力，预填充阶段需要计算 Token 之间的相关性：
\(\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V\)
其中注意力部分的计算量随序列长度近似平方增长，KV Cache 占用通常随长度线性增长。这不等于总推理时延必然按平方增长：模型结构、注意力实现、批处理和缓存命中都会影响结果。Agent 的工具日志若持续累积，会增加请求开销，也可能挤占并发请求可用的缓存空间。&lt;/p&gt;

&lt;h3 id=&quot;22-prefix-prompt-caching-的工业级落地&quot;&gt;2.2 前缀缓存如何复用计算&lt;/h3&gt;
&lt;p&gt;支持 &lt;strong&gt;Prefix Caching（前缀缓存）&lt;/strong&gt;的服务可以复用相同输入前缀的 KV Cache，减少这部分的预填充计算。以 vLLM 为例，缓存不会加速新 Token 的解码阶段。具体命中规则和生命周期应查看所用服务的文档。见 &lt;a href=&quot;https://docs.vllm.ai/en/latest/features/automatic_prefix_caching/&quot;&gt;vLLM 前缀缓存说明&lt;/a&gt;。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ┌─────────────────────────────────────────────────────────────┐
 │  Stable Shared Prefix (Cache Hit: Reuse Prefill Results)   │
 ├─────────────────────────────────────────────────────────────┤
 │ [System Prompt] ── [Tool Declarations] ── [Core Constraints]│
 └─────────────────────────────────────────────────────────────┘
                                │
                                ▼
 ┌─────────────────────────────────────────────────────────────┐
 │  Dynamic Volatile Suffix (Sliding Window &amp;amp; Recent Steps)    │
 ├─────────────────────────────────────────────────────────────┤
 │ [Working Scratchpad] ── [Step History] ── [Tail Assertion]  │
 └─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;一种便于缓存复用的组织方式&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;将稳定的系统提示词、代码规范和工具声明放在前面，并保持序列化顺序一致。&lt;/li&gt;
  &lt;li&gt;将时间戳、当前步骤和会话状态放在后面。前缀变化会缩短可复用的部分，但不一定使变化位置之前的缓存失效。&lt;/li&gt;
  &lt;li&gt;用实际请求测量命中率、首字延迟（TTFT）和成本。缓存粒度、最小长度、有效期和计费方式因服务而异，不宜套用一个固定折扣。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-注意力衰减与迷失在中间-lost-in-the-middle&quot;&gt;3. 长上下文中的信息位置&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/2307.03172&quot;&gt;Lost in the Middle&lt;/a&gt; 在多文档问答和键值检索实验中观察到：相关信息的位置会影响回答表现，放在开头或结尾时往往优于放在中间。这是特定模型和任务上的表现曲线，不能直接解释为所有 Transformer 的注意力权重都固定呈 U 型。&lt;/p&gt;

&lt;p&gt;下面只示意这种位置效应，不表示实测数值：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; Retrieval Performance (schematic)
   ▲
1.0│ *                                                  *
   │  *                                                *
0.5│   *                                              *
   │    *                                            *
   │     * * * * * * * * * * * * * * * * * * * * * *
0.0└───────────────────────────────────────────────────────►
   Start (Prefix)           Middle (Lost)          End (Tail)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;应对策略尾部强制回填-tail-re-anchoring&quot;&gt;可尝试的办法：在尾部重述当前状态&lt;/h3&gt;
&lt;p&gt;可以在请求末尾增加简短的当前目标与预算提示，例如：&lt;/p&gt;
&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[CURRENT CRITICAL ANCHOR]
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Ultimate Target: Complete Wi-Fi driver packet trace analysis.
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Step Budget: 18 / 25 consumed.
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Rule: Before claiming SUCCESS, you MUST run &lt;span class=&quot;sb&quot;&gt;`./tests/verify.sh`&lt;/span&gt; and verify exit code 0.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这样便于模型看到本轮状态，但是否改善任务表现仍需验证。权限和验收规则还应由运行时执行，不能只靠重复提示。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-三层记忆体系分级架构-layered-memory-hierarchy&quot;&gt;4. 三层记忆体系分级架构 (Layered Memory Hierarchy)&lt;/h2&gt;

&lt;p&gt;可以借用 L1 Cache / L2 Cache / 主存的分层概念，将信息分为当前状态、近期历史和跨会话记录。这里的 L1/L2/L3 是便于讨论的命名，并非 Agent 必须采用的标准架构：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ┌──────────────────────────────────────────────────────────────┐
 │ L1: Working Scratchpad (工作记忆)                            │
 │ - 当前执行步骤的状态机寄存器、待办列表、局部环境变量           │
 │ - 放在动态上下文区域，随步骤更新，完成后移出活跃状态        │
 └──────────────────────────────────────────────────────────────┘
                                ▲
                                │ 状态提炼与压缩
                                ▼
 ┌──────────────────────────────────────────────────────────────┐
 │ L2: Ephemeral Sliding Buffer (短暂会话缓冲)                  │
 │ - 最近 3~5 轮交互历史与直接工具返回结果                       │
 │ - 超出步数阈值执行结构化有损压缩（只保留 Exit Code 与错误行）   │
 └──────────────────────────────────────────────────────────────┘
                                ▲
                                │ 经验沉淀与向量召回
                                ▼
 ┌──────────────────────────────────────────────────────────────┐
 │ L3: Semantic &amp;amp; Episodic Memory (长期语义与情景记忆)          │
 │ - 本地向量数据库 (Chromadb/Qdrant) + 知识图谱               │
 │ - 跨会话沉淀历史排错反思、代码模式与领域规范                 │
 └──────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;41-l1-工作记忆-working-scratchpad&quot;&gt;4.1 L1 工作记忆 (Working Scratchpad)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;记录当前目标、子步骤列表（Checklist）、当前假设和已验证状态。&lt;/li&gt;
  &lt;li&gt;尽量保持简短，容量根据任务设定；不要为了固定 Token 上限删掉必要约束。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;42-l2-短暂滑动缓冲-ephemeral-buffer&quot;&gt;4.2 L2 短暂滑动缓冲 (Ephemeral Buffer)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;保存最近的执行动作与工具输出。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;输出清洗与压缩&lt;/strong&gt;：例如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; 产生 5000 行输出时，可以先保留构建概况、退出码和关键错误行，完整日志另存。简单截取前 20 行与后 50 行适合作为起点，但可能漏掉中间的首个错误，需要按日志格式调整。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;43-l3-长期情景记忆-episodic-memory&quot;&gt;4.3 L3 长期情景记忆 (Episodic Memory)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;保存经过核对的排查结论、修复 Diff、适用版本和来源，可通过向量 embedding 或关键词索引检索。&lt;/li&gt;
  &lt;li&gt;遇到相似的内核崩溃（如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kernel panic - not syncing: Fatal exception in interrupt&lt;/code&gt;）时，将历史记录作为参考召回；相似报错不代表同一原因，还要重新验证。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-分层子代理-hierarchical-subagent-dag&quot;&gt;5. 分层子代理 (Hierarchical Subagent DAG)&lt;/h2&gt;

&lt;p&gt;任务涉及很多源文件和规范时，搜索结果可能占用主会话的大部分上下文。是否需要拆分，应看信息相关性和任务边界，而非固定的文件数量。&lt;/p&gt;

&lt;h3 id=&quot;认知过载的表象&quot;&gt;需要留意的表现&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;回答遗漏先前约束。&lt;/li&gt;
  &lt;li&gt;重复调用工具，却没有新的证据或进展。&lt;/li&gt;
  &lt;li&gt;声称文件已修改，但实际 Diff 中没有对应变化。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;终极解法父子代理拓扑解耦&quot;&gt;将独立任务交给子代理&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                   ┌───────────────────────┐
                   │  Parent Agent (主代理) │
                   │  - 掌控全局任务计划    │
                   │  - 维持最终验收断言    │
                   └───────────┬───────────┘
                               │
            ┌──────────────────┼──────────────────┐
            │ 派发临时子任务    │ 派发临时子任务    │ 派发临时子任务
            ▼                  ▼                  ▼
     ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
     │ Subagent A  │    │ Subagent B  │    │ Subagent C  │
     │ 代码全局检索│    │ 单元测试构建│    │ 文档规范查阅│
     └──────┬──────┘    └──────┬──────┘    └──────┬──────┘
            │                  │                  │
            │ 回传结构化结论   │ 回传结构化结论   │ 回传结构化结论
            ▼                  ▼                  ▼
     [返回摘要与来源]   [返回摘要与来源]   [返回摘要与来源]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;独立上下文&lt;/strong&gt;：子代理承担搜索或文档阅读，主会话不必接收全部中间输出。子会话是否保留、能否恢复，由具体运行时决定。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;摘要与来源&lt;/strong&gt;：返回符号位置、结论和未确认项，主代理必要时回读原文。摘要会丢失细节，多个子代理也会增加调用成本；共享文件的编辑还需协调。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;6-总结系统级上下文管理清单&quot;&gt;6. 实现时的检查清单&lt;/h2&gt;

&lt;p&gt;下面这些问题可以帮助检查上下文是否服务于当前任务：&lt;/p&gt;
&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;&lt;strong&gt;稳定前缀&lt;/strong&gt;：系统提示词与工具声明能否保持一致，缓存是否实际命中？&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;&lt;strong&gt;工具输出&lt;/strong&gt;：摘要是否保留关键错误和来源，完整日志是否可回查？&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;&lt;strong&gt;当前状态&lt;/strong&gt;：目标、已完成步骤和剩余预算是否明确？&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;&lt;strong&gt;任务拆分&lt;/strong&gt;：独立搜索是否适合交给子代理，返回结论是否可核对？&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;&lt;strong&gt;验收机制&lt;/strong&gt;：是否有覆盖任务要求的测试或其他外部检查？&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 18 Aug 2026 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/geek/context/</link>
        <guid isPermaLink="true">https://xidianedu.cc/geek/context/</guid>
        
        <category>AI</category>
        
        <category>上下文工程</category>
        
        <category>KV Cache</category>
        
        <category>系统架构</category>
        
        <category>大模型</category>
        
        
      </item>
    
      <item>
        <title>终端 Coding Agent：Claude Code、Aider 与 MCP 的机制和取舍</title>
        <description>&lt;h2 id=&quot;1-终端原生-agent-为何成为高级工程师的首选&quot;&gt;1. 终端 Agent 适合哪些开发任务？&lt;/h2&gt;

&lt;p&gt;AI 编程工具既有行内补全、对话式编辑，也有能调用工具的 Agent。它们可以出现在 IDE、终端或远程服务中，界面形态并不能直接决定能力。&lt;/p&gt;

&lt;p&gt;终端 Agent 的实用之处，是能把检索、编辑、构建和测试接到同一轮任务里。例如先用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ripgrep&lt;/code&gt; 定位符号，修改文件，运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt;，再根据报错继续调整。本文关注支撑这一过程的运行环境（Harness）：工具接口、上下文管理和权限控制。&lt;/p&gt;

&lt;p&gt;对于已经依赖命令行的工程，终端入口有几个方便之处：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;沿用现有工具链&lt;/strong&gt;：Makefile、CMake、GDB、Cargo 和 Docker 等工具不必另写一套接口。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;便于审查改动&lt;/strong&gt;：用 Git 查看 Diff、隔离分支和撤销已记录的修改；未跟踪文件与外部副作用仍需单独处理。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;适合远程与自动化任务&lt;/strong&gt;：可用于 SSH 开发机和 CI/CD，但要配置非交互模式、凭据和执行权限。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-三大主流终端-agent-核心架构横向剖析&quot;&gt;2. 几类编程 Agent 的实现侧重点&lt;/h2&gt;

&lt;p&gt;下面选取几款工具，观察它们如何组织代码上下文和修改流程。OpenCode 有终端入口，Cline 与 Roo Code 主要作为 IDE 扩展；这里把它们放在一起讨论工具接入方式。功能会随版本变化，不能把这张表当作性能排名。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ┌─────────────────────────────────────────────────────────────┐
 │                  CLI CODING HARNESS MATRIX                  │
 ├─────────────────────────────────────────────────────────────┤
 │ Claude Code       │ Aider               │ OpenCode / Cline  │
 ├───────────────────┼─────────────────────┼───────────────────┤
 │ 上下文压缩        │ Tree-sitter RepoMap │ MCP 工具接入      │
 │ Subagent 分工     │ Git 自动提交        │ 多模型配置        │
 │ 权限与工具管理    │ 多种编辑格式        │ 操作确认机制      │
 └─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;21-claude-codeanthropic-官方-cli&quot;&gt;2.1 Claude Code（Anthropic 官方 CLI）&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;实现侧重点&lt;/strong&gt;：围绕终端任务组织文件读写、命令执行、上下文管理和权限检查。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;值得关注的机制&lt;/strong&gt;：
    &lt;ol&gt;
      &lt;li&gt;&lt;strong&gt;上下文压缩&lt;/strong&gt;：历史较长时压缩会话，保留任务信息。压缩会丢失细节，重要约束仍需检查。&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Subagent 分工&lt;/strong&gt;：子代理使用独立上下文完成搜索等任务，再向主会话返回摘要。工具访问范围和权限可以单独配置，并非所有子代理都只读。&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;工具执行反馈&lt;/strong&gt;：读取构建与测试结果，继续修改。是否成功仍取决于任务、模型和验收覆盖范围。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这些机制可参照 &lt;a href=&quot;https://code.claude.com/docs/en/how-claude-code-works&quot;&gt;Claude Code 运行方式&lt;/a&gt;和&lt;a href=&quot;https://code.claude.com/docs/en/sub-agents&quot;&gt;子代理文档&lt;/a&gt;。&lt;/p&gt;

&lt;h3 id=&quot;22-aider开源社区标杆&quot;&gt;2.2 Aider（开源编程助手）&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;实现侧重点&lt;/strong&gt;：用代码地图补充上下文，并通过 Git 记录修改。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;值得关注的机制&lt;/strong&gt;：
    &lt;ol&gt;
      &lt;li&gt;&lt;strong&gt;Tree-sitter 代码地图（Repo Map）&lt;/strong&gt;：提取代码符号，结合引用关系排序，在预算内选择相关内容。它提供的是仓库摘要，并不等于把全部调用关系都送给模型；大小可通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--map-tokens&lt;/code&gt; 配置。见 &lt;a href=&quot;https://aider.chat/docs/repomap.html&quot;&gt;Repo Map 文档&lt;/a&gt;。&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Git 集成&lt;/strong&gt;：默认会自动提交 Aider 的修改，也可以关闭。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/undo&lt;/code&gt; 用于撤销最近一次由 Aider 产生的提交，使用前应确认工作区状态。见 &lt;a href=&quot;https://aider.chat/docs/git.html&quot;&gt;Git 集成文档&lt;/a&gt;。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;23-opencode--cline--roo-code&quot;&gt;2.3 OpenCode / Cline / Roo Code&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;实现侧重点&lt;/strong&gt;：模型选择、外部工具接入和操作确认。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;选型时需要核对&lt;/strong&gt;：
    &lt;ol&gt;
      &lt;li&gt;&lt;strong&gt;MCP 接入&lt;/strong&gt;：能否连接所需的 MCP Server，例如抓包分析器、任务看板或数据库工具，以及是否支持其传输方式和认证要求。&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;操作确认&lt;/strong&gt;：文件写入、命令执行的审批粒度，是否能暂停任务，以及如何限制自动执行范围。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-代码修改策略diff-strategy三大流派评测&quot;&gt;3. 三种代码修改策略（Diff Strategy）&lt;/h2&gt;

&lt;p&gt;模型生成改动后，运行时还要把它准确应用到文件。常见方式有全文件重写、标准补丁和搜索替换块：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  Strategy 1: Whole File Rewrite (全量重写)
    [源文件完整代码] ──&amp;gt; 模型重新生成全部代码 ──&amp;gt; 覆盖写入
    * 风险：输出随文件体积增长，长文件可能被截断或遗漏未修改的内容。

  Strategy 2: Unified Diff (标准补丁)
    --- a/file.c
    +++ b/file.c
    @@ -45,6 +45,7 @@
    * 风险：差异块格式、上下文或行号错误可能使补丁无法应用。

 Strategy 3: Search &amp;amp; Replace Block (搜索替换块)
   &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; SEARCH
   static int wifi_probe(...) {
       init_bus();
   =======
   static int wifi_probe(...) {
       init_bus();
       setup_dma_ring();
   &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; REPLACE
   * 特点：通过原文定位修改，需检查搜索块是否唯一匹配。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;代码修改策略的工程权衡与失效机理&quot;&gt;代码修改策略的工程权衡与失效机理&lt;/h3&gt;

&lt;p&gt;三种格式各有适用范围。补丁能否应用、改动是否正确，是两个需要分别验证的问题：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;差异策略&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;机制特征&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Token 相对开销&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;核心失效模式与风险&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;推荐适用场景&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Whole File&lt;/strong&gt;&lt;br /&gt;(全量重写)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;输出修改后的完整文件&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;随文件大小增长&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;截断或省略未改动内容可能导致覆盖错误&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;小文件、创建新文件或大幅改写&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Unified Diff&lt;/strong&gt;&lt;br /&gt;(标准 Patch)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;输出带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@@ -x,y +a,b @@&lt;/code&gt; 的差异块&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;通常较低&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;格式、上下文或行号不一致可能导致应用失败；补丁工具通常有一定偏移匹配能力&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;已有补丁校验与应用流程的系统&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Search / Replace&lt;/strong&gt;&lt;br /&gt;(上下文锚点替换)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;输出原文片段与替换内容&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;取决于定位上下文长度&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;重复代码产生歧义时，需要扩大搜索块；原文件已变化时也会失败&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;需要按原文定位的局部修改&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-model-context-protocol-mcp-标准化工具生态落地&quot;&gt;4. Model Context Protocol (MCP) 标准化工具生态落地&lt;/h2&gt;

&lt;p&gt;不同 Agent 框架的工具接口往往需要单独适配。&lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; 提供了一种共享资源、工具和提示模板的协议，便于支持它的客户端复用外部服务。&lt;/p&gt;

&lt;h3 id=&quot;41-mcp-架构拓扑&quot;&gt;4.1 MCP 架构拓扑&lt;/h3&gt;
&lt;p&gt;MCP 采用类似于语言服务器协议（LSP）的 Client-Host-Server 架构：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;MCP Host&lt;/strong&gt;：承载用户交互并管理客户端的应用（如 Claude Code、OpenCode）。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;MCP Client&lt;/strong&gt;：由 Host 创建，与一个 Server 建立协议连接。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;MCP Server&lt;/strong&gt;：提供 Resources（资源）、Tools（工具）与 Prompts（模板）的服务。本地服务可通过 stdio 连接，远程服务可使用 Streamable HTTP；旧版 HTTP+SSE 的兼容性需单独检查。见 &lt;a href=&quot;https://modelcontextprotocol.io/specification/2025-06-18/basic/transports&quot;&gt;MCP 传输规范&lt;/a&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ┌────────────────┐         JSON-RPC 2.0         ┌───────────────────────┐
 │   MCP Client   │ ◄──────────────────────────► │      MCP Server       │
 │ (Agent Engine) │   (stdio / Streamable HTTP)  │  (Linux Driver Trace) │
 └────────────────┘                              └───────────┬───────────┘
                                                             │
                                        ┌────────────────────┼────────────────────┐
                                        ▼                    ▼                    ▼
                                 [read_ring_dma()]    [parse_ftrace()]     [query_reg()]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;42-极简-python-mcp-server-范例与注入防护&quot;&gt;4.2 Python MCP Server 示例与输入检查&lt;/h3&gt;

&lt;p&gt;工具是 Agent 与系统之间的接口。下面的示例用参数列表调用系统程序，避免把外部输入拼进 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shell=True&lt;/code&gt; 命令；同时检查 PCI 地址格式、限制返回行数并设置超时。&lt;/p&gt;

&lt;p&gt;它演示的是两个只读诊断工具。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dmesg&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lspci&lt;/code&gt; 的可用性取决于操作系统和权限；格式校验也不能代替服务访问控制。示例使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;capture_output&lt;/code&gt;，只在读取后截断结果，尚未限制子进程输出的峰值内存占用。&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
Linux Driver Diagnostic MCP Server
实现要点：参数列表调用、PCI BDF 格式校验、返回行数限制与执行超时。
&quot;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;re&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;subprocess&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;mcp.server.fastmcp&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FastMCP&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;mcp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FastMCP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DriverDiagnostics&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 严格匹配标准 PCI BDF 格式：例如 &quot;00:01.0&quot; 或 &quot;0000:00:01.0&quot;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PCI_BDF_PATTERN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;^([0-9a-fA-F]{4}:)?[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-7]$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_dmesg_errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;安全读取内核环形缓冲区中最近的错误与警报日志&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 1. 严格校验入参边界，防止资源耗尽
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;参数拒绝: lines 必须在 1 到 500 之间&quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# 2. 避免 shell=True，直接以参数列表调用系统程序
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subprocess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dmesg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-l&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;err,warn&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;capture_output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returncode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dmesg 执行返回非零码 (&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returncode&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;): &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# 3. 在 Python 内部进行尾部切片截取，规避 shell 管道命令注入风险
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;all_lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;splitlines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;recent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_lines&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;无最近错误/警报日志。&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subprocess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TimeoutExpired&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;执行超时: dmesg 读取超过 5 秒已熔断。&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;系统调用异常: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;inspect_pci_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;读取指定 PCI 设备的 BAR 空间与内存映射状态&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clean_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 1. 严格白名单校验：阻断分号、空格、反引号等任何注入载荷
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PCI_BDF_PATTERN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clean_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;参数拒绝: &apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos; 不符合 PCI BDF 格式 (合法示例: &apos;0000:01:00.0&apos; 或 &apos;01:00.0&apos;)&quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# 2. 使用参数列表调用，避免 shell 解释外部输入
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subprocess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lspci&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-vvv&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clean_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;capture_output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returncode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lspci 查询返回非零状态 (&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returncode&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;): &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;设备未返回信息或设备不存在。&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subprocess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TimeoutExpired&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;执行超时: lspci 查询超过 5 秒已熔断。&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;执行异常: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;安装所需 Python 依赖后，可以把该脚本配置为 stdio MCP Server。支持这一传输方式的 Agent 可调用它，无需把诊断逻辑写进 Agent 本身。部署前还应限制运行用户权限，并确认日志是否包含不宜外发的信息。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-安全围栏与沙箱工程最佳实践&quot;&gt;5. 权限、隔离与长任务管理&lt;/h2&gt;

&lt;p&gt;终端工具能修改文件和运行命令，权限范围需要提前明确：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;工作区限制&lt;/strong&gt;：默认将读写范围限制在任务目录，访问 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.ssh/&lt;/code&gt; 等路径应有明确用途和授权。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;命令检查与系统隔离&lt;/strong&gt;：危险命令匹配可以补充防护，但不能覆盖命令别名、脚本间接调用等情况，还需依靠运行用户权限、容器或操作系统沙箱。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;长任务管理&lt;/strong&gt;：交互程序可使用 PTY，非交互构建也可使用管道。两者都需要持续读取输出、设置合适超时并处理子进程；内核构建等任务不宜统一套用 30 秒上限。&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Tue, 11 Aug 2026 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/geek/terminal/</link>
        <guid isPermaLink="true">https://xidianedu.cc/geek/terminal/</guid>
        
        <category>AI</category>
        
        <category>Coding Agent</category>
        
        <category>Claude Code</category>
        
        <category>Aider</category>
        
        <category>MCP</category>
        
        <category>开发者工具</category>
        
        
      </item>
    
      <item>
        <title>Wi-Fi 驱动内存占用分析</title>
        <description>&lt;p&gt;评估 Wi-Fi 驱动内存时，一个总数难以说明哪些配置可以调整，也难以判断是否存在泄漏。可以把问题拆成几项：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;静态成本是多少&lt;/strong&gt;：代码段（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text&lt;/code&gt;）、常驻数据（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.data&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bss&lt;/code&gt;）各占多少？&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;动态开销在哪里&lt;/strong&gt;：驱动基础运行需要多少？业务流量（TX/RX Buffer）撑起时峰值是多少？&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;连接数的影响&lt;/strong&gt;：作为 SoftAP 时，每增加一个 STA 客户端会增加多少内存？&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;稳定性与趋势&lt;/strong&gt;：高负载打流结束后内存能否完全回落？反复连断是否存在隐式泄漏？
下面分别整理 Linux 和 RTOS 环境中的统计方法、占用来源与回收检查。&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;注&lt;/strong&gt;：本文使用经过归一化处理的示例区间说明分析方法，不对应任何具体芯片、客户项目或驱动版本。实际结果应以目标固件的链接 Map、模块信息和运行时统计为准。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1-统计方法与维测工具&quot;&gt;1. 统计方法与维测工具&lt;/h2&gt;

&lt;p&gt;先确认统计覆盖哪些分配，再比较不同运行状态。操作系统的全局剩余内存还会受到其他模块和缓存影响，不能直接视为驱动占用。&lt;/p&gt;

&lt;h3 id=&quot;11-静态段分析&quot;&gt;1.1 静态段分析&lt;/h3&gt;

&lt;p&gt;静态内存反映了驱动固化的基础成本：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Linux 模块&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;size &amp;lt;driver&amp;gt;.ko&lt;/code&gt; 查看 ELF 文件的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.data&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bss&lt;/code&gt; 段大小。&lt;/li&gt;
      &lt;li&gt;通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lsmod&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sys/module/&amp;lt;driver_name&amp;gt;/sections/&lt;/code&gt; 查看加载进内核后的实际内存映射。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;RTOS 静态库 / 固件&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;通过交叉编译链的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arm-none-eabi-size &amp;lt;driver_library&amp;gt;.a&lt;/code&gt;，可以细化到目标文件的段大小分布。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;12-动态内存与维测节点&quot;&gt;1.2 动态内存与维测节点&lt;/h3&gt;

&lt;p&gt;在 Linux 内核驱动中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kmalloc&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmalloc&lt;/code&gt; 散落在各个协议与数据流分支中，单靠内核全局 Slab 统计很难剥离出单一驱动的真实开销。&lt;/p&gt;

&lt;p&gt;推荐的做法是在驱动内部维护轻量级的内存监控结构（例如通过 Procfs 或 Debugfs 的通用统计节点导出），记录运行时的关键指标：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Total allocated size&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Total freed size&lt;/code&gt;（历史累计申请/释放字节数）&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Allocation calls&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Free calls&lt;/code&gt;（调用次数）&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Current dynamic usage&lt;/code&gt;（当前净动态占用 = 累计申请 - 累计释放）&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 示例：节点名称由具体驱动决定&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/&amp;lt;driver&amp;gt;/mem_stats
Total allocated size: &amp;lt;accumulated_allocated_bytes&amp;gt;
Total freed size:     &amp;lt;accumulated_freed_bytes&amp;gt;
Allocation calls:     &amp;lt;allocation_count&amp;gt;
Free calls:           &amp;lt;free_count&amp;gt;
Current tracked usage:&amp;lt;allocated_minus_freed&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在空闲、打流和断开重连时分别记录这些指标，再结合分配位置分析波动来源。未经过监控接口的分配不会出现在这里，需要说明统计范围。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-linux-平台-wi-fi-驱动内存剖析&quot;&gt;2. Linux 平台 Wi-Fi 驱动内存剖析&lt;/h2&gt;

&lt;p&gt;在 Linux 系统下，Wi-Fi 驱动通常以内核模块（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ko&lt;/code&gt;）形式存在，依赖内核的内存管理子系统（Slab/Slub、Buddy 分配器）以及网络子系统的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sk_buff&lt;/code&gt;。&lt;/p&gt;

&lt;h3 id=&quot;21-静态内存分布&quot;&gt;2.1 静态内存分布&lt;/h3&gt;

&lt;p&gt;以经过归一化的嵌入式 Linux Wi-Fi USB 驱动样例为例：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;内存段&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;大小（ELF 解析）&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数百 KB 量级&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;驱动核心逻辑、802.11 状态机、MAC/HIF 控制指令等代码&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.data&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数十 KB 以内&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;已初始化的全局/静态变量、配置表&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bss&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;与预分配策略相关&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;未初始化的全局变量与静态缓冲区&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;实际加载占用 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lsmod&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;通常高于 ELF 段简单求和&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;包含页对齐、模块元数据及其他运行时段&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;为什么 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lsmod&lt;/code&gt; 显示的大小通常大于段之和？&lt;/strong&gt;
内核在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;insmod&lt;/code&gt; 加载模块时，需要按页对齐分配只读段（代码）与可读写段，同时会保留 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct module&lt;/code&gt; 结构、导出符号表、异常表以及模块初始化段（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.init.text&lt;/code&gt; 等在初始化完成后会释放但加载时仍占空间）。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;22-动态内存开销与拆解&quot;&gt;2.2 动态内存开销与拆解&lt;/h3&gt;

&lt;p&gt;Linux 下 Wi-Fi 驱动的动态内存主要由 &lt;strong&gt;协议常驻控制块&lt;/strong&gt;、&lt;strong&gt;STA 节点上下文&lt;/strong&gt; 和 &lt;strong&gt;收发数据包队列（skb）&lt;/strong&gt; 组成：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;内存类型&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;典型开销&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;基础常驻对象 (Base Alloc)&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数百 KB 量级&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;驱动核心管理结构、网卡上下文、HIF 队列描述符、认证状态机等&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;USB TX/RX skb 缓冲池&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数十至数百 KB&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;预分配或飞行中的 USB URB 与网络数据帧缓冲&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;AP 模式单 STA 上下文&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数十 KB / STA&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;包含连接上下文、重排序队列、密钥与速率统计&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;汇总对比：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;STA 工作模式&lt;/strong&gt;：基础常驻对象 + 接口缓冲池；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;AP 工作模式&lt;/strong&gt;：STA 模式基础开销 + $N \times$ 单 STA 上下文。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在这类实现中，动态内存可能成为运行期的大头，因此需要同时观察基础常驻、业务峰值与连接数增长曲线。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-rtos-平台-wi-fi-驱动内存剖析&quot;&gt;3. RTOS 平台 Wi-Fi 驱动内存剖析&lt;/h2&gt;

&lt;p&gt;微控制器上的 RTOS 驱动常使用静态缓冲区或预分配内存池，以控制运行时分配开销和碎片。RTOS 并不只对应静态分配，仍要查看目标实现。&lt;/p&gt;

&lt;h3 id=&quot;31-静态段分布&quot;&gt;3.1 静态段分布&lt;/h3&gt;

&lt;p&gt;下面列出 RTOS 驱动静态库中常见的段占用来源：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;内存段&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;大小&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;核心构成与特点&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数百 KB 量级&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;协议栈、MLME、认证、安全算法与 HIF 通信代码&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.data&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数十 KB 量级&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;可能包含内嵌固件数组和初始化数据&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bss&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数百 KB 量级&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;常由预分配内存池和静态包缓冲主导&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;总计&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;与功能裁剪和池配置相关&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;以最终链接 ELF 与 Map 文件为准&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;32-各模块段大小透视&quot;&gt;3.2 各模块段大小透视&lt;/h3&gt;

&lt;p&gt;通过对静态库内部目标文件进行分类，可以进一步看出空间分布：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;内存池模块&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;大块 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bss&lt;/code&gt; 通常来自静态包池和对象池。这样可以减少系统堆碎片，但会提高固件的常驻 RAM 基线。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;固件内嵌模块&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;没有文件系统时，芯片固件可能以 C 数组形式编入镜像，并在启动阶段通过 SDIO、SPI 或 USB 下发。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;加密与安全模块&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;认证、哈希与对称加密算法通常占据较明显的代码空间，应结合产品安全要求决定是否裁剪旧协议。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;802.11 核心与收发处理&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;MLME、扫描、AP、TX/RX 与 HIF 等模块构成主要协议和数据面代码。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-内存泄漏与稳定性排查方法&quot;&gt;4. 内存泄漏与稳定性排查方法&lt;/h2&gt;

&lt;p&gt;正常收发也会让内存波动，因此单次快照不足以判定泄漏。可以重复相同操作，观察业务结束后的占用是否回到相近水平。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;内存使用量
  ^
  |        /--\  /--\  [高吞吐打流峰值]
  |       /    \/    \
  |      /            \
  |     /              \______________ [业务停止后正常回落至基线]
  |    /
  |   /               ---------------- [异常：基线被抬高，未回收]
  |  /               /
  | /               /
  +-------------------------------------&amp;gt; 时间
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;41-压测前后的基线比对&quot;&gt;4.1 压测前后的基线比对&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;测试步骤&lt;/strong&gt;：
    &lt;ol&gt;
      &lt;li&gt;启动驱动并建立连接，记录基线动态内存 $M_0$。&lt;/li&gt;
      &lt;li&gt;使用 iperf 进行持续 1~2 小时的大流量双向打流，观察动态内存峰值 $M_{\text{peak}}$ 是否收敛（不应无节制上涨）。&lt;/li&gt;
      &lt;li&gt;停止打流，等待 1~2 分钟让缓存与重传队列超时回收，记录当前内存 $M_1$。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;判定标准&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;若 $M_1 \approx M_0$：本次测试中，已统计的分配大致回到基线，仍不能据此证明所有路径都没有泄漏。&lt;/li&gt;
      &lt;li&gt;若 $M_1 &amp;gt; M_0$，且重复测试后持续上涨：检查缓存保留策略、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;skb&lt;/code&gt; 或描述符回收，以及引用计数是否完整。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;42-客户端频繁上下线测试ap-模式&quot;&gt;4.2 客户端频繁上下线测试（AP 模式）&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;测试步骤&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;编写脚本让 STA 客户端以 1 秒一次的频率反复关联（Associate）、认证（Auth）、断开（Disassociate）。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;常见隐患&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;AP 侧为每个 STA 分配的连接上下文（如重排序 BA 窗口队列、密钥上下文、DHCP Lease 结构）在异常离线时未走完清理流程，表现为每次重连后基线持续抬高。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-驱动内存优化与裁剪策略&quot;&gt;5. 驱动内存优化与裁剪策略&lt;/h2&gt;

&lt;p&gt;确定主要占用来源后，可以分别检查功能裁剪和缓冲池配置。&lt;/p&gt;

&lt;h3 id=&quot;51-静态内存裁剪&quot;&gt;5.1 静态内存裁剪&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;废弃算法与协议精简&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;在不需要兼容旧安全协议的产品中，可按安全要求裁剪 WEP、TKIP、ARC4 及过时的 Ad-hoc 模式，具体收益以链接 Map 为准。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;固件加载解耦（RTOS 场景）&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;若系统具备外部 Flash 或存储分区，可将固件二进制从常驻 RAM 数组移出，改为启动时从存储分区读取并通过主机接口下发。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;剥离调试与 Proc 节点&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;Release 编译选项中关闭冗余字符串、详细统计结构与调试节点，可减少代码和常驻数据空间。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;52-动态缓冲与数据面优化&quot;&gt;5.2 动态缓冲与数据面优化&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;按需配置 STA 容量与队列深度&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;通用驱动通常默认支持 8~16 个 STA 连接，并在初始化阶段为每个槽位预分配连接控制块与 BA（Block Ack）接收重排序队列；&lt;/li&gt;
      &lt;li&gt;在单品 IPC 等轻量场景下，将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX_STA_NUM&lt;/code&gt;（如从 16 缩减至 4）对于预分配架构可直接减少常驻内存；对于按需动态分配架构，则能有效限制连接风暴时的内存峰值。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;数据面环形队列复用（零拷贝）&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;高频收发路径上的频繁分配和释放可能增加开销，可以先统计调用量和耗时，再判断是否需要对象池。&lt;/li&gt;
      &lt;li&gt;采用预分配固定长度的 Ring Buffer 与描述符环，数据帧通过共享内存直接上送网络协议栈（如 lwIP 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pbuf&lt;/code&gt; 直接包裹接收数据，避免额外 memcpy）。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;动态收缩的自适应 Buffer Pool&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;可考虑在低负载时缩小池容量、负载增加时扩容；收缩时机要结合流量变化和分配失败风险，避免反复扩缩。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;6-总结构建有说服力的内存报告&quot;&gt;6. 内存报告应记录什么&lt;/h2&gt;

&lt;p&gt;报告中需要说明统计口径、运行状态和占用来源。可以按下面的式子整理项目，但预分配在静态段中的缓冲池不能再计入动态占用：&lt;/p&gt;

\[\text{总内存占用} = \underbrace{\text{代码段 (.text)} + \text{数据段 (.data/.bss)}}_{\text{静态基础成本}} + \underbrace{\text{常驻控制结构} + \text{缓冲池 (TX/RX Ring)} + N \times \text{STA 节点}}_{\text{动态业务成本}}\]

&lt;p&gt;同时记录驱动版本、功能开关、连接数、队列深度和测试流量，保留空闲、峰值以及业务结束后的数据。这样才能比较两次构建，判断节省来自功能裁剪、缓冲配置还是资源回收变化。&lt;/p&gt;
</description>
        <pubDate>Sun, 08 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/2026/02/08/wifi-driver-memory-analysis/</link>
        <guid isPermaLink="true">https://xidianedu.cc/2026/02/08/wifi-driver-memory-analysis/</guid>
        
        <category>无线网络</category>
        
        <category>驱动</category>
        
        <category>内存分析</category>
        
        <category>嵌入式</category>
        
        
      </item>
    
      <item>
        <title>Wi-Fi USB 驱动架构与多核性能调优</title>
        <description>&lt;p&gt;嵌入式 Linux 设备常通过 USB 接入 Wi-Fi 芯片。无线链路速率较高时，主控 CPU、USB 总线和驱动处理都可能限制实测吞吐，不能只看物理层速率。&lt;/p&gt;

&lt;p&gt;网络协议栈、USB 中断和驱动线程集中在同一个核心上时，可能出现一个核心忙、其他核心空闲的情况。这时可以检查中断亲和性和网络分流配置，再判断是否需要调整。&lt;/p&gt;

&lt;p&gt;下面用一种 USB Wi-Fi 驱动模型说明收发路径和四核分工。线程名、CPU 分配和预期负载均为示例，实际使用时需按驱动实现、SoC 拓扑和测量结果调整。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1-wi-fi-usb-驱动收发数据流模型&quot;&gt;1. Wi-Fi USB 驱动收发数据流模型&lt;/h2&gt;

&lt;p&gt;可以分别沿发送路径（TX Path）和接收路径（RX Path）查看数据经过的队列、线程和回调。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ 发送链路 (TX Path) ]
应用数据 / 转发数据
       │
       ▼
Linux 协议栈 / 桥接转发 (ndo_start_xmit)
       │ (将 skb 放入驱动待发环形缓冲区)
       ▼
驱动待发队列: &amp;lt;tx_pending_queue&amp;gt;
       │ (唤醒驱动专用发送线程 / Workqueue)
       ▼
驱动发送工作线程: &amp;lt;driver_tx_thread&amp;gt;
  ├── 1. 锁存并出队待发 sk_buff
  ├── 2. 执行 A-MSDU 软件报文聚合
  ├── 3. 填充硬件 TX 描述符 (TX Descriptor)
  └── 4. 组装 USB URB，调用 usb_submit_urb() 提交给 USB Core
       │
       ▼
USB 主控驱动 (xHCI / EHCI DMA 发送至芯片)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ 接收链路 (RX Path) ]
芯片通过 USB 批量端点上报数据
       │
       ▼
USB 主机控制器硬件触发中断 (Hard IRQ)
       │ (调度 USB 完成软中断 / Tasklet)
       ▼
USB 完成回调函数: &amp;lt;rx_complete_callback&amp;gt;()
  ├── 1. 从 RX URB 池取出已完成的 URB
  ├── 2. 剥离芯片私有 RX 描述符
  ├── 3. 解聚合 A-MSDU / A-MPDU，组装为标准 sk_buff
  └── 4. 调用 napi_gro_receive() 或 netif_receive_skb() 递交协议栈
       │
       ▼
重新提交新的空闲 URB (usb_submit_urb) 保持接收窗口
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-驱动内部四大核心数据对象&quot;&gt;2. 驱动中的缓冲与工作线程&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;接收 URB 环&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;驱动初始化时预分配的一组 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct urb&lt;/code&gt; 及其对应 DMA 内存，具体深度由吞吐、延迟和可用内存共同决定；&lt;/li&gt;
      &lt;li&gt;驱动时刻保证有足够数量的 URB 挂在 USB 主控底层，防止芯片有数据上报时因 Host 端无空闲 URB 导致硬件 FIFO 溢出。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;待发包缓冲环&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;介于协议栈 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ndo_start_xmit&lt;/code&gt; 与驱动发送线程之间的 FIFO 环形队列；&lt;/li&gt;
      &lt;li&gt;用于解耦网络层发包与 USB 物理总线提交，提供流量突发时的吸收缓冲。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;发送 URB 环&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;驱动用于承载实际 USB 批量传输请求的 URB 对象池；&lt;/li&gt;
      &lt;li&gt;发送完成后在 TX Complete 回调中释放 skb 并回收 URB，供下一轮复用。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;驱动发送引擎线程&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;专职负责出队、硬件描述符封装、软件聚合与 URB 下发的内核工作线程。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-多核-smp-亲和性affinity分核策略&quot;&gt;3. 多核 SMP 亲和性（Affinity）分核策略&lt;/h2&gt;

&lt;p&gt;在典型四核 ARM 平台上，若中断路由与网络分流未做针对性配置，网卡和 USB 相关处理可能集中在同一核心，使该核心的软中断负载接近饱和并成为瓶颈。&lt;/p&gt;

&lt;h3 id=&quot;31-四核流水线分工模型&quot;&gt;3.1 四核流水线分工模型&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   ┌───────────────┐     ┌───────────────┐     ┌───────────────┐     ┌───────────────┐
   │     CPU 0     │     │     CPU 1     │     │     CPU 2     │     │     CPU 3     │
   ├───────────────┤     ├───────────────┤     ├───────────────┤     ├───────────────┤
   │ * 以太网中断   │     │ * RPS 协议栈   │     │ * USB 主控中断│     │ * 驱动发送线程│
   │   (eth0 IRQ)  │───&amp;gt; │   软中断处理  │───&amp;gt; │   (xhci IRQ)  │     │ * TX Worker   │
   │ * 数据入站网关│     │   (NET_RX)    │     │ * RX Complete │     │ * A-MSDU 聚合 │
   └───────────────┘     └───────────────┘     └───────────────┘     └───────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CPU 0（以太网入口）&lt;/strong&gt;：处理以太网入口的硬件中断与 NAPI 轮询；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CPU 1（协议栈分流）&lt;/strong&gt;：通过 Linux 内核 RPS（Receive Packet Steering）机制，将以太网接收后的 TCP/IP 协议栈计算分流到 CPU 1，卸载 CPU 0；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CPU 2（USB 处理）&lt;/strong&gt;：处理 USB 主控中断及相应接收工作，具体回调上下文由实现决定；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CPU 3（发送线程）&lt;/strong&gt;：运行驱动的发送工作线程，处理内存拷贝与聚合组包。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;32-实际调优配置示例&quot;&gt;3.2 实际调优配置示例&lt;/h3&gt;

&lt;p&gt;在 Linux 环境下，可以通过 sysfs 与 procfs 配置中断与协议栈分流：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Wi-Fi USB SMP Affinity &amp;amp; RPS Configuration Example&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;ETH_IF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;eth0&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;WLAN_IF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;wlan0&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 1. 查找硬件中断号&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;ETH_IRQ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ETH_IF&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; /proc/interrupts | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 1 | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{print $1}&apos;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;USB_IRQ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;(xhci|ehci)&quot;&lt;/span&gt; /proc/interrupts | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 1 | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{print $1}&apos;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 2. 绑定硬件中断亲和性&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 以太网中断 -&amp;gt; CPU 0 (Affinity Mask 0x1)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ETH_IRQ&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;1 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /proc/irq/&lt;span class=&quot;nv&quot;&gt;$ETH_IRQ&lt;/span&gt;/smp_affinity

&lt;span class=&quot;c&quot;&gt;# USB 主控中断 -&amp;gt; CPU 2 (Affinity Mask 0x4)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$USB_IRQ&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;4 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /proc/irq/&lt;span class=&quot;nv&quot;&gt;$USB_IRQ&lt;/span&gt;/smp_affinity

&lt;span class=&quot;c&quot;&gt;# 3. 启用 RPS 协议栈软中断分流&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 将以太网入站流量的协议栈处理推给 CPU 1 (Mask 0x2)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/sys/class/net/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ETH_IF&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/queues/rx-0&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;2 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /sys/class/net/&lt;span class=&quot;nv&quot;&gt;$ETH_IF&lt;/span&gt;/queues/rx-0/rps_cpus
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 4. 绑定驱动发送工作线程（若驱动提供独立 kthread）&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 请替换为目标驱动中可从 ps/top 观察到的实际线程名&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;TX_THREAD_PATTERN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;driver-specific-kthread-name&amp;gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;TX_PID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;pgrep &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TX_THREAD_PATTERN&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 1&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TX_PID&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;taskset &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8 &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TX_PID&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# 绑定 CPU 3 (Mask 0x8)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SMP affinity configuration complete.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-调优效果与瓶颈诊断&quot;&gt;4. 如何判断调整是否有效&lt;/h2&gt;

&lt;h3 id=&quot;41-初始未调优时的瓶颈现象&quot;&gt;4.1 调整前记录负载&lt;/h3&gt;
&lt;p&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iperf3 -c &amp;lt;target&amp;gt; -P 4&lt;/code&gt; 进行 TCP 吞吐测试，同时记录各核心负载、中断计数和吞吐。如果 CPU 0 的软中断负载（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%si&lt;/code&gt;）接近饱和，而其他核心负载较低，可以进一步检查处理是否过于集中。单核满载只是一个线索，还需要确认 USB 总线、无线重传和发送队列是否也存在瓶颈。&lt;/p&gt;

&lt;h3 id=&quot;42-调优后的负载分布&quot;&gt;4.2 调整后重复同一测试&lt;/h3&gt;
&lt;p&gt;每次修改一项配置，再用相同的流量、方向和连接条件重复测试。上面的分工希望把入口收包、协议栈、USB 处理和发送线程分散，但并不保证吞吐提升。跨核传递和缓存访问也会带来开销，应结合吞吐、时延、丢包和各核心负载判断是否保留配置。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-总结&quot;&gt;5. 总结&lt;/h2&gt;

&lt;p&gt;绑核是处理负载集中问题的一种手段。先确定时间主要花在哪条路径，再选择中断亲和性、RPS 或线程分配；如果负载已均衡，继续拆分反而可能增加开销。最终配置应以目标平台上的重复测试为依据。&lt;/p&gt;
</description>
        <pubDate>Sun, 13 Jul 2025 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/2025/07/13/wifi-usb-driver-performance-tuning/</link>
        <guid isPermaLink="true">https://xidianedu.cc/2025/07/13/wifi-usb-driver-performance-tuning/</guid>
        
        <category>Wi-Fi</category>
        
        <category>驱动开发</category>
        
        <category>嵌入式</category>
        
        <category>Linux</category>
        
        <category>性能优化</category>
        
        
      </item>
    
      <item>
        <title>IEEE 802.11 分片机制</title>
        <description>&lt;p&gt;空口抓包中的分片和聚合都涉及帧的组织方式，但处理的数据单位不同：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;分片&lt;/strong&gt;：把一个超长的大帧（MSDU）拆分成多个小片段（Fragments / MPDUs）独立发送，核心目标是&lt;strong&gt;抗干扰与提升可靠性&lt;/strong&gt;；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;聚合&lt;/strong&gt;：把多个数据单元打包成一个超大物理帧（A-MSDU / A-MPDU）一次性发出，核心目标是&lt;strong&gt;摊薄信道竞争开销、提升吞吐量&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;下面以传统 MAC 分片为例，说明帧头标识、传输时序和抓包特征。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1-为什么需要-80211-mac-层分片&quot;&gt;1. 为什么需要 802.11 MAC 层分片？&lt;/h2&gt;

&lt;p&gt;在存在误码或干扰的信道上，长帧可能需要重传更多数据。分片把一次重传的范围缩小到单个片段，同时增加帧头和确认开销。&lt;/p&gt;

&lt;p&gt;如果一个 1500 字节的 IP 报文在空中传输时最后几个字节遭遇干扰出错：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;未分片场景&lt;/strong&gt;：接收端 CRC 校验（FCS）失败，整帧被丢弃，发送端必须重新退避并重传整整 1500 字节；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;分片场景&lt;/strong&gt;：若将其拆为 3 个 500 字节的片段，即使第 3 个片段损坏，前 2 个片段已经成功 ACK 确认，发送端&lt;strong&gt;只需重传最后 500 字节&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;是否值得分片，需要比较减少的重传量与新增的协议开销，不能仅凭信号弱或频段拥挤就判断收益。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-帧头格式与分片标识字段&quot;&gt;2. 帧头格式与分片标识字段&lt;/h2&gt;

&lt;p&gt;802.11 MAC 帧头通过以下字段精确控制和识别分片：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+-------------------+-------------------+------------------------+
| Frame Control (2B)| Duration/ID (2B)  | Address Fields (6B*3/4)|
+-------------------+-------------------+------------------------+
| Sequence Ctrl(2B) | QoS Control (2B)  | Frame Body (0-2304B)   |
+-------------------+-------------------+------------------------+
| FCS (4B)          |
+-------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;21-序列控制字段-sequence-control&quot;&gt;2.1 序列控制字段 (Sequence Control)&lt;/h3&gt;

&lt;p&gt;序列控制字段占用 2 字节（16 位），明确划分了两级编号：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; 15                                4 3            0
+-----------------------------------+--------------+
|       Sequence Number (12 bits)   | Frag Num(4b) |
+-----------------------------------+--------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;序列号 (Sequence Number, 12 位)&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;标识属于同一个上层 MSDU 的所有分片。一个原始报文拆出的所有分片&lt;strong&gt;共享完全相同的序列号&lt;/strong&gt;（0 ~ 4095 循环）。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;片段号 (Fragment Number, 4 位)&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;标识当前片段在该报文中的序号。从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; 开始单调递增，下一个片段为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;，依此类推。&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;理论分片上限&lt;/strong&gt;：由于片段号只有 4 位，&lt;strong&gt;一个 MSDU 最多只能被拆分为 16 个片段（0~15）&lt;/strong&gt;。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;22-更多分片标志-more-fragments&quot;&gt;2.2 更多分片标志 (More Fragments)&lt;/h3&gt;

&lt;p&gt;在 2 字节的 &lt;strong&gt;Frame Control&lt;/strong&gt; 字段中，第 2 字节包含 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;More Fragments&lt;/code&gt; 标志位（第 13 位）：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;More Frag = 1&lt;/code&gt;&lt;/strong&gt;：表明后续还有属于本序列号的后续分片；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;More Frag = 0&lt;/code&gt;&lt;/strong&gt;：表明当前片段是该报文的&lt;strong&gt;最后一个片段&lt;/strong&gt;（或者未分片报文）。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-sifs-连续突发与信道保护机制&quot;&gt;3. SIFS 连续突发与信道保护机制&lt;/h2&gt;

&lt;p&gt;802.11 的分片突发传输（Fragmentation Burst）允许连续片段通过 SIFS 间隔发送，减少重复竞争信道的开销：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;发送端: [ 片段 0 ] ──SIFS──&amp;gt;                [ 片段 1 ] ──SIFS──&amp;gt;
           │                                    │
           ▼                                    ▼
接收端:             &amp;lt;──SIFS── [ ACK 0 ]                   &amp;lt;──SIFS── [ ACK 1 ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;SIFS 短帧间间隔抢占&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;片段 0 发送完毕后，接收端在等待一个 &lt;strong&gt;SIFS&lt;/strong&gt;（Short Interframe Space，通常为 10~16µs）后立即回复 ACK 0；&lt;/li&gt;
      &lt;li&gt;发送端收到 ACK 0 后，无需重新执行 DIFS 和随机 Backoff，&lt;strong&gt;仅等待一个 SIFS 即可直接发送片段 1&lt;/strong&gt;；&lt;/li&gt;
      &lt;li&gt;SIFS 短于 DIFS/AIFS，让连续分片优先于重新开始竞争的节点发送。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;NAV（网络分配向量）虚拟载波监听&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;片段 0 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Duration&lt;/code&gt; 字段会提前将&lt;strong&gt;覆盖到 ACK 0 + 片段 1 + ACK 1 的空中时间&lt;/strong&gt;写入，更新周围所有监听节点的 NAV，防止被第三方节点抢占信道。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-分片与无线加密aes-ccmp--tkip的交互&quot;&gt;4. 分片与无线加密（AES-CCMP / TKIP）的交互&lt;/h2&gt;

&lt;p&gt;在启用 WPA2（AES-CCMP）或 WPA3（GCMP）的安全网络中，分片与加密是如何协同工作的？&lt;/p&gt;

&lt;h3 id=&quot;41-独立封装与解密原则&quot;&gt;4.1 独立封装与解密原则&lt;/h3&gt;

&lt;p&gt;IEEE 802.11 标准明确规定：&lt;strong&gt;分片发生在加密之前，每个片段作为独立的 MPDU 进行单独封装和加密&lt;/strong&gt;。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ 上层 MSDU 原文 ]
       │
       ▼ (分片)
[ 片段 0 数据 ]                 [ 片段 1 数据 ]
       │                               │
       ▼ (独立 AES-CCMP 加密)          ▼ (独立 AES-CCMP 加密)
[ CCMP头 | 密文 0 | MIC 0 ]     [ CCMP头 | 密文 1 | MIC 1 ] (Packet Number 单调递增)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;数据完整性保证&lt;/strong&gt;：每个分片拥有独立的 CCMP 头部（8 字节）和消息完整性校验码（MIC，8 字节），且每个分片的包序列号（Packet Number, PN）依次递增；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;容错优势&lt;/strong&gt;：接收端每收到一个片段即可立即硬件解密并校验 MIC，确认无篡改后放入重组缓存。即使某个片段中途丢失，也不会导致前面已收到的片段因无法解密而废弃。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-分片-vs-帧聚合a-msdu--a-mpdu对比&quot;&gt;5. 分片 vs 帧聚合（A-MSDU / A-MPDU）对比&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;特性维度&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;802.11 分片 (Fragmentation)&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;802.11n/ac/ax 帧聚合 (Aggregation)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;主要目标&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;提升弱网/干扰环境下的可靠性&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;消除协议头部与退避开销，提升吞吐&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;核心机制&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;将大 MSDU 拆成多个独立小 MPDU&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;将多个 MSDU/MPDU 打包为一个超大 PPDU&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;确认机制&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;逐片独立 SIFS + 单独 ACK&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;块确认机制（Block ACK, BA 一次确认数十个子帧）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;信道适用度&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;强干扰、低 SNR、高误码率信道&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;高信噪比、高速率（5GHz/6GHz）清洁信道&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;现代应用现状&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;默认分片阈值通常设为 2346B（几乎不触发）&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;现代 Wi-Fi 标配核心技术&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：在 Wi-Fi 4/5/6 中，A-MPDU 聚合子帧与分片是互斥的，通常规范不允许对 A-MPDU 内部的子帧再次进行传统分片。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;6-实战抓包识别与驱动配置&quot;&gt;6. 实战：抓包识别与驱动配置&lt;/h2&gt;

&lt;h3 id=&quot;61-wireshark-抓包特征&quot;&gt;6.1 Wireshark 抓包特征&lt;/h3&gt;

&lt;p&gt;在 Wireshark 中过滤并定位 802.11 分片：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;过滤条件：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wlan.fc.frag &amp;gt; 0 || wlan.fc.more_frag == 1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;关键特征&lt;/strong&gt;：
    &lt;ol&gt;
      &lt;li&gt;连续几个数据帧具有&lt;strong&gt;相同的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wlan.seq&lt;/code&gt;（序列号）&lt;/strong&gt;；&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wlan.frag&lt;/code&gt;（片段号）从 0、1、2 依次递增；&lt;/li&gt;
      &lt;li&gt;最后一个片段的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wlan.fc.more_frag == 0&lt;/code&gt;，其余片段均为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;；&lt;/li&gt;
      &lt;li&gt;片段之间紧跟着独立的 ACK 帧（Delta Time 约等于 SIFS）。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;62-linux-驱动分片阈值配置&quot;&gt;6.2 Linux 驱动分片阈值配置&lt;/h3&gt;

&lt;p&gt;在 Linux 下可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iw&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iwconfig&lt;/code&gt; 调整分片阈值（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frag&lt;/code&gt;）：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 查看当前无线网卡分片阈值&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;iwconfig wlan0 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;fragmentation&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 将分片阈值设置为 512 字节（低于 512 字节不分片，高于则切片）&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iwconfig wlan0 frag 512

&lt;span class=&quot;c&quot;&gt;# 恢复默认不分片设置（设为最大 2346 字节或 off）&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iwconfig wlan0 frag off
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;7-总结&quot;&gt;7. 总结&lt;/h2&gt;

&lt;p&gt;抓包时可结合序列号、片段号和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;More Fragments&lt;/code&gt; 判断分片是否完整。调整分片阈值前，还要确认设备和当前传输模式是否支持；调整后对比重传量、吞吐和时延，判断减少重传的收益是否抵消了新增开销。&lt;/p&gt;
</description>
        <pubDate>Sun, 08 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/2024/12/08/ieee-80211-fragmentation/</link>
        <guid isPermaLink="true">https://xidianedu.cc/2024/12/08/ieee-80211-fragmentation/</guid>
        
        <category>无线网络</category>
        
        <category>802.11</category>
        
        <category>Wi-Fi</category>
        
        <category>抓包分析</category>
        
        
      </item>
    
      <item>
        <title>Wi-Fi P2P 的建链过程与并发模式</title>
        <description>&lt;p&gt;Wi-Fi P2P（&lt;strong&gt;Wi-Fi Direct&lt;/strong&gt;）让设备在没有外部无线路由器的情况下建立无线连接，常用于投屏、文件传输和无线打印。&lt;/p&gt;

&lt;p&gt;建链时仍需要设备发现、GO 角色协商、安全配对和地址配置。设备同时连接路由器时，还要处理 STA 与 P2P 接口的信道关系。下面按这些步骤整理协议和调试命令。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1-架构角色与-group-模型&quot;&gt;1. 架构角色与 Group 模型&lt;/h2&gt;

&lt;p&gt;Wi-Fi Direct 在拓扑上仍然复用了经典的 802.11 基础设施架构，核心差异在于&lt;strong&gt;AP 角色是在设备间动态竞选产生的&lt;/strong&gt;：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                 ┌─────────────────────────┐
                 │    P2P Group Owner      │
                 │   (GO - 充当自主 AP)    │
                 │  * 广播 Beacon/SSID     │
                 │  * 运行内部 DHCP Server  │
                 └───────────┬─────────────┘
                             │
            ┌────────────────┴────────────────┐
            ▼                                 ▼
┌───────────────────────┐         ┌───────────────────────┐
│      P2P Client       │         │      P2P Client       │
│ (充当 STA，获取 IP)   │         │ (充当 STA，获取 IP)   │
└───────────────────────┘         └───────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;P2P Device&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;处于发现阶段的未入组实体，仅具备扫描与协商能力。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;P2P Group Owner (GO)&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;在建立连接时被推选出来的“主设备”。GO 会对外广播以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DIRECT-&lt;/code&gt; 开头的 Beacon 帧，维护 BSSID，并在内核/用户态启动轻量级 DHCP Server（通常分配 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.49.x&lt;/code&gt; 网段），负责为 Client 分配 IP。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;P2P Client&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;组内的“从设备”，以传统 Station 身份关联至 GO，通过 DHCP 获取 IP 地址。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Autonomous GO (自主 GO)&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;设备不经过双向协商，单方面直接以 GO 模式建组，其他设备通过扫码或输入 PIN 码直接加入。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-p2p-连接全流程与状态机&quot;&gt;2. P2P 连接全流程与状态机&lt;/h2&gt;

&lt;p&gt;下面是一条经过 GO 协商的建链路径，服务发现为可选步骤：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;sequenceDiagram
    autonumber
    participant D1 as P2P Device A (Client)
    participant D2 as P2P Device B (GO 胜出者)

    Note over D1,D2: 阶段 1: 发现阶段 (Social Channels 1, 6, 11)
    D1-&amp;gt;&amp;gt;D2: Probe Request (P2P IE)
    D2--&amp;gt;&amp;gt;D1: Probe Response (P2P IE: Device Info)

    Note over D1,D2: 阶段 2: 服务发现 (可选 GAS/ANQP)
    D1-&amp;gt;&amp;gt;D2: GAS Initial Request (Bonjour/UPnP)
    D2--&amp;gt;&amp;gt;D1: GAS Initial Response (支持投屏/传输)

    Note over D1,D2: 阶段 3: GO 角色协商 (GON 握手)
    D1-&amp;gt;&amp;gt;D2: GO Negotiation Request (GO Intent=5, Tie=0)
    D2--&amp;gt;&amp;gt;D1: GO Negotiation Response (GO Intent=14, Tie=1)
    D1-&amp;gt;&amp;gt;D2: GO Negotiation Confirmation (Status: Success, B 胜出)

    Note over D1,D2: 阶段 4: 安全配置与建链 (WPS + 4-Way HS)
    D1-&amp;gt;&amp;gt;D2: Provision Discovery (PBC / PIN)
    D2--&amp;gt;&amp;gt;D1: Provision Discovery Response
    D1-&amp;gt;&amp;gt;D2: 802.11 Auth &amp;amp; Assoc (DIRECT-xx SSID)
    D1-&amp;gt;&amp;gt;D2: EAP-WSC (WPS 交换凭证与 PSK)
    D1-&amp;gt;&amp;gt;D2: WPA2 4-Way Handshake

    Note over D1,D2: 阶段 5: 地址分配与业务数据
    D1-&amp;gt;&amp;gt;D2: DHCP Discover
    D2--&amp;gt;&amp;gt;D1: DHCP Offer / ACK (分配 192.168.49.x)
    D1-&amp;gt;&amp;gt;D2: TCP/UDP 数据高速传输
    D2--&amp;gt;&amp;gt;D1: TCP/UDP 双向响应数据
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;21-设备发现discovery-phase&quot;&gt;2.1 设备发现（Discovery Phase）&lt;/h3&gt;

&lt;p&gt;为了避免在 2.4GHz 和 5GHz 所有频段盲目轮询造成耗电与延迟，Wi-Fi Direct 定义了 &lt;strong&gt;3 个社交信道（Social Channels: 1, 6, 11）&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Listen 状态&lt;/strong&gt;：随机选取 1、6、11 某信道作为 Listen Channel，静默监听 Probe Request；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Search 状态&lt;/strong&gt;：在 1、6、11 信道轮流发送携带 P2P Information Element (IE) 的 Probe Request 广播帧；&lt;/li&gt;
  &lt;li&gt;状态机在 Search 与 Listen 之间随机切换，直到双方在同一社交信道上相遇并完成响应。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;22-go-角色协商go-negotiation&quot;&gt;2.2 GO 角色协商（GO Negotiation）&lt;/h3&gt;

&lt;p&gt;当用户发起连接时，两端通过 3 次握手协商出由谁当 AP：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;GO Intent（意愿值，0 ~ 15）&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;双方在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GO Negotiation Request/Response&lt;/code&gt; 报文中携带自己的 Intent 值；&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Intent 规则&lt;/strong&gt;：拥有持续供电的设备通常配置较高的 Intent 值。当双方 Intent 不同时，&lt;strong&gt;Intent 较大的一方胜出成为 GO&lt;/strong&gt;；&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;平局处理&lt;/strong&gt;：若双方 Intent 相同（$&amp;lt;15$），则比对协商报文中的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tie-Breaker&lt;/code&gt; 比特位决定胜负；&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;特殊情况&lt;/strong&gt;：若双方均设置了最高意愿值 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Intent = 15&lt;/code&gt;（均要求强制为 GO），协议规定协商失败（返回状态码 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAIL_BOTH_GO_INTENT_15&lt;/code&gt;），无法建立连接。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Operating Channel 协商&lt;/strong&gt;：双方确定建组后的最终工作信道（可切至干净的 5GHz 频段）。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;23-安全与入网wps--4-way-handshake&quot;&gt;2.3 安全与入网（WPS + 4-Way Handshake）&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;WPS 配对&lt;/strong&gt;：支持 PBC（Push Button Configuration，虚拟按键确认）或 PIN 码；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;凭证分发&lt;/strong&gt;：通过 EAP-WSC 交互后，GO 向 Client 分发预共享密钥（PSK）与动态 SSID；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;4 次握手&lt;/strong&gt;：基于生成的 PSK 立即执行标准的 802.11i WPA2-PSK (AES-CCMP) 四次握手生成 PTK/GTK。&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-多角色并发scc-vs-mcc&quot;&gt;3. 多角色并发：SCC vs MCC&lt;/h2&gt;

&lt;p&gt;在移动终端上，常见的并发场景为：手机既连接无线路由器上网（STA 模式），又要通过 Wi-Fi Direct 投屏到电视（P2P Client 或 P2P GO）。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        ┌─────────────┐
        │  家用路由器 │ (例如工作在 Channel 36)
        └──────┬──────┘
               │ (STA 链路)
               ▼
        ┌─────────────┐ (单 RF 射频芯片)
        │   智能终端  │
        └──────┬──────┘
               │ (P2P 链路)
               ▼
        ┌─────────────┐
        │   智能电视  │ (若 P2P 工作在 Channel 149 -&amp;gt; 产生 MCC)
        └─────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;31-单信道并发scc---single-channel-concurrency&quot;&gt;3.1 单信道并发（SCC - Single Channel Concurrency）&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;原理&lt;/strong&gt;：STA 接口与 P2P 接口工作在&lt;strong&gt;完全相同的信道&lt;/strong&gt;（例如均为 Ch 36）；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;优势&lt;/strong&gt;：单 RF 射频无需在多个频点间跳变，开销最低，吞吐性能最好；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;限制&lt;/strong&gt;：要求 GO 协商或建组时服从当前已有 STA 连接的信道。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;32-多信道并发mcc---multi-channel-concurrency&quot;&gt;3.2 多信道并发（MCC - Multi Channel Concurrency）&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;原理&lt;/strong&gt;：当 STA 必须工作在 Ch 36，而 P2P 必须工作在 Ch 149 时，单 RF 芯片需以&lt;strong&gt;时分复用（Time Division Multiplexing）&lt;/strong&gt;方式在两个信道间切换；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;特点与机制&lt;/strong&gt;：
    &lt;ol&gt;
      &lt;li&gt;&lt;strong&gt;吞吐下降&lt;/strong&gt;：由于信道切换存在锁相环稳定时间与空口保护时间，有效吞吐通常显著降低；&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;TBTT 同步&lt;/strong&gt;：需协调两个信道的 Beacon 接收，防止错过 STA 端的信标帧；&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;NoA (Notice of Absence) 与 CTWindow&lt;/strong&gt;：P2P GO 可在 Beacon 帧或管理帧中携带 NoA（缺席通知）或使用 Client Traffic Window（CTWindow）机制声明离信道时间，协调组内 Client 在 GO 切换至另一信道期间暂缓发包。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-linux-下-wpa_cli-实操与调试&quot;&gt;4. Linux 下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_cli&lt;/code&gt; 实操与调试&lt;/h2&gt;

&lt;p&gt;在 Linux 系统下，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant&lt;/code&gt; 完整实现了 P2P 协议状态机。以下是通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_cli&lt;/code&gt; 调试 P2P 的常用命令链路：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 1. 启动 P2P 设备搜索&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wpa_cli &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; wlan0 p2p_find

&lt;span class=&quot;c&quot;&gt;# 2. 列出附近发现的 P2P 节点信息&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wpa_cli &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; wlan0 p2p_peers
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wpa_cli &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; wlan0 p2p_peer &amp;lt;PEER_MAC_ADDR&amp;gt;

&lt;span class=&quot;c&quot;&gt;# 3. 向对端设备发起 PBC 按钮配对连接&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wpa_cli &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; wlan0 p2p_connect &amp;lt;PEER_MAC_ADDR&amp;gt; pbc &lt;span class=&quot;nv&quot;&gt;go_intent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;14

&lt;span class=&quot;c&quot;&gt;# 4. (可选) 以自主 GO (Autonomous GO) 方式直接建组&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wpa_cli &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; wlan0 p2p_group_add &lt;span class=&quot;nv&quot;&gt;freq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5180

&lt;span class=&quot;c&quot;&gt;# 5. 查看当前 P2P 状态与组接口名 (如 p2p-wlan0-0)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wpa_cli &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; wlan0 p2p_group_status
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wpa_cli status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-总结&quot;&gt;5. 总结&lt;/h2&gt;

&lt;p&gt;P2P 故障可以按发现、协商、配对和地址分配逐段定位。单射频设备同时运行 STA 与 P2P 时，还需要记录两个接口的工作信道；使用 MCC 时，重点检查信道切换、Beacon 接收和 NoA 配合，观察它们是否影响业务时延。&lt;/p&gt;
</description>
        <pubDate>Sun, 18 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://xidianedu.cc/2024/08/18/wifi-p2p-basics/</link>
        <guid isPermaLink="true">https://xidianedu.cc/2024/08/18/wifi-p2p-basics/</guid>
        
        <category>无线网络</category>
        
        <category>Wi-Fi</category>
        
        <category>P2P</category>
        
        <category>wpa_supplicant</category>
        
        <category>Linux</category>
        
        
      </item>
    
  </channel>
</rss>
