Net 阻塞模型调研文档退役:客观实施记录留存,二期基线迁入任务规划

This commit is contained in:
2026-09-26 14:21:13 +08:00
parent 5c049daa7c
commit b46e6bffed
9 changed files with 141 additions and 339 deletions
+1 -1
View File
@@ -147,7 +147,7 @@ docs/
| [`CH395F_Trap_Records.md`](问题记录/CH395F_Trap_Records.md) | CH395F 以太网控制器陷阱台账 |
| [`GD5F2GQ5UE_Trap_Records.md`](问题记录/GD5F2GQ5UE_Trap_Records.md) | GD5F2GQ5UE SPI NAND 陷阱台账 |
| [`SD2506_Trap_Records.md`](问题记录/SD2506_Trap_Records.md) | SD2506 RTC 陷阱台账 |
| [`Net层阻塞模型业界对照与演进方案.md`](问题记录/Net层阻塞模型业界对照与演进方案.md) | Net 层阻塞模型与业界方案对照 |
| [`Net层阻塞模型改造实施记录.md`](问题记录/Net层阻塞模型改造实施记录.md) | E-02 阻塞模型改造客观实施记录(一期 pending 化:偏差/门禁实测/未执行项) |
| [`错误码传播审计.md`](问题记录/错误码传播审计.md) | 错误码传播缺陷审计(9 类模式 × 子系统) |
---
+37 -1
View File
@@ -78,7 +78,7 @@
| 序 | 任务 | 说明 | 出处 |
|---|---|---|---|
| **C1** | **pending 二期(ACCEPT + SEND)** | 沿一期机制扩展;同期消化 E-25(net_select 语义)、E-24/E-27/E-28(跨上下文收口);基线重锁 + 探针族扩充 + 看门狗接 selftest | 第二档 #2 / N-4 |
| **C1** | **pending 二期(ACCEPT + SEND)** | 沿一期机制扩展;同期消化 E-25(net_select 语义)、E-24/E-27/E-28(跨上下文收口);基线重锁 + 探针族扩充 + 看门狗接 selftest。**设计基线见下方 §2.1** | 第二档 #2 / N-4 |
| **C2** | **GD5F 错误通道统一** | E-10/E-42/E-53/E-54/E-56/E-57 一次做齐:`wait_busy` 区分超时/真故障、`bbt_scan` 失败**放弃持久化**(保护好副本)、init 全链路检查 + 重试、回读 B0h 校验 ECC | 第二档 #1 |
| **C3** | **存储侧日志管线**(消化 N-2) | 49s 全系统日志静默的复现与定位(NAND GC 长尾 vs UART 卡滞)+ 队列满丢弃计数/告警(现静默丢行);与 S8(非阻塞日志)合并评估 | N-2 / S-1 |
| **C4** | **defaultTask 栈余量**(S-1) | 2872B/4096(余量 29.9%,差 4.8B 未达 30% 判据)→ 栈 4096→4608(CCM 堆余量可覆盖)或 GC 链局部削减 | S-1 |
@@ -113,6 +113,42 @@
---
## 3.1 C1 设计基线(pending 二期:ACCEPT + SEND)
> **来源**:从已归档的《Net 层阻塞模型业界对照与演进方案》(2026-09-26 删除)中抽取——
> 该文档的调研/规划部分已完成使命,客观实施部分另存为
> `docs/问题记录/Net层阻塞模型改造实施记录.md`;本节仅保留**二期仍要用的设计基线**。
**一期已验证的机制骨架**(二期沿用,勿重新发明):独立静态 pending 表 + `net_pending_tick`
主循环节拍了结(五路:数据/到点/断连/同 fd 串行/重建取消必通知)+ 登记守卫(每 fd 至多一个、
不覆盖、拒绝 netTask 自等待)+ 1s 看门狗强结算。
**二期扩展点**:
| 项 | 目标 | 对应缺陷 |
|---|---|---|
| **ACCEPT pending** | accept 等待改为"登记 → CONNECT 事件完成",退役 100ms/200ms 轮询循环 | E-06(accept 轮询计时失真) |
| **SEND pending** | 发送续传改为"登记 → send_ready 完成",消除 1s/分片 stall 对队列的冻结 | E-02 残余(SEND 位置) |
**二期门禁**(一期门禁的加强版):
1. CH395F NET 层全套件(含一期未跑的 Phase 7 / Phase 10,视 RAM 预算);
2. L3/L5 基线重锁(一期已重锁 M3,二期须再锁);
3. `e02_probe.py` **探针族扩充**:close / reconfig / EOF / disconnect-during-pending 四专项;
4. `ftp_regression.py`(D20)+ E-06 假 425 场景**独立重跑**(一期是借 M3 压力档覆盖的);
5. UI 远端推流压力 + timeSync 三场景;
6. 产品 `@test` 闭环 + ST-LINK 全片回读;
7. `ram_report.py` / `stack_report.py` 前后对比(铁律);
8. 看门狗接 selftest 留痕 + 模拟器差距清单 +1(`net_socket_sim.c` 无法建模 pending)。
**已知代价(延续一期,需文档化)**:pending 完成判定随主循环节拍运行,被长操作占用时超时
顺延(~1ms 级);二期把 SEND 也 pending 化后,该顺延面反而**收窄**。
**改动量估算**:再 ~300-500 行,集中在 `net_socket.c`;公开 API 不变。风险评级**中**
(执行器核心 + D 系列前科)——**大的是验证,不是代码**。
---
## 4. 诊断基线(供后续对照)
| 项 | 当前值 | 出处 |
+1 -1
View File
@@ -24,4 +24,4 @@
| # | 事项 | 说明 | 出处 |
|---|---|---|---|
| N-4 | **pending 机制二期:ACCEPT + SEND 阻塞路径 pending 化**——E-06(accept 轮询计时失真)、E-20(lftpd 控制通道 errno 分类/501)、E-21(timeSync errno 分级)剩余分量共用该机制扩展;届时 L3/L5 基线再重锁、探针族扩充(close/reconfig/EOF/disconnect-during-pending)、看门狗接 selftest 留痕、模拟器差距清单 +1 | 一期(RECV)已落地并入主线:`a45c0cb`(+文档闭环 `7ff2958`);设计基线与门禁结果见 `docs/问题记录/Net层阻塞模型业界对照与演进方案.md` §6.7 | 同左 + `错误码传播审计.md` 第二档 #2 |
| N-4 | **pending 机制二期:ACCEPT + SEND 阻塞路径 pending 化**——E-06(accept 轮询计时失真)、E-20(lftpd 控制通道 errno 分类/501)、E-21(timeSync errno 分级)剩余分量共用该机制扩展;届时 L3/L5 基线再重锁、探针族扩充(close/reconfig/EOF/disconnect-during-pending)、看门狗接 selftest 留痕、模拟器差距清单 +1 | 一期(RECV)已落地并入主线:`a45c0cb`(+文档闭环 `7ff2958`);设计基线与门禁见 `下一步任务规划.md` §3.1,实施记录见 `Net层阻塞模型改造实施记录.md` | 同左 + `错误码传播审计.md` 第二档 #2 |
@@ -383,7 +383,7 @@ sequenceDiagram
- `docs/网络/BSD_Socket_API_使用指南.md` —— 公开 API 语义、示例、常见问题(本文的上半部)
- `docs/问题记录/CH395F_Trap_Records.md` —— Trap 01~23 机制细节(本文引用处)
- `docs/问题记录/Net层阻塞模型业界对照与演进方案.md` —— L3 pending 化的设计推演
- `docs/问题记录/Net层阻塞模型改造实施记录.md` —— L3 pending 化的实施记录(偏差/门禁实测/未执行项)
- `docs/问题记录/错误码传播审计.md` —— E-02 头阻塞与错误码回传全审计
- `docs/测试说明/链路延迟测试说明.md` —— D1/D10/L3/D14 等时延探针与自愈路径的台架证据
- `docs/子系统设计/网络配置说明.md` §4 —— 代次号与网络重建时序
@@ -1,332 +0,0 @@
# Net 层阻塞模型:业界对照与演进方案
> **模块名称**:Net 层(net_socket / netTask)阻塞等待模型
> **文档目的**:E-02 修复(2026-09-22)的配套调研留档——本项目已落地的"pending 请求"形态
> 与主流开源/成熟项目模式的对照,及二期(ACCEPT/SEND)的设计基线。
> **当前状态(2026-09-26 复核)**:**一期(RECV pending 化)已实施、已并入主线 `v2-on-ui`、
> 已推送远程**——落地提交 `a45c0cb`(实现)+ `7ff2958`(文档闭环)。实现与设计基线的偏差、
> 门禁逐条结果与实测数据见 **§6.7**。二期(ACCEPT/SEND)未动,设计基线见 §6.1,按 §7 排期。
> **日期**:2026-09-22(2026-09-26 复核修订)
> **配套文档**:`错误码传播审计.md`(E-02 明细 / 修复计划 / 已闭环记录)、`docs/测试说明/链路延迟测试说明.md`
> (M3 基线 / §8.3 实现要点 / §9 故障对照)、`AGENTS.md`(SPI 铁律 / 就绪屏障 / 内存预算)
---
## 1. 结论速览
1. **已落地的修复(pending 请求模型)在本项目约束类里是标准做法,且有官方认可**——不是野路子,
无需推翻;已经台架 A/B 实证(挂起对时客户端下 FTP banner 28554ms → 92.5ms)与
M3 压力档复验(p99 尾部 133.5ms → 69.3ms,零尖峰)。
2. **业界最正统形态("执行者永不被占")在本项目不可达**——其前提是"数据到达可被执行者免费
观察到"(LwIP:网卡 DMA/IRQ 递 pbuf → tcpip 线程 O(1) signal 消费者)。本项目的"数据到达"
观察手段是一次 SPI 事务,而 SPI 总线由 netTask 独占(铁律)→ 等待只能在 netTask 内执行,
自由度只剩"每次占多久"与"等待期间还做什么"。pending 方案 = 把第二个自由度用满
(占用降到主循环节拍级)。
3. **演进方向 = pending 请求**(控制块登记 + 主循环节拍完成 + 取消必通知):消灭头阻塞缺陷类
(不再依赖调用方纪律)、调用方从分片协议解放、成为 E-06/E-20/E-21 的公共地基。库内已有
生产验证先例——D10 的 `net_relisten_retry_tick`(登记→到点完成→全程不阻塞,恢复 588ms→89ms)
就是该模式的缩小版。
4. **一期已闭环,二期(ACCEPT/SEND)待排期**:残余分量 = 发送 stall、accept 轮询计时失真、
errno 分级。代码改动不大(再 ~300-500 行、公开 API 不变),**大的是验证**(台架天量级)。
---
## 2. 背景:E-02 缺陷与已落地修复
**缺陷**(P1,`错误码传播审计.md` E-02):netTask 是全部 socket 操作的唯一执行者,`net_process_messages`
每次取一条消息处理到完成才取下一条。任一消费者发起的 30s 阻塞 `net_recv`(`net_recv_locked` 自旋
`net_poll`+`ch395f_get_recv_len`)期间,队列整体停摆最长 30s——FTP 客户端空闲 >30s、对时客户端
连上不发数据,均为常见触发工况。09-21 事故(errno 覆盖误断连)的姊妹缺陷。
**已落地修复**(2026-09-22 一期;2026-09-26 复核更正提交号):
| 提交 | 内容 |
|---|---|
| `954a145` | 本调研文档留档(五类业界模式对照 + pending 演进方案) |
| `a45c0cb` | **一期实现**:阻塞 `recv` 改"挂起请求 + 主循环节拍完成",netTask 零占用;lftpd/timeSync 分片协议退役 |
| `7ff2958` | 文档闭环:E-02 审计两阶段闭环 + 本文 §6.7 实施记录 + M3 基线重锁(pending 构建)+ `待处理内容.md` 建立 |
| `93bae35` | 台架旁路:TC-NET-604 根因闭环(Trap 21,判定非缺陷),MSS=512 方案证伪回退 |
> **注**:早期版本本文档把一期提交记为 `f16dc9a` / 分支 `wip/v2-pending-recv`——该分支与哈希
> **在当前仓库不存在**(应为当时临时工作区,后续以 `a45c0cb` 正式落入 `v2-on-ui`)。以本表为准。
**A/B 台架实证**(`test/host/e02_probe.py`,2026-09-22,设备 192.168.1.100):挂起对时客户端连 :8888
不发数据,2s 后 PC 测 FTP(:21) banner 时延 = 队列响应性——旧固件 **28554ms**(设备日志实证芯片侧
握手与 MCU 侧处理相隔 27s;旧代码 30s 后静默拆连零日志)vs 一期修复后 **92.5ms**。30s 截止按主循环
节拍精确触发。监听恢复 6.6s(2 次 Trap 09 重试,既有行为同构)。
**当前架构**(netTask 主循环,`App/task/net_task.c`):
```
for (;;) {
[reconfig 检查 → net_stack_bring_up 重建]
net_poll(); // 读芯片中断状态、分发事件、维护 readable 标志
net_process_messages(); // ① net_pending_tick(一期:按节拍了结挂起 recv)
// ② net_relisten_retry_tick(D10:到点重试)
// ③ while(队列非空) 取一条消息;无数据阻塞 recv 则登记 pending 即返回
osDelay(1); // 主循环节拍 ≈1ms
}
```
---
## 3. 业界调研:"带超时的等数据"的五类成熟模式
| # | 模式 | 代表项目 | 处理方式 | 执行者是否被占用 |
|---|---|---|---|---|
| A | 宿主事件循环 | Node.js/libuv、glib、Qt、POSIX select/poll | 非阻塞 I/O + 就绪通知(epoll/kqueue/IOCP)+ 定时器;等待 = 登记请求,由 OS 观察就绪,"就绪或超时"唤醒后处理就绪集 | **永不允许**——Node 官方文档明文 "never block the Event Loop";长任务的两条官方解法 = **分片(partitioning,定期让出)** 或 offload 到 worker 池 |
| B | RTOS 网络栈 | LwIP(ESP32/STM32 生态事实标准,FreeRTOS 任务模型与本项目同款) | 消费者线程在**自己上下文**带超时睡眠(信号量/mailbox);tcpip 线程只在包事件时 signal;超时用 poll timer 回调 | **永不**——官方 raw API 文档:"Raw API applications may **never block** since all packet processing… is done in a single execution context";多线程章节:"Application threads… communicate with this main thread through **message passing**" |
| C | 嵌入式事件循环 | Zephyr `net_context`、ESP-IDF `esp_event` | 应用线程阻塞在自己的 k_sem/事件上;net 线程只做完成回调("callback is called by RX thread so **its** stack and execution context is used here") | 永不 |
| D | 后台 I/O 线程 + 有界 poll | librdkafka(Kafka 官方客户端,生产级) | 后台线程循环**短超时** `poll()` + 每轮间隙排空内部工作队列("calls rd_kafka_poll(timeout) in a loop") | **有界**(短 poll 量子,队列不饿死) |
| E | 独占硬件属主(offload 芯片 / 总线属主) | W5500/W6500 类芯片驱动(CH395F 同类)、共享 SPI 的"专用任务 + 作业队列"模式 | 非阻塞原语 + **调用方预算循环**;或专用任务 + 作业队列、每个作业每轮推进一步(状态机步进) | 有界(每步/每片) |
| F | 每连接一线程 | 传统 threaded server(Apache worker、Java thread-per-connection) | 每连接独占线程,阻塞 recv 只冻结自己 | N/A(隔离) |
**本项目归属**:E 类。CH395F 与 W5500 同属"SPI 总线上的硬连线 TCP/IP 协议栈"芯片(W5500 产品
定义:"Hardwired Internet controller with an integrated full TCP/IP stack… over SPI");"专用任务
+ 消息队列"是该类的标准串行化形态之一(另一形态"每调用加锁"在社区中常见,但会把"等待"也锁进
临界区——正是 E-02 的形态)。F 类不可行:SPI 铁律决定所有 socket 操作必须经 netTask 串行,
不存在"每连接一线程"的空间。
**各模式关键证据**(2026-09-22 访问):
- A:[Node.js《Don't Block the Event Loop (or the Worker Pool)》](https://nodejs.org/learn/asynchronous-work/dont-block-the-event-loop)
(partitioning 与 offloading 并列两条官方解法;"If a thread is blocked working on behalf of a
specific client request, pending requests for other clients may not get a turn")
- B:[LwIP raw API 文档](https://www.nongnu.org/lwip/2_0_x/raw_api.html)("must reside in different
execution contexts"、tcpip_thread、message passing、never block、`tcp_poll` 定时器回调);
[EEVblog LwIP 讨论](https://www.eevblog.com/forum/microcontrollers/anyone-here-familiar-with-lwip/75/)
("the LwIP code is designed to never block when the core lock is held");
[LwIP+RTOS netconn 阻塞问题](https://stackoverflow.com/questions/10848851/lwip-rtos-how-to-avoid-netconn-block-the-thread-forever);
[mbed-os LwIPSocket 非阻塞实现](https://github.com/ARMmbed/mbed-os/issues/13197)
- C:[Zephyr net_context 文档](https://docs.zephyrproject.org/latest/doxygen/html/net__context_8h.html)、
[ESP-IDF esp_event](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/esp_event.html)
- D:[librdkafka INTRODUCTION](https://github.com/confluentinc/librdkafka/blob/master/INTRODUCTION.md)、
[WaterDrop 对 librdkafka 后台线程的剖析](https://mensfeld.pl/2026/02/waterdrop-fd-polling-50-percent-faster/)
- E:[W5500 产品页](https://wiznet.io/products/ethernet-chips/w5500)、
[FreeRTOS 论坛 W5500 多任务共享](https://forums.freertos.org/t/handle-several-sockets-w5500-tcp-stack/14524)
---
## 4. 约束分析:为什么最正统形态(B 类)在本项目不可达
B 类(LwIP netconn)的三个构件在本项目的对应物:
| LwIP 构件 | LwIP 里的形态 | 本项目对应物 | 差距 |
|---|---|---|---|
| 数据到达观测 | 网卡 DMA/IRQ → pbuf 递到 tcpip 线程(免费,O(1)) | 数据到达在 CH395F **芯片内部**;唯一观测手段 = SPI 事务(GET_REMV_LEN / socket 中断状态),而 SPI 只许 netTask 发起 | **观测本身占用执行者** → 等待无法挪出 netTask |
| 消费者侧睡眠 | 应用线程睡在自己的 sem/mailbox 上(带超时) | 调用方睡在任务通知上(`net_wait_result` 两段式等待,带全掩码清除) | **已一致** ✓ |
| 完成通知 | tcpip 线程事件驱动 signal | 当前 = 等待自旋结束才通知;pending 方案 = 主循环检测到完成条件即通知 | 差"事件完成"一步 |
补充两条不可行路径:
1. **消费者自行轮询就绪**(如读 INT# GPIO 电平):INT# 只是"某 socket 有事件"的全局电平,
非 per-connection;且 AGENTS.md 明令"所有 CH395F 中断在 `net_poll()` 内集中读取并清除,
**不得**在 ISR 或其他地方单独处理"——纪律上禁止。
2. **ISR 里读 per-socket 状态**:需要 SPI 事务,CH395F 驱动非 ISR 安全(设计即"中断集中读取")。
**结论**:本项目的等待只能在 netTask 内执行,设计自由度 = ①每次占用时长 ②等待期间是否/如何
做其他事。**pending 方案 = 把两个自由度同时用满**:占用降到"登记一次 + 每轮 tick 一次读标志"
(主循环节拍级),等待期间 netTask 正常排空整个队列。
---
## 5. 方案的正当性(两代形态)
本项目的等待模型经历两代,二者都属 E 类"有界执行者等待"的合法变体:
| 代次 | 形态 | 状态 |
|---|---|---|
| 一代(分片有界等待) | `net_recv_to` + 5ms 片 + 30s 总预算 + 片间 `vTaskDelay(1)` 让出;调用方持有预算循环 | **已退役**(一期被 pending 取代) |
| 二代(pending 请求,现行) | 无数据即登记 pending、netTask 零占用返回;`net_pending_tick` 按主循环节拍(~1ms)了结 | **一线现行**(`a45c0cb`) |
**一代的正当性**(留档,说明当时的取舍不是野路子):
1. **官方认可**:Node 文档把"分片 + 定期让出"(partitioning)列为不阻塞事件循环的**一等官方解法**
(与 offload 并列;offload 在本项目不可行——SPI 独占)。5ms 片 + `vTaskDelay(1)` 让出即逐字对应。
2. **生产级先例**:librdkafka 后台 I/O 线程 = 短超时 poll + 间隙排空队列,"有界执行者等待"
在生产级客户端里被接受。
3. **变体选择有据**:审计方向 ① 原文为 "DONTWAIT 分片 + 调用方重投",实际落地选**有界阻塞片**。
理由:DONTWAIT 每片一次完整队列往返(入队+调度+取消息+通知,L5 实测 ~1.2ms),30s 等待 =
~2.5 万次往返;有界片让 netTask 片内连续多次 `net_poll`,片内到达的数据当片即收。M3 实测
支持:100ms 片受压帧 ~750ms → 5ms 片 ~10ms。
**二代相对一代的消除项**(为什么一期要推进):
- 队列最坏滞后从"一个片(5ms)+ 往返"压到 **~1ms**(主循环节拍);
- **不再依赖调用方纪律**:新消费者写裸 `net_recv(fd, buf, len, 0)`(默认 30s、无分片)也**不会**
复发头阻塞——一代的核心残留缺陷,二代结构性免疫;
- 调用方分片循环 + `vTaskDelay(1)` 让出协议(lftpd/timeSync 各 ~30 行)删除。
**仍存的残余**(转二期):
- **SEND 的 1s/分片 stall 仍冻结队列**(审计 E-02 位置明列)——二期 pending 覆盖;
- 超时精度退化到主循环节拍(被长操作占用时顺延)——现状反向打平,需文档化。
---
## 6. 演进方案:RECV 消息 → pending 请求
> **一期(RECV)已实施**(`a45c0cb`),实现实测与基线的偏差见 §6.7;下文 §6.1 保留为设计基线
> 原文(含二期扩展),§6.2~§6.6 为当初的利弊/改动量/门禁评估,§6.7 为落地实录。
### 6.1 机制
- `net_sock_t` 增加 pending 字段:`buf 指针 / len / flags / deadline(tick) / caller 句柄 / active`
(≈20B/fd × 8 fd ≈ 160B 静态增长);
- `net_process_messages` 的 RECV 分支:数据已在 → 立即读出(**现快速路径不变**);数据未至且
`timeout_ms > 0` → **登记 pending、跳过本次通知、继续循环取下一条消息**;
- 新增 `net_pending_tick()`(与 `net_relisten_retry_tick` 同位——主循环每轮调用),对每个带
pending 的 fd 走五路完成/取消:
| # | 条件 | 动作 |
|---|---|---|
| 1 | 数据到达(`readable` 标志已由 net_poll 每轮更新,零额外 SPI) | SPI 读出 + 通知调用方(结果 = 字节数) |
| 2 | `HAL_GetTick() >= deadline` | 通知(`NET_ERR_TIMEDOUT` → 对外 -2 映射保持) |
| 3 | EOF/DISCONNECT 事件(`handle_disconnect_event` 路径发现 pending) | 按 0(EOF) 完成 + auto_relisten + 通知 |
| 4 | 同 fd 的 CLOSE 等后续操作 | per-fd 串行:先完成 pending 再执行(冻结面从"全网"缩到"本 fd") |
| 5 | 网络重建(`net_stack_bring_up`,芯片复位) | **取消 + 必须通知**(调用方阻塞等回执,取消不通知 = 永久挂死) |
- **调用方与公开 API 不变**:仍 `net_wait_result` 阻塞等通知(30s 睡眠发生在调用方自己上下文
——与 LwIP 模型一致);`net_recv`/`net_recv_to` 返回契约不变,测试/模拟器/既有调用方零改动。
### 6.2 好处
1. **头阻塞缺陷类消灭**(而非封顶):等待期间 netTask 零额外占用,队列延迟 = 一个主循环周期
(~1ms);
2. **不再依赖调用方纪律**:任意新消费者写裸 `net_recv(..., 0)` 也不会冻结队列;
3. **调用方简化**:lftpd/timeSync 的分片循环 + `vTaskDelay(1)` 让出协议(各 ~30 行)删除,
还原为一次 `net_recv_to(fd, ..., 30000)`;
4. **E-06/E-20/E-21 共用机制**:accept 轮询循环(100ms/200ms)、SEND 1s/分片 stall 同型转化
(ACCEPT pending = CONNECT 事件完成;SEND 续传 = send_ready 完成)——第二档 #1 四条目收敛
为一个机制;
5. **长等待 SPI/CPU 成本归零**:30s 等待从 ~6000 次专属轮询降为搭主循环既有 `net_poll` 的便车。
### 6.3 坏处 / 代价
1. **执行者获得跨时间状态 → 边界交互面变大**:§6.1 五路语义每条都是新的时序边界,须逐一定义
并测试——本库 D 系列(D10~D20)历史即此类边界的坟场;
2. **只改 RECV 则收益对折**:SEND 1s/分片 stall 仍在(需二期);
3. **超时精度退化到主循环节拍**:主循环若正被长操作(如 SEND stall)占用,RECV 超时最多顺延
相应时长(现状是反方向,打平,需文档化);
4. **验证成本 >> 代码量**:net 层是回归最敏感区(09-21 事故、D 系列),执行器核心改动 = 全
套回归 + 基线重锁,台架投入天量级;
5. **新故障类**:"pending 登记后永不完成"(完成条件 bug / fd 状态与芯片失步)→ 调用方无限期
睡眠——需配套看门狗/自检(pending 最大龄告警);
6. **模拟器差距 +1**:`net_socket_sim.c`(单线程直连 Winsock)无法建模 pending,附录 D 结构性
差距清单加一条;
7. **排障文档需更新**:"结果缺失"类问题新增成因(pending 滞留),`net_wait_result` 两段式
等待与 [LAT] 探针的假设需补充说明。
### 6.4 改动量
| 阶段 | 内容 | 规模 |
|---|---|---|
| 一期(RECV) | `net_sock_t` pending 字段;RECV 分支"有数据即读 / 无数据登记";`net_pending_tick()` 五路完成/取消;close/rebuild 取消钩子 | **~200-400 行,集中在 `net_socket.c`;公开 API 零改动** |
| 调用方简化(可随一期) | lftpd `read_line`/`read`、timeSync `handle_conn` 分片循环 → 单次调用 | 各删 ~30 行 |
| 二期(可选:ACCEPT + SEND) | ACCEPT pending(E-06 accept 计时 / E-20 / E-21 轮询循环退役);SEND 续传 pending(1s stall 非占用化) | 再 ~300-500 行;L3/L5 基线再变 |
风险评级:**中**(执行器核心 + D 系列前科)。代码量不是主要成本,验证才是。
### 6.5 验证门禁(实施时逐项过)
1. CH395F NET 层全套件(Phase 6-14);
2. M3 基线重锁:L5 队列往返(预期 ~1ms 量级)、L3/L7 生产路径 Δ;
3. `test/host/e02_probe.py` A/B 回归(队列响应性应优于 5ms 片方案);
4. `test/host/ftp_regression.py`(D20)+ E-06 假 425 场景;
5. UI 远端推流压力(ui_net_sink 100Hz);
6. timeSync 三场景(挂起 / 部分包 / 正常包);
7. 产品构建 `@test` 闭环 + ST-LINK 全片回读;
8. `scripts/ram_report.py` 前后对比(铁律);`scripts/stack_report.py` 栈水位。
### 6.6 风险缓解
- 一期只做 RECV;**保留分片路径作影子对照/回退开关**(双路径并行验证后再摘除);
- 复用 D10 `net_relisten_retry_tick` 的"登记→到点完成"骨架(已在生产验证);
- 探针族扩充:close-during-pending / reconfig-during-pending / EOF-during-pending /
disconnect-during-pending(扩展 `e02_probe.py`);
- pending 最大龄自检(selftest 留痕,防"永不完成");
- 排障文档同步(`错误码传播审计.md` / `链路延迟测试说明.md` §9 故障对照表)。
### 6.7 实施记录(一期,2026-09-22,commit `a45c0cb`)
**实现与 §6.1 基线的一致性/偏差**(diff 已逐行评审):
| 基线条目 | 实施 | 说明 |
|---|---|---|
| pending 控制块 ≈20B/fd | `net_pending_t` = {active 1B, buf 4B, len 4B, deadline 4B, registered 4B, caller 4B} ≈24B/fd × 8 = **192B**(+4B `s_net_task_handle`) | 实测 SRAM +200B,与估算同量级 |
| 控制块位置:`net_sock_t` 内 | **偏差:独立静态数组** `s_net_pending[NET_MAX_SOCKETS]` | `net_close_locked` 对 `net_sock_t` 做整块 memset——置入表内则 close 静默抹掉 pending(调用方悬空);独立表 = §6.3#1 预警的"跨时间状态"与 socket 表解耦,仿 D10 relisten 表的生产验证模式 |
| 无数据 → 登记 pending、跳过本次通知 | 哨兵 `NET_PENDING_REGISTERED`(0x70000000)→ dispatch `do_notify=0` | 逐字一致 |
| 五路完成/取消 | tick 实际顺序:① 数据(`readable` 门控 SPI 读,ESTABLISHED/UDP_OPEN;spurious readable 清除)② deadline(状态无关、有符号回绕安全差值)→ TIMEDOUT ③ CLOSED:排空→数据否则 EOF(0)+auto-relisten ④ 他态等待(**不做**状态推断取消)⑤ 1s 看门狗强结算 + DBG_ERROR | 基线 #3 的"EOF 发现"实现为 CLOSED 态排空判定;基线 #4(CLOSE 先行完成 pending)= `net_close` 的 settle 钩子(排空→数据否则 CONNRESET);基线 #5(重建取消必通知)= `net_init` 顶部 `net_pending_cancel_all(CONNRESET)`(先于芯片复位);RESYNC_LISTEN 陈旧分支/`net_socket` 另加 cancel/clear 钩子 |
| 看门狗/自检(§6.6) | 1s 最大龄看门狗强结算 + DBG_ERROR | 简化版:强结算防"永不完成",未接 selftest 留痕(留二期) |
| 调用方简化:单次 `net_recv_to(…, 30000)` | **偏差:剩余预算循环**(`rem = 预算 − 已耗时` 作片长,`n==-2` 续轮,`rem==0` 退出) | 公开契约(30s 总超时语义、跨 TCP 分段累积)要求调用方保留循环骨架;删掉的是分片常数 + `vTaskDelay(1)` 让出协议(改为睡任务通知)——净效果与基线 #3 目标一致 |
| 登记守卫(基线未列,实施新增) | 每 fd 至多一个 pending(**不覆盖**);`caller==NULL` 或 `caller==netTask` 拒绝(BUSY) | 覆盖 = 丢首个调用方通知 = 永久挂起;netTask 上下文自通知 = 无完成者死锁——§6.3#1 边界风险的两条实证化防线 |
**§6.5 验证门禁逐条结果**(2026-09-22 下午,设备 192.168.1.100,pending 构建):
| # | 门禁 | 结果 |
|---|---|---|
| 1 | CH395F NET 层套件 | **PASS(分组合并执行)**:F1 组合 Phase 6/9/11——64B/1460B 回显 11/11、select 回显 11/11、断开重连、KeepAlive 断连 + auto-relisten 全 PASS;F2 组合 Phase 8-RECV——100KB 阻塞接收 50/50 块(2048B/块)逐块校验 + CRC32 整包一致(0x9A0E0C8C)+ 收齐 close + auto-relisten。Phase 7(TC703 环境互斥 + 全 DONTWAIT 不经过 pending)、Phase 10(双 32KB 缓冲与全产品镜像结构性超 RAM)本轮未跑——DONTWAIT 路径另由 M3 探针族(L5~L7 全 DONTWAIT)重锁覆盖。TC-NET-604 4096B 子项 FAIL = **既有芯片侧问题**(A/B:切片构建行为逐字节相同,L3 无责;后续经真实路径 227 轮复测判定为非缺陷,2026-09-23 结案,见 `CH395F_Trap_Records.md` Trap 21) |
| 2 | M3 基线重锁 | **PASS**:静默档 host 帧 med 58.9/p95 69.9/max 72.1ms 零尖峰;压力档(FTP 头阻塞工况实发)med 60.1/p95 66.4/max 69.3ms 零尖峰(分片基线 65.0/133.5 → p99 尾部压缩近半);MCU `prod_cycle_mcu` med 6706µs 压力下平坦(min 6698/max 6720);relisten 89ms×3;L5~L7 探针路径(DONTWAIT)不受 pending 影响 |
| 3 | e02_probe A/B 回归 | **PASS 且优于分片方案**:队列响应性 92.5ms(分片 109/75ms);30s 截止按节拍精确触发(30.1s);超时留痕在位;TIME 正常路径全通;监听恢复 6.6s(2 次 Trap 09 重试,既有行为同构) |
| 4 | ftp_regression / E-06 假 425 | **随 F1/F2 台架 + M3 压力档覆盖**(FTP 空闲登录头阻塞工况 + 数据通道收发);未单独重跑 D20 脚本(其场景 = M3 压力档的 FTP 半登录态,已实证) |
| 5 | UI 远端推流压力 | **PASS** = M3 静默/压力两档(ui_net_sink :7003 100Hz 全帧 CRC 50/50,零尖峰) |
| 6 | timeSync 三场景 | **PASS**:挂起客户端(e02_probe 主场景)/ 正常包(wall clock updated + RTC 回写);部分包场景由 Phase 8-RECV 100KB 跨段累积(同 `handle_conn` 跨片累积逻辑的 pending 化形态)等效覆盖 |
| 7 | 产品 `@test` + 全片回读 | **PASS**:Required 全中/Forbidden 零命中;烧录回读 `No difference found` |
| 8 | RAM/栈前后对比 | **PASS**:SRAM +200B(192B pending 表 + 4B 句柄 + 4B 他项)/Flash +608B;netTask 运行栈峰值 488B/4096(余量 88%)、静态最坏链 432B——零占用设计落点;六任务水位全 PASS(defaultTask 29% 边际 = 既有静态链,与 L3 无关) |
**未执行/延后项(如实留档)**:
- §6.6"保留分片路径作影子对照/回退开关"→ **未保留**,分片协议直接退役;对照目的由"旧镜像 A/B"承担(A/B 轮即影子验证),回退路径 = git revert(单提交、API 不变);
- 探针族扩充(close/reconfig/EOF/disconnect-during-pending 专项)→ 二期随 SEND/ACCEPT 一并建;
- pending 看门狗接 selftest 留痕 → 二期;
- 模拟器差距 +1(`net_socket_sim.c` 单线程 Winsock 无法建模 pending)→ 附录清单更新随二期;
- **tick 放置后果(一期文档化、不修)**:pending 完成判定随主循环节拍运行——队列里排着长 SEND/CLOSE 消息处理时,同 tick 的 pending 完成顺延至下轮(~1ms 级,长 SEND stall 1s 期间最多顺延相应时长)= §6.3#3 的已知代价,按"文档化"处置;
- 台架期间另发现一次 49s 全系统日志静默(defaultTask/NAND syslog 排空停滞,net 栈照常工作)——既有存储侧现象,与 L3 无关,转 `docs/待处理内容.md` N-2。
---
## 7. 结论与实施建议
1. **一期(RECV pending 化)已实施、已全量台架复验、已并入主线并推送**(`a45c0cb` + `7ff2958`,
`v2-on-ui`;门禁逐条结果见 §6.7):头阻塞缺陷类结构性消灭、调用方分片协议退役、M3 压力档
p99 尾部 133.5ms→69.3ms、队列响应性 92.5ms、RAM +200B。**本项(E-02)至此闭环,无遗留动作。**
2. **二期(ACCEPT/SEND)待排期**——E-06/E-20/E-21 剩余分量(SEND 1s/分片 stall、accept 轮询
计时失真、errno 分级)共用同一 pending 机制扩展;届时 L3/L5 基线再重锁。
**实施时机 = `项目审计改进清单.md` 第二档 #2**(与 GD5F 错误通道统一并列,见第 2 项)。
3. **路线**:~~一期 RECV(影子验证)~~ ✅ 已完成 → 二期 ACCEPT → SEND(最复杂:多分片/短发送/
L3 探针钩子)。
4. **二期启动动作**:以 §6.1 为设计基线评审(含 §6.7 一期实测对基线的修正) → 按 §6.5 门禁执行
→ 按 E-01/E-31/E-32/E-02 的留档惯例更新 `错误码传播审计.md`(明细"已修复"+ 页脚闭环注记 +
提交记录)+ 销 `docs/待处理内容.md` N-4。
**一句话**:好处 = 缺陷类消灭 + 调用方解放 + E-06/20/21 共用机制;坏处 = 执行器状态机复杂化
+ 天量级台架验证;改动本身不大(一期 ~200-400 行、API 不变),大的是验证。**一期已验证此判断
成立**(RAM +200B / Flash +608B,验证成本远超代码量)。
---
## 9. 修订记录
| 日期 | 内容 |
|---|---|
| 2026-09-22 | 初版:五类业界模式对照 + pending 演进方案 + §6.7 一期实施记录 |
| 2026-09-26 | 复核修订:①"已落地修复"由一代分片改为二代 pending(§1/§2/§5),一代降级为留档;②更正一期提交号 `f16dc9a`/`wip/v2-pending-recv` → `a45c0cb`(实测该分支与哈希不存在,应为临时工作区);③§7 一期标闭环、二期实施时机锚定审计清单第二档 #2 |
---
## 8. 参考链接(2026-09-22 访问)
| 来源 | 用途 |
|---|---|
| [Node.js:Don't Block the Event Loop (or the Worker Pool)](https://nodejs.org/learn/asynchronous-work/dont-block-the-event-loop) | A 类:never block 规则 + partitioning 官方解法 |
| [LwIP raw API 文档(2.0.x)](https://www.nongnu.org/lwip/2_0_x/raw_api.html) | B 类:tcpip_thread / message passing / never block / tcp_poll |
| [EEVblog:Anyone here familiar with LWIP?](https://www.eevblog.com/forum/microcontrollers/anyone-here-familiar-with-lwip/75/) | B 类:tcpip 线程不阻塞的设计陈述与社区讨论 |
| [SO:LWIP + RTOS how to avoid netconn block the thread forever](https://stackoverflow.com/questions/10848851/lwip-rtos-how-to-avoid-netconn-block-the-thread-forever) | B 类:netconn 阻塞超时/非阻塞的常见问法 |
| [mbed-os issue #13197:Non-blocking recv with lwip](https://github.com/ARMmbed/mbed-os/issues/13197) | B 类:LwIPSocket 非阻塞实现的真实案例 |
| [Zephyr:net_context API](https://docs.zephyrproject.org/latest/doxygen/html/net__context_8h.html) | C 类:回调在 RX 线程上下文执行 |
| [ESP-IDF:Event Loop Library](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/esp_event.html) | C 类:事件循环 + 队列 |
| [librdkafka INTRODUCTION](https://github.com/confluentinc/librdkafka/blob/master/INTRODUCTION.md) | D 类:多线程库 + 有界 poll |
| [WaterDrop:One Thread to Poll Them All(librdkafka 后台线程剖析)](https://mensfeld.pl/2026/02/waterdrop-fd-polling-50-percent-faster/) | D 类:后台线程 `rd_kafka_poll(timeout)` 循环 |
| [WIZnet W5500 产品页](https://wiznet.io/products/ethernet-chips/w5500) | E 类:同类 offload 芯片定义 |
| [FreeRTOS 论坛:Handle several sockets (W5500)](https://forums.freertos.org/t/handle-several-sockets-w5500-tcp-stack/14524) | E 类:多任务共享 offload 芯片的加锁/串行化实践 |
| 库内:`错误码传播审计.md` E-02 明细 / `docs/测试说明/链路延迟测试说明.md` §8.3 / AGENTS.md SPI 铁律 | 本项目约束与已验证基线 |
@@ -0,0 +1,97 @@
# Net 层阻塞模型改造实施记录(E-02)
> **模块名称**:Net 层(net_socket / netTask)阻塞等待模型
> **文档性质**:**客观实施记录**——只记录"做了什么、实测到什么、哪些没做"。
> 设计原理与机制细节见 `docs/网络/BSD_Socket_API_使用指南.md`、`docs/网络/BSD_Socket_API_函数调用关系.md`;
> 基线数据见 `docs/测试说明/链路延迟测试说明.md`;缺陷明细见 `错误码传播审计.md` E-02。
> **状态**:**一期(RECV pending 化)已实施、已全量台架复验、已并入主线 `v2-on-ui` 并推送**
> (`a45c0cb` 实现 + `7ff2958` 文档闭环)。二期(ACCEPT/SEND)待排期——
> 设计基线与排期见 `docs/审查记录/下一步任务规划.md`。
> **日期**:2026-09-22(2026-09-26 复核修订)
---
## 1. 缺陷与修复动机
**E-02**(P1,明细见 `错误码传播审计.md`):netTask 是全部 socket 操作的唯一执行者,
`net_process_messages` 每次取一条消息处理到完成才取下一条。任一消费者发起的 30s 阻塞
`net_recv`(`net_recv_locked` 自旋 `net_poll` + `ch395f_get_recv_len`)期间,队列整体
停摆最长 30s——FTP 客户端空闲 >30s、对时客户端连上不发数据,均为常见触发工况。
**台架实证**(`test/host/e02_probe.py`,2026-09-22,设备 192.168.1.100):挂起对时客户端
连 :8888 不发数据,2s 后 PC 测 FTP(:21) banner 时延 = 队列响应性——修复前 **28554ms**
(设备日志实证芯片侧握手与 MCU 侧处理相隔 27s;旧代码 30s 后静默拆连零日志)。
---
## 2. 实施方案(两代形态)
| 代次 | 形态 | 状态 | 提交 |
|---|---|---|---|
| 一代 | **分片有界等待**:`net_recv_to` + 5ms 片 + 30s 总预算 + 片间 `vTaskDelay(1)` 让出;调用方持有预算循环 | 已退役(一期取代) | `f8d6e90`(lftpd)/ `4a1605b`(timeSync) |
| 二代 | **pending 请求**:无数据即登记挂起、netTask 零占用返回;`net_pending_tick` 按主循环节拍(~1ms)了结 | **一线现行** | `a45c0cb`(一期) |
**二代机制要点**(细节见 `docs/网络/` 两份文档):
- `net_sock_t` 之外的**独立静态表** `s_net_pending[NET_MAX_SOCKETS]` 保存挂起请求;
- `net_process_messages` 的 RECV 分支:数据已在 → 立即读出(快速路径不变);无数据且
`timeout_ms > 0` → 登记待定、跳过本次通知、继续取下一条;
- `net_pending_tick()` 每轮主循环执行,五路完成/取消:① 数据到达 ② 到点超时
③ EOF/DISCONNECT ④ 同 fd 后续操作先行结算 ⑤ 网络重建取消必通知;
- 公开 API 与调用契约不变;调用方仍在**自己上下文**睡任务通知(与 LwIP 模型一致)。
---
## 3. 实施与设计基线的偏差(如实留档)
| 基线条目 | 实施 | 说明 |
|---|---|---|
| pending 控制块 ≈20B/fd | `net_pending_t` ≈24B/fd × 8 = **192B**(+4B `s_net_task_handle`) | 实测 SRAM +200B,与估算同量级 |
| 控制块置于 `net_sock_t` 内 | **偏差:独立静态数组** `s_net_pending[]` | `net_close_locked` 对 `net_sock_t` 整块 memset——置于表内则 close 静默抹掉 pendn(调用方悬空);独立表把"跨时间状态"与 socket 表解耦,仿 D10 relisten 表的生产验证模式 |
| 无数据 → 登记 pending、跳过通知 | 哨兵 `NET_PENDING_REGISTERED`(0x70000000)→ dispatch `do_notify=0` | 逐字一致 |
| 五路完成/取消 | tick 实际顺序:① 数据(`readable` 门控 SPI 读,ESTABLISHED/UDP_OPEN;spurious readable 清除)② deadline(状态无关、有符号回绕安全差值)→ TIMEDOUT ③ CLOSED:排空→数据否则 EOF(0)+auto-relisten ④ 他态等待(**不做**状态推断取消)⑤ 1s 看门狗强结算 + DBG_ERROR | CLOSE 先行完成 pending = `net_close` settle 钩子;重建取消必通知 = `net_init` 顶部 `net_pending_cancel_all(CONNRESET)`(先于芯片复位);RESYNC_LISTEN 陈旧分支另加 cancel/clear 钩子 |
| 看门狗 | 1s 最大龄强结算 + DBG_ERROR | 简化版:防"永不完成",未接 selftest 留痕(留二期) |
| 调用方改单次 `net_recv_to(…, 30000)` | **偏差:保留剩余预算循环**(`rem = 预算 − 已耗时` 作片长,`n==-2` 续轮,`rem==0` 退出) | 公开契约(30s 总超时语义、跨 TCP 分段累积)要求保留循环骨架;删掉的是分片常数 + `vTaskDelay(1)` 让出(改为睡任务通知) |
| 登记守卫(基线未列) | 每 fd 至多一个 pending(**不覆盖**);`caller==NULL` 或 `caller==netTask` 拒绝(BUSY) | 覆盖 = 丢首个调用方通知 = 永久挂起;netTask 上下文自通知 = 无完成者死锁 |
---
## 4. 验证门禁逐条实测结果
(2026-09-22 下午,设备 192.168.1.100,pending 构建)
| # | 门禁 | 结果 |
|---|---|---|
| 1 | CH395F NET 层套件 | **PASS(分组合并执行)**:F1 组合 Phase 6/9/11——64B/1460B 回显 11/11、select 回显 11/11、断开重连、KeepAlive 断连 + auto-relisten 全 PASS;F2 组合 Phase 8-RECV——100KB 阻塞接收 50/50 块(2048B/块)逐块校验 + CRC32 整包一致(0x9A0E0C8C)+ 收齐 close + auto-relisten。Phase 7(TC703 环境互斥 + 全 DONTWAIT 不经过 pending)、Phase 10(双 32KB 缓冲与全产品镜像结构性超 RAM)本轮未跑——DONTWAIT 路径另由 M3 探针族(L5~L7)重锁覆盖。TC-NET-604 4096B 子项 FAIL = **既有芯片侧问题**(A/B 切片构建行为逐字节相同,L3 无责;经真实路径 227 轮复测判定非缺陷,2026-09-23 结案,见 Trap 21) |
| 2 | M3 基线重锁 | **PASS**:静默档 host 帧 med 58.9/p95 69.9/max 72.1ms 零尖峰;压力档(FTP 头阻塞工况实发)med 60.1/p95 66.4/max 69.3ms 零尖峰(分片基线 65.0/133.5 → p99 尾部压缩近半);MCU `prod_cycle_mcu` med 6706µs 压力下平坦(min 6698/max 6720);relisten 89ms×3;L5~L7 探针路径(DONTWAIT)不受 pending 影响 |
| 3 | e02_probe A/B 回归 | **PASS 且优于分片方案**:队列响应性 **92.5ms**(分片 109/75ms);30s 截止按节拍精确触发(30.1s);超时留痕在位;TIME 正常路径全通;监听恢复 6.6s(2 次 Trap 09 重试,既有行为同构) |
| 4 | ftp_regression / E-06 假 425 | **随 F1/F2 台架 + M3 压力档覆盖**(FTP 空闲登录头阻塞工况 + 数据通道收发);未单独重跑 D20 脚本(其场景 = M3 压力档的 FTP 半登录态,已实证) |
| 5 | UI 远端推流压力 | **PASS** = M3 静默/压力两档(ui_net_sink :7003 100Hz 全帧 CRC 50/50,零尖峰) |
| 6 | timeSync 三场景 | **PASS**:挂起客户端(e02_probe 主场景)/ 正常包(wall clock updated + RTC 回写);部分包场景由 Phase 8-RECV 100KB 跨段累积等效覆盖 |
| 7 | 产品 `@test` + 全片回读 | **PASS**:Required 全中 / Forbidden 零命中;烧录回读 `No difference found` |
| 8 | RAM/栈前后对比 | **PASS**:SRAM **+200B**(192B pending 表 + 4B 句柄 + 4B 他项)/ Flash **+608B**;netTask 运行栈峰值 488B/4096(余量 88%)、静态最坏链 432B——零占用设计落点;六任务水位全 PASS(defaultTask 29% 边际 = 既有静态链,与 L3 无关) |
---
## 5. 未执行 / 延后项(如实留档)
- **未保留分片路径作影子对照/回退开关** → 分片协议直接退役;对照目的由"旧镜像 A/B"承担
(A/B 轮即影子验证),回退路径 = git revert(单提交、API 不变);
- 探针族扩充(close/reconfig/EOF/disconnect-during-pending 专项)→ 二期随 SEND/ACCEPT 一并建;
- pending 看门狗接 selftest 留痕 → 二期;
- 模拟器差距 +1(`net_socket_sim.c` 单线程 Winsock 无法建模 pending)→ 附录清单更新随二期;
- **tick 放置后果(一期文档化、不修)**:pending 完成判定随主循环节拍运行——队列里排着长
SEND/CLOSE 消息处理时,同 tick 的 pending 完成顺延至下轮(~1ms 级,长 SEND stall 1s 期间
最多顺延相应时长);
- 台架期间另发现一次 49s 全系统日志静默(defaultTask/NAND syslog 排空停滞,net 栈照常工作)
——既有存储侧现象,与本次改造无关,转 `docs/待处理内容.md` N-2。
---
## 6. 结论
E-02 **已闭环,无遗留动作**。头阻塞缺陷类结构性消灭、调用方分片协议退役、M3 压力档 p99 尾部
133.5ms→69.3ms、队列响应性 28554ms→92.5ms、RAM +200B / Flash +608B。
二期(ACCEPT/SEND)覆盖剩余分量(SEND 1s/分片 stall、accept 轮询计时失真、errno 分级)——
设计基线与排期见 `docs/审查记录/下一步任务规划.md`。
+1 -1
View File
@@ -10,7 +10,7 @@
> **本版**:2026-09-25 重写 —— ① 已闭环项从正文移除,只在 §2 留一行索引;② 全部未闭环项
> **逐项回到当前代码复核**;③ 新增本轮复核发现。
> **代码基线**:`v2-on-ui` @ `9a8255f`(2026-09-24),复核日期 2026-09-25
> **配套文档**:`docs/待处理内容.md`(N-2/N-4 登记项)、`docs/问题记录/Net层阻塞模型业界对照与演进方案.md`(E-02 配套)、
> **配套文档**:`docs/待处理内容.md`(N-2/N-4 登记项)、`docs/问题记录/Net层阻塞模型改造实施记录.md`(E-02 配套)、
> `docs/问题记录/*_Trap_Records.md`(模块陷阱史)、`AGENTS.md`(已固化铁律)
---