E-02配套调研留档:Net层阻塞模型五类业界模式对照与pending演进方案利弊/改动量/验证门禁
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
# Net 层阻塞模型:业界对照与演进方案
|
||||
|
||||
> **模块名称**:Net 层(net_socket / netTask)阻塞等待模型
|
||||
> **文档目的**:E-02 修复(2026-09-22)的配套调研留档——(1) 本项目"分片有界等待"方案与主流开源/
|
||||
> 成熟项目模式的对照;(2) 演进方向"RECV 消息 → pending 请求"(正统事件驱动形态)的利弊与改动量估算。
|
||||
> **留作备用**:第二档 #1(E-02+E-06+E-20+E-21 阻塞模型改造)排期实施时,以 §6 为设计基线、
|
||||
> §6.5 为验证门禁。
|
||||
> **日期**:2026-09-22
|
||||
> **配套文档**:`错误码传播审计.md`(E-02 明细 / 修复计划 / 已闭环记录)、`docs/测试说明/链路延迟测试说明.md`
|
||||
> (M3 基线 / §8.3 实现要点 / §9 故障对照)、`AGENTS.md`(SPI 铁律 / 就绪屏障 / 内存预算)
|
||||
|
||||
---
|
||||
|
||||
## 1. 结论速览
|
||||
|
||||
1. **已落地的修复(分片有界等待)在本项目约束类里是标准做法,且有官方认可**——不是野路子,
|
||||
无需推翻;已经台架 A/B 实证(挂起对时客户端下 FTP banner 28554ms → 109ms/75ms)与
|
||||
M3 压力档复验(帧周期 17.7s 尖峰 → 零尖峰,med 65.0ms)。
|
||||
2. **业界最正统形态("执行者永不被占")在本项目不可达**——其前提是"数据到达可被执行者免费
|
||||
观察到"(LwIP:网卡 DMA/IRQ 递 pbuf → tcpip 线程 O(1) signal 消费者)。本项目的"数据到达"
|
||||
观察手段是一次 SPI 事务,而 SPI 总线由 netTask 独占(铁律)→ 等待只能在 netTask 内执行,
|
||||
自由度只剩"每次占多久"与"等待期间还做什么"。
|
||||
3. **演进方向 = pending 请求**(控制块登记 + 主循环节拍完成 + 取消必通知):消灭头阻塞缺陷类
|
||||
(不再依赖调用方纪律)、调用方从分片协议解放、成为 E-06/E-20/E-21 的公共地基。库内已有
|
||||
生产验证先例——D10 的 `net_relisten_retry_tick`(登记→到点完成→全程不阻塞,恢复 588ms→89ms)
|
||||
就是该模式的缩小版。
|
||||
4. **这是结构演进,不是紧急修复**:现状(分片)已验证、残余最坏可控(队列滞后 ≤5ms、发送
|
||||
stall ≤1s/分片,M3 基线已按此锁定)。实施时机 = 第二档 #1 排期窗口;路线 RECV 先行 →
|
||||
ACCEPT/SEND 跟进。代码改动不大(一期 ~200-400 行、公开 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,两提交 + 闭环留档):
|
||||
|
||||
| 提交 | 内容 |
|
||||
|---|---|
|
||||
| `f8d6e90` | lftpd 侧:新增 `net_recv_to` 接口(片长经 `msg.timeout_ms` 入队、片超时独立返回码 -2);`lftpd_inet_read_line`/`lftpd_inet_read` 改 5ms 分片 + 30s 总预算 + 片间 `vTaskDelay(1)` 让出;M3 压力档复验(17.7s 尖峰 → med 65.0ms/max 133.5ms/零尖峰) |
|
||||
| `4a1605b` | timeSync 侧:`time_sync_handle_conn` 同模式改造(5ms 片/30s 总预算/跨片累积容忍 TCP 分段/超时留痕 `time_sync: no TIME packet in 30s, drop conn`);产品构建 `@test` 闭环 PASS |
|
||||
| `3b28c56` | 审计闭环留档 + 专项回归探针 `test/e02_probe.py` |
|
||||
|
||||
**A/B 台架实证**(`test/e02_probe.py`,2026-09-22,设备 192.168.1.100):挂起对时客户端连 :8888
|
||||
不发数据,2s 后 PC 测 FTP(:21) banner 时延 = 队列响应性——旧固件 **28554ms**(设备日志实证芯片侧
|
||||
握手与 MCU 侧处理相隔 27s;旧代码 30s 后静默拆连零日志)vs 修复后 **109ms**(产品构建)/ **75ms**
|
||||
(测试构建)。30s 预算拆连与监听恢复行为两侧同构(~8s,2 次 Trap 09 重试)。
|
||||
|
||||
**当前架构**(netTask 主循环,`App/task/net_task.c`):
|
||||
|
||||
```
|
||||
for (;;) {
|
||||
[reconfig 检查 → net_stack_bring_up 重建]
|
||||
net_poll(); // 读芯片中断状态、分发事件、维护 readable 标志
|
||||
net_process_messages(); // ① net_relisten_retry_tick(D10:到点重试)
|
||||
// ② while(队列非空) 取一条消息处理到完成 → 通知调用方
|
||||
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 内执行,设计自由度 = ①每次占用时长(现状:分片封顶 5ms)
|
||||
②等待期间是否/如何做其他事(现状:仅片间隙排空队列)。pending 方案 = 把自由度 ② 用满。
|
||||
|
||||
---
|
||||
|
||||
## 5. 现状方案(分片有界等待)的正当性
|
||||
|
||||
1. **官方认可**:Node 文档把"分片 + 定期让出"(partitioning)列为不阻塞事件循环的**一等官方解法**
|
||||
(与 offload 并列;offload 在本项目不可行——SPI 独占)。5ms 片 + `vTaskDelay(1)` 让出即逐字
|
||||
对应。
|
||||
2. **生产级先例**:librdkafka 后台 I/O 线程 = 短超时 poll + 间隙排空队列,"有界执行者等待"
|
||||
在生产级客户端里被接受。
|
||||
3. **E 类标准实践**:offload 芯片驱动族的通行形态 = 非阻塞原语 + 调用方预算循环
|
||||
(`net_recv_to` + 5ms 片 + 30s 总预算与之同构)。
|
||||
4. **变体选择有据**:审计方向 ① 原文为 "DONTWAIT 分片 + 调用方重投",实际落地选**有界阻塞片**。
|
||||
理由:DONTWAIT 每片一次完整队列往返(入队+调度+取消息+通知,L5 实测 ~1.2ms),30s 等待 =
|
||||
~2.5 万次往返;有界片让 netTask 片内连续多次 `net_poll`,片内到达的数据当片即收。M3 实测
|
||||
支持:100ms 片受压帧 ~750ms → 5ms 片 ~10ms。
|
||||
5. **已知残余**(如实留档):
|
||||
- 队列最坏滞后一个片(5ms)+ 往返——pending 方案可压到 ~1ms(主循环节拍);
|
||||
- SEND 的 1s/分片 stall 仍冻结队列(审计 E-02 位置明列)——pending 方案二期覆盖;
|
||||
- **依赖调用方纪律**:新消费者若随手调 `net_recv(fd, buf, len, 0)`(默认 30s、无分片)即复发
|
||||
头阻塞——pending 方案结构性免疫。
|
||||
|
||||
---
|
||||
|
||||
## 6. 演进方案:RECV 消息 → pending 请求
|
||||
|
||||
### 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/e02_probe.py` A/B 回归(队列响应性应优于 5ms 片方案);
|
||||
4. `test/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 故障对照表)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 结论与实施建议
|
||||
|
||||
1. **现状(分片)安全有效,不必急着演进**——残余风险可控且已基线锁定;pending 是结构演进,
|
||||
不是缺陷修复,无时间压力。
|
||||
2. **实施时机 = 第二档 #1 排期窗口**:E-06/E-20/E-21 迟早要做,pending 是四条的公共地基,
|
||||
一次做齐比四个独立补丁便宜。
|
||||
3. **路线**:一期 RECV(影子验证)→ 二期 ACCEPT → SEND(最复杂:多分片/短发送/L3 探针钩子)。
|
||||
4. **启动动作**:以 §6.1 为设计基线评审 → 按 §6.5 门禁执行 → 完成后按 E-01/E-31/E-32/E-02
|
||||
的留档惯例更新 `错误码传播审计.md`(明细"已修复"+ 页脚闭环注记 + 提交记录)。
|
||||
|
||||
**一句话**:好处 = 缺陷类消灭 + 调用方解放 + E-06/20/21 共用机制;坏处 = 执行器状态机复杂化
|
||||
+ 天量级台架验证;改动本身不大(一期数百行、API 不变),大的是验证。
|
||||
|
||||
---
|
||||
|
||||
## 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 铁律 | 本项目约束与已验证基线 |
|
||||
@@ -11,7 +11,8 @@
|
||||
> + 父审计组(net 核心/事件标志/UI/启动路径)交叉覆盖,**全部关键发现经父审计组逐行代码复核**(含芯片手册
|
||||
> 原文核对)后才入册。
|
||||
> **配套文档**:`docs/项目审计改进清单.md`(交叉引用见 §6)、`docs/问题记录/*_Trap_Records.md`(模块陷阱史)、
|
||||
> `docs/网络配置说明.md`、`AGENTS.md`(09-21 教训已固化条目)。
|
||||
> `docs/网络配置说明.md`、`AGENTS.md`(09-21 教训已固化条目)、`docs/问题记录/Net层阻塞模型业界对照与演进方案.md`
|
||||
> (E-02 配套:业界模式对照 + pending 请求演进方案利弊/改动量,第二档 #1 排期时用)。
|
||||
|
||||
---
|
||||
|
||||
@@ -398,7 +399,7 @@ E-60"write_enable WRTC2 与手册矛盾"经三方复核(手册表头 D7~D0 顺
|
||||
|
||||
| # | 项 | 内容 |
|
||||
|---|---|---|
|
||||
| 1 | **E-02+E-06+E-20+E-21** | 阻塞模型改造:lftpd 控制通道/timeSync 改 `DONTWAIT` + 调用方状态机(ui_sink 模式推广);`net_process_messages` 长阻塞间隙按 tick 继续排空队列;`accept_timeout` 墙钟计时 + 去跨任务 state 直读。**E-02 部分已闭环(2026-09-22,f8d6e90+4a1605b)**:两触发源改 `net_recv_to` 分片有界读(落地方案 = 有界阻塞片,非 DONTWAIT 重投),台架 A/B 实证;E-06/E-20/E-21 部分仍待办 |
|
||||
| 1 | **E-02+E-06+E-20+E-21** | 阻塞模型改造:lftpd 控制通道/timeSync 改 `DONTWAIT` + 调用方状态机(ui_sink 模式推广);`net_process_messages` 长阻塞间隙按 tick 继续排空队列;`accept_timeout` 墙钟计时 + 去跨任务 state 直读。**E-02 部分已闭环(2026-09-22,f8d6e90+4a1605b)**:两触发源改 `net_recv_to` 分片有界读(落地方案 = 有界阻塞片,非 DONTWAIT 重投),台架 A/B 实证;E-06/E-20/E-21 部分仍待办(候选公共地基 = pending 请求机制,利弊/改动量/验证门禁见 `docs/问题记录/Net层阻塞模型业界对照与演进方案.md` §6) |
|
||||
| 2 | **E-05** | `net_socket/net_bind/net_getsockname` 并入队列(新消息类型);过渡方案:alloc+init 临界区 + `s_dynamic_port` 收归 netTask |
|
||||
| 3 | **E-10/E-42/E-53/E-54** | GD5F 驱动错误通道统一:init 重试 1~2 次;`wait_busy`/轮询路径 HAL 检查;ECC 使能回读校验;错误向上传递 |
|
||||
| 4 | **E-22** | lftpd/timeSync 向 ui_sink close 规则看齐(EOF 不 close、auto_relisten 常驻、仅代次变化/判死时重建) |
|
||||
|
||||
Reference in New Issue
Block a user