diff --git a/docs/子系统设计/网络Socket监听生命周期设计说明.md b/docs/子系统设计/网络Socket监听生命周期设计说明.md index 494f8f06..18f92d38 100644 --- a/docs/子系统设计/网络Socket监听生命周期设计说明.md +++ b/docs/子系统设计/网络Socket监听生命周期设计说明.md @@ -357,7 +357,7 @@ RAM 预算台账 `.md`,属另一在途任务)。这两个文件在主工作 --- -## 10. 监听生命周期模块化边界设计(重构方案,**未执行**) +## 10. 监听生命周期模块化边界设计(**已执行 2026-10-12**,提交 `c1ab902`) > **动机**:真机 net 层 `net_socket.c` 4126 行,而模拟器做同样的事只有 807 行(5 倍); > `relisten` 一词在文件里出现 110 次。用户诉求 = **高内聚低耦合**。 @@ -499,3 +499,49 @@ void net_listener_tick(void); 2. **再搬 7 个函数**,同步把 8 处外部引用改成 4 个窄接口; 3. **最后合并 tick**(`net_listener_tick` 内部调 retry + pump),`net_process_messages` 少一个调用点; 4. 每步独立提交、独立 `@build`;**第 3 步后**才跑完整台架矩阵(前两步是纯组织变更,可只跑 `@build` + `@test`)。 + +### 10.9 执行结果(2026-10-12,提交 `c1ab902`) + +**执行顺序调整(与 §10.8 的差异,据实记录)**:§10.8 的「先搬状态与常量」**单独做不可行**—— +状态数组被 `net_relisten_*` 函数直接读写,只搬状态不搬函数会**编译失败**。 +故第 1 步改为「**状态 + 常量 + 7 函数一次性纯搬移**」,第 3 步(合并 tick)**未做** +(收益仅少一个调用点,却会破坏「尺寸不变」这条硬判据,性价比不足)。 + +| 判据 | 结果 | +|---|---| +| `net_socket.c` 行数 | 4126 → **3656**(-471) | +| 新增模块 | `net_listener.c` / `net_listener.h`(真机专属) | +| **RW-data** | 980 → **980**(不变 ✓) | +| **ZI-data** | 143060 → **143060**(不变 ✓) | +| Code / RO-data | 197236 → 197228(-8)/ 17012 → 17000(-12) | +| 接口 | 8 处散点直调 + 2 处直接写数组 → **4 个窄接口** | +| `s_net_socks` 依赖 | **已消除**(改用 `net_get_sock` + `ch395_sock`) | +| 静态门禁 | 全绿(cppcheck / C 规范 / 双端注册 / 主机侧单测 12 套 / mem-numbers) | +| `@test` + 回读 | PASS + `No difference found` | +| 全量回归 | `:21` 0ms×50 与 100ms×50 各 **50/50**;`:8888` **20/20**;`:7003` **10/10**;`ftp_regression` **11/11**;Trap23 abort/graceful 各 **5/5** | +| 设备侧 `orphan listener` | **0**(保持 P2a 基线) | + +> **关于「尺寸完全不变」判据的修订**:实际执行发现该判据**过严** —— 接口改造 +> (fd 改传参、`net_set_errno` 提升可见性、新增 `net_pending_active`/`net_listener_settle`) +> **必然**改变代码生成。故修订为:**RW-data / ZI-data 必须完全不变**(数据总量不变), +> **Code / RO-data 允许极小变化**(本次各 -8 / -12 字节,相对 471 行搬移可忽略)。 + +**执行中暴露的三处「非纯搬移」(必要,均已注释留痕)**: + +1. **`net_set_errno` 由 `static` 提升为模块间可见** —— 它是 `static`,新模块链接期 + 报 `L6218E: Undefined symbol`;`NET_ERR_RETURN_1` 宏随之迁到 `net_socket.h` + (它依赖前者,不能只移宏)。 +2. **新增 `net_pending_active(fd)`** —— `net_listener_retry_tick` 原有「本 fd 有在途 + 挂起 recv 则跳过」(L3 保险,防重开 Socket 摧毁在途连接)直接读 `s_net_pending[i].active`; + 新模块不能碰该 static 数组,故加薄访问器。**语义原样保留**。 +3. **`net_listener.c` 必须真机专属** —— 它依赖 `ch395f_*` SPI 驱动,而 sim 是 Winsock + 后端(无 `ch395f_*`、无孤儿态、无重监听概念)→ **无法**在 sim 编译。故: + 只注册 Keil 端;并在 `scripts/check_registration.py` 的 `SIM_EXEMPT` **显式点名** + (该脚本既定的豁免原则正是「显式清单 + 每行理由,不整目录一刀切」,本例遵此)。 + +**教训(供后续搬移复用)**: +- 搬移前先查**跨边界引用面**(本次发现「状态数组外部写仅 2 处」),它直接决定接口面与风险; +- 「纯搬移可证」判据要选**对改造不敏感的量**(RW/ZI 数据总量),否则会被接口改造的 + 正常开销误报; +- 改完文件**必须重新 `git add`** —— pre-commit 校验的是**暂存区快照**,漏 add 会让 + 「本地已修好」与「提交时仍报错」自相矛盾(本次踩到,白跑两轮)。