From 0485e79da0c4b452053187f23cdac455a483ad3a Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Tue, 29 Sep 2026 05:51:16 +0800 Subject: [PATCH] =?UTF-8?q?Net=20=E9=98=BB=E5=A1=9E=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=94=B9=E5=86=99=E4=B8=BA=E6=9E=B6=E6=9E=84?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E5=B9=B6=E8=BF=81=E5=85=A5=20docs/=E7=BD=91?= =?UTF-8?q?=E7=BB=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Drivers/BSP/NET/README.md | 2 +- Drivers/BSP/README.md | 2 +- docs/README.md | 3 +- docs/审查记录/下一步任务规划.md | 5 +- docs/待处理内容.md | 2 +- docs/网络/BSD_Socket_API_函数调用关系.md | 2 +- docs/网络/Net层阻塞模型架构设计.md | 236 +++++++++++++++++++++ docs/问题记录/Net层阻塞模型改造实施记录.md | 97 --------- docs/问题记录/错误码传播审计.md | 2 +- 9 files changed, 244 insertions(+), 107 deletions(-) create mode 100644 docs/网络/Net层阻塞模型架构设计.md delete mode 100644 docs/问题记录/Net层阻塞模型改造实施记录.md diff --git a/Drivers/BSP/NET/README.md b/Drivers/BSP/NET/README.md index 6e241e79..15290475 100644 --- a/Drivers/BSP/NET/README.md +++ b/Drivers/BSP/NET/README.md @@ -60,6 +60,6 @@ - 上层用法:`docs/网络/BSD_Socket_API_使用指南.md` - 内部调用关系:`docs/网络/BSD_Socket_API_函数调用关系.md` -- 实施记录:`docs/问题记录/Net层阻塞模型改造实施记录.md`(E-02 pending 化) +- 架构设计:`docs/网络/Net层阻塞模型架构设计.md`(阻塞等待 / pending 请求模型) - 二期设计基线:`docs/审查记录/下一步任务规划.md` §3.1 - 测试:`docs/测试说明/CH395F_Test_Guide.md`、`docs/测试说明/FTP_Test_Guide.md` diff --git a/Drivers/BSP/README.md b/Drivers/BSP/README.md index 9cf14576..502e47dc 100644 --- a/Drivers/BSP/README.md +++ b/Drivers/BSP/README.md @@ -12,7 +12,7 @@ | `TPAFE5160/` | TPAFE5160 高精度 ADC | 并行 16 位 | ADC 采样驱动(CONVST/BUSY 时序) | — | | `SD2506/` | SD2506 RTC | I2C | 实时时钟驱动 | `docs/问题记录/SD2506_Trap_Records.md` | | `RS485/` | RS-485 半双工 | UART5 | 收发方向控制(DE 引脚)+ 时序 | — | -| `NET/` | BSD Socket 网络抽象层 | — | Socket API + select + 轻量 FTP 服务器 | `docs/网络/`、`docs/问题记录/Net层阻塞模型改造实施记录.md` | +| `NET/` | BSD Socket 网络抽象层 | — | Socket API + select + 轻量 FTP 服务器 | `docs/网络/`(含 `Net层阻塞模型架构设计.md`) | | `NETCFG/` | 网络配置 | — | `/config.ini` 网络段的加载/保存 + 旧档迁移 | `docs/子系统设计/网络配置说明.md` | | `UI/` | LVGL UI 组件 | — | 菜单/内容页/组件/中文字体 | `docs/UI设计/` | diff --git a/docs/README.md b/docs/README.md index 8a25039b..032dafbb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -78,7 +78,7 @@ docs/ | [`运行与自检记录设计说明.md`](子系统设计/运行与自检记录设计说明.md) | `/log/run.log`·`selftest.log` 定长记录与待机显示 | | [`网络/BSD_Socket_API_使用指南.md`](网络/BSD_Socket_API_使用指南.md) | **上层视图**:BSD Socket API 公开语义、示例、常见问题 | | [`网络/BSD_Socket_API_函数调用关系.md`](网络/BSD_Socket_API_函数调用关系.md) | **内部视图**:netTask / 消息队列 / L3 挂起 / 重试对账的调用关系与设计意图 | - +| [`网络/Net层阻塞模型架构设计.md`](网络/Net层阻塞模型架构设计.md) | **等待模型**:pending 请求架构、五路完成语义、设计边界与性能特征 | --- ## 5. 测试说明 @@ -147,7 +147,6 @@ 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) | E-02 阻塞模型改造客观实施记录(一期 pending 化:偏差/门禁实测/未执行项) | | [`错误码传播审计.md`](问题记录/错误码传播审计.md) | 错误码传播缺陷审计(9 类模式 × 子系统) | --- diff --git a/docs/审查记录/下一步任务规划.md b/docs/审查记录/下一步任务规划.md index a6be2839..d13af8e4 100644 --- a/docs/审查记录/下一步任务规划.md +++ b/docs/审查记录/下一步任务规划.md @@ -115,9 +115,8 @@ ## 3.1 C1 设计基线(pending 二期:ACCEPT + SEND) -> **来源**:从已归档的《Net 层阻塞模型业界对照与演进方案》(2026-09-26 删除)中抽取—— -> 该文档的调研/规划部分已完成使命,客观实施部分另存为 -> `docs/问题记录/Net层阻塞模型改造实施记录.md`;本节仅保留**二期仍要用的设计基线**。 +> **来源**:一期(RECV)架构现状见 `docs/网络/Net层阻塞模型架构设计.md`(含演进溯源附录); +> 本节仅保留**二期仍要用的设计基线**。 **一期已验证的机制骨架**(二期沿用,勿重新发明):独立静态 pending 表 + `net_pending_tick` 主循环节拍了结(五路:数据/到点/断连/同 fd 串行/重建取消必通知)+ 登记守卫(每 fd 至多一个、 diff --git a/docs/待处理内容.md b/docs/待处理内容.md index e456346e..c0d1b6a8 100644 --- a/docs/待处理内容.md +++ b/docs/待处理内容.md @@ -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`);设计基线与门禁见 `下一步任务规划.md` §3.1,实施记录见 `Net层阻塞模型改造实施记录.md` | 同左 + `错误码传播审计.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`);架构现状见 `Net层阻塞模型架构设计.md`,二期设计基线与门禁见 `下一步任务规划.md` §3.1 | 同左 + `错误码传播审计.md` 第二档 #2 | diff --git a/docs/网络/BSD_Socket_API_函数调用关系.md b/docs/网络/BSD_Socket_API_函数调用关系.md index 8a68441e..31568cdc 100644 --- a/docs/网络/BSD_Socket_API_函数调用关系.md +++ b/docs/网络/BSD_Socket_API_函数调用关系.md @@ -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` —— 阻塞等待模型的现状架构设计(pending 请求模型 / 五路完成语义) - `docs/问题记录/错误码传播审计.md` —— E-02 头阻塞与错误码回传全审计 - `docs/测试说明/链路延迟测试说明.md` —— D1/D10/L3/D14 等时延探针与自愈路径的台架证据 - `docs/子系统设计/网络配置说明.md` §4 —— 代次号与网络重建时序 diff --git a/docs/网络/Net层阻塞模型架构设计.md b/docs/网络/Net层阻塞模型架构设计.md new file mode 100644 index 00000000..b251488b --- /dev/null +++ b/docs/网络/Net层阻塞模型架构设计.md @@ -0,0 +1,236 @@ +# Net 层阻塞模型架构设计 + +> **模块名称**:Net 层(`net_socket.c` / netTask)阻塞等待模型 +> **文档定位**:**现状架构设计说明**——描述本层**当前如何组织等待与完成**、为什么这样设计、 +> 边界条件与已验证的性能特征。**不是历史记录**;演进过程与门禁实测数据作为溯源附于文末。 +> **状态**:设计已落地并全量台架验证(`v2-on-ui`)。 +> **日期**:2026-09-29 +> **相关文档**: +> `docs/网络/BSD_Socket_API_使用指南.md`(应用视角 API 语义)、 +> `docs/网络/BSD_Socket_API_函数调用关系.md`(调用链与执行域)、 +> `docs/测试说明/链路延迟测试说明.md`(延迟基线与故障对照)、 +> `docs/审查记录/下一步任务规划.md` §3.1(二期 ACCEPT/SEND 扩展设计) + +--- + +## 1. 问题域 + +netTask 是**全部 socket 操作的唯一执行者**——CH395F 的 SPI 总线归它独占(SPI 铁律), +因此所有 socket 操作必须经消息队列串行化到 netTask 上下文完成。 + +这带来一个结构性约束:**消费者发起的"等待数据"会占住执行者**。若 `net_recv` 采用 +"在 netTask 内自旋轮询直到数据到达"的朴素形态,一条空闲连接即可让整个网络层停摆—— +所有其他 socket 的操作都要排队等它。 + +> **约束的本质**:本项目的"数据到达"无法被免费观测。业界正统形态(LwIP 等)依赖网卡 +> DMA/IRQ 把数据递到协议线程,数据到达是 O(1) 事件;而本项目的数据到达发生在 CH395F +> **芯片内部**,唯一观测手段是一次 SPI 事务,而 SPI 只许 netTask 发起。 +> → **观测本身占用执行者**,等待无法挪出 netTask。 + +设计自由度因此只剩两条:① 每次占用执行者多久 ② 等待期间执行者还能做什么。 +本架构的答案:**占用降到登记一次(微秒级),等待期间执行者照常服务整个队列**。 + +--- + +## 2. 架构总览:pending 请求模型 + +核心思想:把"等数据"从**执行者内的自旋**改为**执行者外的登记**。 + +``` + 调用方任务 netTask(执行者) CH395F 芯片 + ────────── ───────────────── ──────────── + net_recv(fd, buf, len, timeout) + │ + ├─ 数据已在?── 是 ──→ 立即 SPI 读出 ────────────────────→ GET_REMV_LEN/READ + │ 通知调用方(结果 = 字节数) + │ + └─ 否,且 timeout>0 + │ + ├─ 登记 pending 到 s_net_pending[fd] ← 占用执行者到此结束(微秒级) + └─ 在自己上下文睡任务通知 ⟵──────────────┐ + │ + ┌────────────────┴─────────────────┐ + │ netTask 主循环(~1ms 节拍) │ + │ net_poll() ← 刷新 readable + │ net_pending_tick() ← 了结挂起 + │ net_relisten_retry_tick() │ + │ 排空消息队列 │ + └──────────────────────────────────┘ + │ + ┌──────────────────────────────────────────────────┘ + │ 五路完成/取消判定(每轮对每个挂起 fd) + │ ① 数据到达 → SPI 读出,通知调用方(结果 = 字节数) + │ ② 到点 deadline → 通知 NET_ERR_TIMEDOUT + │ ③ EOF/DISCONNECT → 按 0(EOF) 完成 + auto-relisten + 通知 + │ ④ 同 fd 后续操作 → 先行结算该 fd 的挂起,再执行新操作 + │ ⑤ 网络重建 → 取消 + **必须通知**(否则调用方永久挂死) + └─→ xTaskNotify → 唤醒调用方 +``` + +**关键性质**: + +- 等待期间 netTask **零额外占用**——`net_pending_tick` 只读标志与到期时间, + 数据到达判据 `readable` 由主循环既有的 `net_poll()` 每轮刷新,**不引入额外 SPI 事务**; +- 调用方**在自己的上下文睡眠**(任务通知),与 LwIP 的消费者线程模型同构; +- 公开 API 与调用契约**不变**——`net_recv` / `net_recv_to` 的签名、返回值、 + 超时语义均与改造前一致,既有调用方、测试与模拟器零改动。 + +--- + +## 3. 数据结构 + +### 3.1 挂起请求表 + +| 项 | 设计 | +|---|---| +| 存储 | **独立静态数组** `s_net_pending[NET_MAX_SOCKETS]`(不置于 `net_sock_t` 内) | +| 字段 | `active` / `buf` / `len` / `deadline` / `registered` / `caller` | +| 容量 | 每 fd **至多一个**挂起请求 | +| 占用 | ≈24B/fd × 8 fd = **192B**(+4B 任务句柄),实测 SRAM +200B | + +**为什么独立成表而不是塞进 `net_sock_t`**: + +`net_close_locked` 对 `net_sock_t` 做**整块 memset**。若挂起状态置于其中,`close` 会 +静默抹掉 pending——调用方永远等不到通知,**永久挂死**。独立表把"跨时间状态"与 +socket 生命周期解耦,与 `net_relisten_retry_tick` 的重试表同构。 + +### 3.2 登记守卫(两条硬防线) + +| 守卫 | 理由 | +|---|---| +| 每 fd 至多一个,**不覆盖** | 覆盖 = 丢掉首个调用方的通知 = 该调用方永久挂起 | +| `caller == NULL` 或 `caller == netTask` 时**拒绝**(返回 BUSY) | netTask 上下文自等待 = 无人能完成它 = 死锁;netTask 内必须用 DONTWAIT | + +--- + +## 4. 完成与取消语义(五路) + +`net_pending_tick()` 在主循环每轮运行,对每个挂起 fd 按序判定: + +| # | 条件 | 动作 | 设计要点 | +|---|---|---|---| +| 1 | **数据到达** | SPI 读出 + 通知(结果 = 字节数) | 由 `net_poll` 维护的 `readable` 门控,**零额外 SPI**;仅 ESTABLISHED / UDP_OPEN 态可读;spurious readable 需清除 | +| 2 | **到点** `now >= deadline` | 通知 `NET_ERR_TIMEDOUT`(对外 -2 映射保持) | 状态无关;用有符号回绕安全差值,防 tick 回绕 | +| 3 | **CLOSED**(EOF/DISCONNECT) | 排空:有数据则读出;否则按 0(EOF) 完成 + `auto_relisten` + 通知 | CLOSE 先行完成挂起 = `net_close` 的 settle 钩子(排空→数据否则 CONNRESET) | +| 4 | **同 fd 后续操作** | 先结算挂起,再执行新操作 | per-fd 串行——冻结面从"全网"缩到"本 fd" | +| 5 | **网络重建**(`net_stack_bring_up`,芯片复位) | **取消 + 必须通知** | `net_init` 顶部 `net_pending_cancel_all(CONNRESET)`,先于芯片复位;**取消不通知 = 调用方永久挂死** | + +**状态推断的克制**:CONNECTING / LISTENING 等中间态**保持等待**,**不做**状态推断式取消—— +CONNECT → ESTABLISHED 是合法迁移,推断取消会误杀正在建链的等待。 + +### 4.1 看门狗 + +到点后 1s 仍未了结 = 完成逻辑缺位 → **强制了结 + `DBG_ERROR`**。 +定位:防"挂起登记后永不完成"导致调用方无限期睡眠。 + +--- + +## 5. 调用方契约 + +调用方**不改协议、不改 API**,但需知悉三条: + +| 契约 | 说明 | +|---|---| +| `buf` 生命周期 | 挂起期间 `buf` 指针须**保持有效**至调用返回(挂起表按指针写入) | +| 剩余预算循环 | 调用方保留"总预算 − 已耗时"循环骨架(`n == -2` 续轮,预算耗尽退出)——这是**公开契约要求**(30s 总超时语义 + 跨 TCP 分段累积),与本架构无关 | +| 超时精度 | 完成判定随主循环节拍(~1ms);主循环被长操作占用时,超时**最多顺延**相应时长(已知代价,见 §7) | + +> **已退役形态**:改造前调用方需自行实现"5ms 分片 + `vTaskDelay(1)` 让出"协议。 +> 该协议已随本架构落地而删除——分片是"执行者被占"前提下的妥协,pending 模型下不再需要。 + +--- + +## 6. 性能特征(已验证) + +| 指标 | 值 | 条件 | +|---|---|---| +| 队列响应性(挂起连接下) | **92.5ms** | 挂起对时客户端 + FTP banner 探测 | +| 改造前同场景 | 28554ms | — | +| M3 静默档帧周期 | med 58.9 / p95 69.9 / max 72.1ms | 零尖峰 | +| M3 压力档帧周期 | med 60.1 / p95 66.4 / max 69.3ms | 零尖峰,p99 尾部 133.5→69.3ms | +| netTask 栈峰值 | 488B / 4096(余量 88%) | 零占用设计落点 | +| RAM / Flash 增量 | +200B / +608B | 相对改造前 | + +--- + +## 7. 设计边界与已知代价 + +| 项 | 现状 | 说明 | +|---|---|---| +| **SEND 路径未覆盖** | 发送仍为分块阻塞(1s/chunk stall) | 该期间队列仍被冻结;二期 pending 化解决 | +| **ACCEPT 路径未覆盖** | accept 仍用轮询计时 | 需 pending 化(二期) | +| **超时精度** | 随主循环节拍(~1ms),被长操作占用时顺延 | 一期文档化、不修;二期 SEND 化后该顺延面**收窄** | +| **看门狗未接自检** | 强结算 + `DBG_ERROR`,未写 selftest | 二期补齐 | +| **模拟器不可建模** | `net_socket_sim.c` 单线程 Winsock 无法复现挂起模型 | 该路径在模拟器上零覆盖,只能硬件验证 | + +**二期扩展设计**(ACCEPT / SEND 的挂起化、门禁清单、改动量)见 +`docs/审查记录/下一步任务规划.md` §3.1。 + +--- + +## 8. 设计铁律(为什么是这样) + +1. **执行者永不在等待中自旋**——等待必须在调用方上下文完成,netTask 只负责"登记"与"了结"。 +2. **取消必通知**——任何取消路径(close / 重建 / 陈旧重同步)都必须唤醒调用方, + 否则是永久挂死而非错误返回。 +3. **挂起状态与 socket 表解耦**——`net_sock_t` 会被整块 memset,跨时间状态不能寄居其中。 +4. **不做状态推断式取消**——中间态(CONNECTING/LISTENING)合法迁移存在, + 推断取消会误杀正常建链等待。 +5. **数据到达不引入额外 SPI**——判据复用主循环既有 `net_poll` 维护的 `readable` 标志。 + +--- + +## 附录 A:演进溯源 + +> 本架构由 E-02 缺陷修复演进而来(明细见 `错误码传播审计.md` E-02)。**以下为历史信息, +> 描述"如何演到这里",不作为当前设计依据。** + +**E-02 缺陷**:netTask 每次取一条消息处理到完成才取下一条;任一消费者发起的 30s 阻塞 +`net_recv` 期间队列整体停摆最长 30s(FTP 客户端空闲 >30s、对时客户端连上不发数据均可触发)。 + +**两代形态**: + +| 代次 | 形态 | 状态 | 提交 | +|---|---|---|---| +| 一代 | 分片有界等待:`net_recv_to` + 5ms 片 + 30s 预算 + 片间 `vTaskDelay(1)` 让出 | 已退役 | `f8d6e90` / `4a1605b` | +| 二代 | **pending 请求(本文档所述,现行)** | **一线现行** | `a45c0cb` | + +**实施与初始设计基线的偏差**(如实留档): + +| 基线条目 | 实施 | 说明 | +|---|---|---| +| pending 控制块 ≈20B/fd | ≈24B/fd × 8 = 192B | 实测 SRAM +200B,同量级 | +| 控制块置于 `net_sock_t` 内 | **独立静态数组** | 见 §3.1 理由 | +| 无数据 → 登记、跳过通知 | 哨兵 `NET_PENDING_REGISTERED`(0x70000000)→ `do_notify=0` | 逐字一致 | +| 调用方改单次 `net_recv_to(…, 30000)` | **保留剩余预算循环** | 公开契约要求(见 §5) | + +**验证门禁逐条实测**(2026-09-22,设备 192.168.1.100): + +| # | 门禁 | 结果 | +|---|---|---| +| 1 | CH395F NET 层套件 | **PASS**:F1 组合 Phase 6/9/11(64B/1460B 回显 11/11、select 回显 11/11、断开重连、KeepAlive + auto-relisten);F2 组合 Phase 8-RECV(100KB 阻塞接收 50/50 块 + CRC32 整包一致 0x9A0E0C8C)。Phase 7/10 未跑(DONTWAIT 路径另由 M3 探针族 L5~L7 覆盖)。TC-NET-604 FAIL = 既有芯片侧问题(Trap 21,2026-09-23 结案非缺陷) | +| 2 | M3 基线重锁 | **PASS**:见 §6 | +| 3 | e02_probe A/B | **PASS 且优于分片方案**:队列响应性 92.5ms;30s 截止按节拍精确触发(30.1s);监听恢复 6.6s | +| 4 | ftp_regression / E-06 假 425 | 随 F1/F2 + M3 压力档覆盖(FTP 半登录态即其场景) | +| 5 | UI 远端推流压力 | **PASS**:`:7003` 100Hz 全帧 CRC 50/50,零尖峰 | +| 6 | timeSync 三场景 | **PASS**:挂起 / 正常包;部分包由 Phase 8-RECV 跨段累积等效覆盖 | +| 7 | 产品 `@test` + 全片回读 | **PASS**:Required 全中 / Forbidden 零命中;回读 `No difference found` | +| 8 | RAM/栈前后对比 | **PASS**:见 §6 | + +**未执行 / 延后项**: + +- 未保留分片路径作影子对照 → 分片协议直接退役;对照由"旧镜像 A/B"承担,回退 = git revert + (单提交、API 不变); +- 探针族扩充(close/reconfig/EOF/disconnect-during-pending 专项)→ 二期; +- 看门狗接 selftest 留痕 → 二期; +- 模拟器差距 +1(`net_socket_sim.c` 无法建模挂起)→ 二期更新清单; +- 台架期间另发现一次 49s 全系统日志静默(defaultTask/NAND syslog 排空停滞,net 栈照常工作) + ——既有存储侧现象,与本层无关,见 `docs/待处理内容.md` N-2。 + +## 附录 B:修订记录 + +| 日期 | 内容 | +|---|---| +| 2026-09-22 | 一期落地并全量台架验证(原《Net 层阻塞模型业界对照与演进方案》实施记录) | +| 2026-09-26 | 调研文档退役,客观实施记录独立成文 | +| 2026-09-29 | **改写为架构设计文档**:以"当前如何设计/为何如此"为主线重组织;历史演进与门禁实测降级为附录 A;迁入 `docs/网络/` | diff --git a/docs/问题记录/Net层阻塞模型改造实施记录.md b/docs/问题记录/Net层阻塞模型改造实施记录.md deleted file mode 100644 index 3043181f..00000000 --- a/docs/问题记录/Net层阻塞模型改造实施记录.md +++ /dev/null @@ -1,97 +0,0 @@ -# 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`。 diff --git a/docs/问题记录/错误码传播审计.md b/docs/问题记录/错误码传播审计.md index 99d6b064..b94cce35 100644 --- a/docs/问题记录/错误码传播审计.md +++ b/docs/问题记录/错误码传播审计.md @@ -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`(已固化铁律) ---