refactor(NET): 源码注释去阶段化 + 网络两份文档重构 + 不稳根因图更新

- 源码注释:删去自愈收敛阶段
1/1.5/3等 scaffolding 称谓,改为语义引用
  (E-02 收口 / F-NET-2/3/4 / docs/网络/网络自愈架构设计.md §5.2 E13);
  涉及 net_socket/.h、net_events、net_listener、net_pending、net_types、
  net_config、ch395f、time_sync、iec104_serv、ui_net_sink、lftpd、
  simulator/sim/net_socket_sim、board/host 测试与探针
- 文档重构:网络自愈架构设计.md 与 Net层阻塞模型架构设计.md 改为现状口径
  (删历史节与阶段叙事),NET/README.md、docs/README.md 同步
- 工具与配图:gen_net_instability_svg.py 与
  docs/images/网络不稳根因总览.svg 随源码口径一并更新
- 门禁:@build 0 错误 0 警告
This commit is contained in:
2026-10-14 22:05:53 +08:00
parent cea2b51efb
commit d770e36c7c
30 changed files with 574 additions and 682 deletions
+39 -39
View File
@@ -45,7 +45,7 @@
* 假设=「RX 非空但 readable=0」(RECV_OK 事件未收到的数据面形态)在生产真实
* 发生。置 1 烧实验固件:net_poll 每 32 轮对在用 fd 发一条 GET_RECV_LEN,
* 命中计数 + 低频日志(每小时 ≤1 条防刷屏);跑 24h 常态 + E1 压测。
* 判据:命中 >0 → 阶段 3 项 4(U15 内化)立项;=0(含压测)→ 上层 32 轮
* 判据:命中 >0 → U15(数据面失配)内化立项;=0(含压测)→ 上层 32 轮
* 盲收保留现状、U15 登记观察项。**默认 0 = 产品构建零成本(编译剔除)**。
* E6 已裁决(2026-10-13,《网络自愈架构设计》§5.2 E6):命中=0(含压测)→ 项 4 不立项,维持默认 0。
* ⚠ 必须定义在文件最前部:bring_up 的 armed 日志与 net_poll 探测环两处消费。 */
@@ -240,7 +240,7 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
/* 复位芯片 */
ch395f_reset();
/* 芯片版本留痕 + 0-6 版本门控(自愈收敛阶段0,§5.52 表):bit3 SOCKET_CLOSE
/* 芯片版本留痕 + 版本门控(CH395F 手册 §5.52 表):bit3 SOCKET_CLOSE
* 需芯片 ≥0x46、TCP_SERVER 需 ≥0x44。本台架芯片实测 ≥0x46(TRAP-NET-20 定案
* SOCKET_CLOSE 实际生效);门控防批次漂移——版本不足则**拒置 bit3**
* (退回芯片自动关断语义)并 [ERR] 留痕,不静默带病运行 */
@@ -414,7 +414,7 @@ int net_poll(void) {
/* 读取全局中断状态(2 字节):读操作本身会清除 CH395F 中断并使其拉高 INT#,
* 若此后仍有新中断,CH395F 会再次拉低 INT#,由下一次 net_poll() 处理 */
int_status = ch395f_get_glob_int_status_all();
/* 自愈收敛阶段 3(F-DRV-13 接线):把全局位喂驱动——bit2 PHY_CHANGE 时驱动
/* F-DRV-13 接线:把全局位喂驱动——bit2 PHY_CHANGE 时驱动
* 重读 PHY 更新 link_up 缓存 + 变化计数,net 层在 reconciler 订阅留痕
* (运行期拔网线不再静默;不自动重配,重配仍走 UI/配置引擎路径) */
ch395f_glob_event_feed(int_status);
@@ -496,7 +496,7 @@ int net_poll(void) {
/* 因此每次 net_poll() 只处理“一批”,剩余数据在后续轮询中读取 */
} while (0);
/* 自愈收敛阶段 3(§5 项 1 基础):每轮全量刷新在用 Socket 的驱动状态缓存
/* 单一事实源(I1):每轮全量刷新在用 Socket 的驱动状态缓存
* (唯一刷新点;E2 实测单次回读 18.1us,在用 5~6 个 ≈100us ≪ 1ms 轮询
* 周期)。reconciler / 探针 / 镜像降级决策点一律读缓存(
* ch395f_sock_state_cached),不再各自发状态 SPI。放在中断处理之后:
@@ -504,7 +504,7 @@ int net_poll(void) {
for (int i = 0; i < NET_MAX_SOCKETS; i++) {
if (s_net_socks[i].in_use != 0U) {
(void)ch395f_get_sock_state((uint8_t)i);
/* 自愈收敛阶段 3(E-02 收口):驱动 sock_reset 状态机在 net_poll 步进
/* E-02 收口:驱动 sock_reset 状态机在 net_poll 步进
* (驱动头注释契约"在 net_poll 或测试循环里周期调用")。IDLE 槽位
* 纯 RAM 判返回 0 无 SPI;仅活跃复位机做短 SPI。作用:同步包装
* (net_sock_reset_sync)600ms 放弃后复位机不搁浅,芯片条件满足
@@ -572,7 +572,7 @@ int net_poll(void) {
* 30ms 节奏 / 2s 预算;门集与"芯片在听就不 open"(U12 防护)都在这一处
* 3. net_pending_tick:按节拍结束挂起 recv(数据/到点[仅显式预算]/断连)
* 4. net_send_pending_tick:按节拍推进挂起 send(断连/推进/写完/无进展超时)
* 5. net_reconcile_tick(TRAP-NET-17 + pump 合并,自愈收敛阶段 3):100ms 对账
* 5. net_reconcile_tick(TRAP-NET-17 事件面自愈 + 监听重建合一):100ms 对账
* ①②⑤ + ③④ 重建 + U11 重同步,判据读驱动状态缓存;去抖分级 + 1s 冷却
* 6. net_msg_t 按值入队 → 结果只能搭任务通知值回传(32 位整体即结果,不做位域压缩)
* 7. RECV / SEND 特例:超预算登记 pending 哨兵 NET_PENDING_REGISTERED(0x70000000),
@@ -593,7 +593,7 @@ void net_process_messages(void) {
net_pending_tick(s_net_socks);
/* 挂起 send 推进与完成检查(SEND pending):断连 / 推进写块 / 写完 / 无进展超时 */
net_send_pending_tick(s_net_socks);
/* TRAP-NET-17 状态对账 + 监听器 pump(自愈收敛阶段 3 合并单一 100ms tick):
/* TRAP-NET-17 状态对账 + 监听重建合一(单一 100ms tick):
* 判据读驱动缓存(net_poll 每轮全量刷新),①②⑤ 失同步 + ③④ 重建 +
* U11 重同步全部在此(本层唯一周期重建入口,N-32 P2 单一所有者) */
net_reconcile_tick();
@@ -690,7 +690,7 @@ void net_process_messages(void) {
break;
}
case NET_MSG_DROP_CONN: {
/* 自愈收敛阶段 3(E-02 收口):应用放弃会话的主动拆除(拆连接、保监听) */
/* E-02 收口:应用放弃会话的主动拆除(拆连接、保监听) */
net_sock_t *p_sock = net_get_sock(msg.sockfd);
if (p_sock == NULL) {
/* 描述符无效 → BADF */
@@ -709,7 +709,7 @@ void net_process_messages(void) {
}
break;
}
/* 自愈收敛阶段1(F-NET-3):NET_MSG_RESYNC_LISTEN / NET_MSG_RELISTEN 两个
/* F-NET-3:NET_MSG_RESYNC_LISTEN / NET_MSG_RELISTEN 两个
* 手动自愈消息已删——RESYNC 语义并入对账⑤(net_reconcile_tick),
* RELISTEN 与 reconciler/D10 完全重叠且对健康监听器是 footgun;
* 生产调用者本就为零(仅 test/board Phase 13,已改由自动机制接管) */
@@ -833,7 +833,7 @@ int net_socket(int domain, int type) {
p_sock->send_ready = 1;
/* 无可读数据 */
p_sock->readable = 0;
/* 自愈收敛阶段 1.5:阻塞模式默认 = 阻塞(BSD/Python 语义;非阻塞用
/* 阻塞模式默认 = 阻塞(BSD/Python 语义;非阻塞用
* net_setblocking(fd, 0) 显式设置)。close 的 memset 会清零本字段,
* 新 fd 必须在此显式置 1(同 released_abnormal 的"不得继承"纪律) */
p_sock->blocking = 1;
@@ -962,7 +962,7 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
}
/*
* 函数功能:驱动 sock_reset 原语的有界确定性排渣等待(P2b 收口,自愈收敛阶段 3;
* 函数功能:驱动 sock_reset 原语的有界确定性排渣等待(排渣收口;
* 替代原"close + 盲等 500ms"式忙等)
* 入口参数:sockfd - Socket 描述符 (0~7) int
* mode - CH395F_RESET_GRACEFUL(等 100ms)/ QUARANTINE(等 400ms)
@@ -1038,7 +1038,7 @@ int net_listen_locked(int sockfd) {
ch395f_set_sour_port(sockfd, p_sock->local_port);
/* CH395F 关闭 Socket 后需延时才能重新打开(TRAP-NET-09),故失败重试最多 3 次。
* P2b 收口(自愈收敛阶段 3):原"close + 盲等 500ms"改**确定性排渣**——
* 排渣收口:原"close + 盲等 500ms"改**确定性排渣**——
* sock_reset(读空 RX -> CLOSE -> 排空事件 -> 等 byte0=00H,内置 LISTEN
* 态二段 CLOSE 补发;E4 定案 60 轮实证复位后 open 必成)。GRACEFUL
* 最短等 100ms ≪ 原 500ms 盲等;复位失败/超时仍走下一轮重试,TRAP-NET-09 语义保留 */
@@ -1084,7 +1084,7 @@ int net_listen_locked(int sockfd) {
status = ch395f_tcp_listen(sockfd);
/* LISTEN 失败 → BUSY */
if (status != CH395F_ERR_SUCCESS) {
/* 0-3(自愈收敛阶段0,U12 对称):open 已成而 LISTEN 失败必须 close,
/* U12 对称:open 已成而 LISTEN 失败必须 close,
* 否则芯片 Socket 卡"OPEN 无监听"、后续 open 恒返 USE(同
* net_relisten_locked 对应分支) */
ch395f_close_socket(sockfd);
@@ -1326,7 +1326,7 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
return msg.result;
}
/* 自愈收敛阶段1(F-NET-4):net_can_accept 已删除——它只认 ESTABLISHED,作为 accept
/* F-NET-4:net_can_accept 已删除——它只认 ESTABLISHED,作为 accept
* 门控会把"监听器在服役但本轮还没 CONNECT"的窗口全挡掉(:2404 CONNECT 事件补 accept 探针
* 因此从不运行,与已修的 :7003 探针失效同型);唯一生产调用者 iec104 已迁
* net_listener_armed。net_can_read(RECV 门控)不受影响、保留。 */
@@ -1338,11 +1338,11 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
* 返回值:1 - 就绪(LISTENING,或 CLOSED + auto_relisten = 断连待重建态);
* 0 - 未就绪(fd 未分配 / 非监听型 / 正处隔离期以外的不就绪态) int
* 限定条件:任意任务上下文;net_init() 已调用
* 函数说明:1. N-32(P1 不变量 II):取代已退役的 net_can_accept()(要求
* ESTABLISHED,自愈收敛阶段1 删除)作为监听 accept 门控。原门控下
* 函数说明:1. 不变量 II(单一重建所有者):取代已退役的 net_can_accept()(只认
* ESTABLISHED,F-NET-4 删除)作为监听 accept 门控。原门控下
* :7003 永不进 net_accept →
* net_lost_connect_probe(CONNECT 事件未收到补 accept)对该端口从不运行
* (设计文档 §2.3 末"探针失效")
* (F-NET-4)
* 2. 为什么放行 LISTENING:探针与"closed-but-readable 接受"(:1338)
* 只在 net_accept_locked 内部发生,门控挡在外面就永远到不了;
* LISTENING 态 accept 由探测补 accept 或返 WOULDBLOCK,均安全
@@ -1364,7 +1364,7 @@ int net_listener_armed(int sockfd) {
/* 连接已到、应用尚未 accept:单连接模型下 CONNECT 处理(net_poll 分派 /
* 探针补 accept / 对账② standalone accept)把监听 fd 转 ESTABLISHED,
* 这就是"待 accept"电平——**必须放行**(原 net_can_accept 唯一放行态;
* 自愈收敛阶段1 i104 台架实证:200ms 任务周期抢不过对账②的 ~400ms 去抖,
* i104 台架实证:200ms 任务周期抢不过对账②的 ~400ms 去抖,
* 对账②先转 ESTABLISHED → 不放行则应用永不 accept、会话整场饿死)。
* 无 RPC 风暴风险:此态下 accept 必返 fd,一次调用即离开本分支 */
if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
@@ -1380,7 +1380,7 @@ int net_listener_armed(int sockfd) {
* 仍能拿到该连接。
* ⚠ 无残留时必须返回 0 —— 否则调用方会在整个 CLOSED 窗口内每轮都发起
* net_accept(RPC:入队 + xTaskNotifyWait 回执**无上界**)→ 队列积压 →
* 调用方任务喂不上狗。2026-10-12 P2a 台架实测:删掉即时 relisten 后 CLOSED
* 调用方任务喂不上狗。台架实测:删掉即时登记重建后 CLOSED
* 窗口被拉长到 reconciler 周期 + 隔离期(~100ms),:21 0ms×50 期间出现 48 条
* `[WD] task stall`(mask=0x67/req=0x77,缺 bit4=UI)。
* 重建本身由 net_reconcile_tick 形态③④ 负责,调用方**无需**在此催促。
@@ -1501,7 +1501,7 @@ int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen) {
* 限定条件:net_init() 已调用;必须在 netTask 上下文中调用
* 函数说明:1. 校验控制块(in_use、TCP 类型、地址参数)并保存对端地址
* 2. 芯片侧 OPEN(失败重试 3 次,每次失败走 sock_reset 确定性排渣,
* 见 TRAP-NET-09 / P2b)+ 配置源/目的端口与目的 IP
* 见 TRAP-NET-09)+ 配置源/目的端口与目的 IP
* 3. 清本 Socket 残留中断状态(丢弃上一条连接遗留的 DISCONNECT)
* 4. 发起 TCP_CONNECT(驱动内已轮询 CMD_STATUS)并置 CONNECTING;
* 命令级被拒立即关 Socket 返 -1,TCP 层成败仍由 CONNECT/TIMEOUT 裁定
@@ -1553,7 +1553,7 @@ static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int a
ch395f_set_proto_type(sockfd, CH395F_PROTO_TYPE_TCP);
/* CH395F 关闭 Socket 后需延时才能重新打开(TRAP-NET-09),故失败重试最多 3 次。
* P2b 收口(自愈收敛阶段 3):原"close + 盲等 500ms"改**确定性排渣**——
* 排渣收口:原"close + 盲等 500ms"改**确定性排渣**——
* sock_reset(读空 RX -> CLOSE -> 排空事件 -> 等 byte0=00H,内置 LISTEN
* 态二段 CLOSE 补发;E4 定案 60 轮实证复位后 open 必成)。GRACEFUL
* 最短等 100ms ≪ 原 500ms 盲等;复位失败/超时仍走下一轮重试,TRAP-NET-09 语义保留 */
@@ -1574,7 +1574,7 @@ static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int a
}
/* 清掉本 Socket 可能残留的中断状态,丢弃上一条连接遗留的 DISCONNECT。
* F-NET-7(自愈收敛阶段 3):只清**本 Socket** SINT(驱动护栏原语)——原
* F-NET-7:只清**本 Socket** SINT(驱动护栏原语)——原
* "再读清全局"会焊死其它在用 Socket 的事件位(全局寄存器唯一读者=net_poll) */
(void)ch395f_sock_events((uint8_t)sockfd);
@@ -1670,7 +1670,7 @@ static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int a
* netTask 最坏停滞由 1s 压到 NET_SEND_SPIN_MS。
* ⚠ 仅**写块前**的等待可挂起:末块写完后 sent == len,此时超预算必须
* 直接返回 sent 而非登记(登记函数按 sent >= len 拒收,会把完整发送
* 报成 -1;2026-10-14 台架实证,详见《Net层阻塞模型架构设计.md》 §9.1)
* 报成 -1;详见《Net层阻塞模型架构设计.md》 §5.5 末块边界)
* 4. 发送中途断连(状态非 ESTABLISHED)→ 立即失败并返回已发字节
* (errno=CONNRESET,不再空等超时)
* 5. 未写完即返回(含挂起完成)均为**短写**:调用方须按 ret != len 判定
@@ -1810,7 +1810,7 @@ static int net_send_locked(net_sock_t *p_sock, const void *buf, int len,
* buf - 接收缓冲区指针 void *
* len - 缓冲区大小 int > 0
* flags - 标志位,NET_MSG_DONTWAIT 表示非阻塞 int
* timeout_ms - 本次等待预算(0 = 无限等待,自愈收敛阶段 1.5 起无默认值)uint32_t
* timeout_ms - 本次等待预算(0 = 无限等待,无默认值)uint32_t
* caller - 调用方任务句柄(挂起请求的完成通知目标) TaskHandle_t
* 出口参数:buf - 填充接收到的数据
* 返回值:实际接收字节数(> 0);0 表示对端关闭;-1 表示出错/非阻塞无数据 int
@@ -1818,7 +1818,7 @@ static int net_send_locked(net_sock_t *p_sock, const void *buf, int len,
* 限定条件:p_sock 非空;netTask 上下文
* 函数说明:1. 数据已在(快速路径)→ 立即读出返回
* 2. 非阻塞(NET_MSG_DONTWAIT 单次覆盖 **或** socket blocking 属性为 0,
* 自愈收敛阶段 1.5 模式属性)无数据立即返回 -1(NET_ERR_WOULDBLOCK)
* 模式属性)无数据立即返回 -1(NET_ERR_WOULDBLOCK)
* 3. 无数据 + 阻塞等待 → 登记挂起请求(pending 化,E-02 结构演进)
* 4. netTask 零占用立即返回;完成条件(数据/到点[仅显式预算]/断连)由 net_pending_tick 按主循环节拍检查
* 5. 并通知 caller;关闭/网络重建/陈旧重同步由对应路径显式结束(取消必通知)
@@ -1835,7 +1835,7 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
}
/* 超时来源:只有调用方显式预算(net_recv_to);0 = 无限等待
* (自愈收敛阶段 1.5:NET_RECV_TIMEOUT_MS 30s 默认预算已删,API 不强加隐藏值) */
* (NET_RECV_TIMEOUT_MS 30s 默认预算已删,API 不强加隐藏值) */
uint32_t to_ms = timeout_ms;
/* 先轮询一次:刷新状态机与可读标志 */
@@ -1859,7 +1859,7 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
}
/* 非阻塞模式:NET_MSG_DONTWAIT 单次覆盖,或 socket 的 blocking 属性为 0
* (net_setblocking(fd, 0),自愈收敛阶段 1.5 模式挂控制块属性) */
* (net_setblocking(fd, 0),模式挂控制块属性) */
if ((flags & NET_MSG_DONTWAIT) || (p_sock->blocking == 0U)) {
/* 非阻塞且当前无数据:若连接已断开则视为 EOF(0) 并自动重监听,
* 否则返回 WOULDBLOCK(-1) 表示暂时无数据 */
@@ -1905,7 +1905,7 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
* 出口参数:无
* 返回值:0 - 关闭成功 int
* 限定条件:必须在 netTask 上下文中调用;p_sock 有效
* 函数说明:1. P2b 收口(自愈收敛阶段 3):原"close + 500ms 盲等排空循环"改
* 函数说明:1. 排渣收口:原"close + 500ms 盲等排空循环"改
* **确定性 sock_reset**(读空 RX -> CLOSE(幂等) -> 排空本 Socket
* 事件(quiescent) -> 等 byte0=00H,内置 LISTEN 态二段 CLOSE 补发
* ——E2 补充发现:一次 CLOSE 只拆监听 byte0 恒 05)
@@ -2077,7 +2077,7 @@ int net_send(int sockfd, const void *buf, int len, int flags) {
/*
* 函数功能:接收数据(线程安全版本,通过消息队列委托给 netTask;
* **默认无限阻塞**——自愈收敛阶段 1.5 语义主流化,30s 默认预算已删)
* **默认无限阻塞**,30s 默认预算已删)
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
* buf - 接收缓冲区指针 void *
* len - 缓冲区大小 int > 0
@@ -2121,7 +2121,7 @@ int net_recv(int sockfd, void *buf, int len, int flags) {
msg.len = len;
/* 标志:0=按 socket 阻塞属性,NET_MSG_DONTWAIT=单次非阻塞 */
msg.flags = flags;
/* 0 = 无限等待(自愈收敛阶段 1.5:无默认预算;显式预算走 net_recv_to) */
/* 0 = 无限等待(无默认预算;显式预算走 net_recv_to) */
msg.timeout_ms = 0U;
/* 调用方任务句柄(netTask 凭它回传回执) */
msg.caller = xTaskGetCurrentTaskHandle();
@@ -2147,7 +2147,7 @@ int net_recv(int sockfd, void *buf, int len, int flags) {
}
/*
* 函数功能:接收数据(非阻塞具名入口——自愈收敛阶段 1.5 把 NET_MSG_DONTWAIT 路径转正,
* 函数功能:接收数据(非阻塞具名入口——原 NET_MSG_DONTWAIT 路径转正,
* 对齐 BSD recv(MSG_DONTWAIT) / Python recv 非阻塞模式的"名如其义")
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
* buf - 接收缓冲区指针 void *
@@ -2167,7 +2167,7 @@ int net_recv_nb(int sockfd, void *buf, int len) {
/*
* 函数功能:接收数据(带调用方指定超时的阻塞版,用于分片有界读;
* 自愈收敛阶段 1.5 起为**显式预算**便捷入口,等价 Python settimeout,
* 为**显式预算**便捷入口,等价 Python settimeout,
* 不再有隐藏默认值)
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
* buf / len - 接收缓冲与容量 void * / int > 0
@@ -2199,7 +2199,7 @@ int net_recv_to(int sockfd, void *buf, int len, uint32_t timeout_ms) {
}
/* ---- 3. 分片长度检查:timeout_ms = 0 在 netTask 侧意味着"**无限等待**"
* (自愈收敛阶段 1.5 删除 30s 默认预算),恰与本接口"有界等待"的存在
* (已删除 30s 默认预算),恰与本接口"有界等待"的存在
* 理由相反,直接拒绝 ---- */
if (timeout_ms == 0U) {
/* 分片长度必须 > 0 */
@@ -2508,7 +2508,7 @@ int net_sendto(int sockfd, const void *buf, int len, int flags,
* 限定条件:Socket 已创建且为 UDP 类型(SOCK_DGRAM);net_init() 已调用;有数据可用
* 函数说明:1. 轮询检查芯片接收缓冲(net_poll + get_recv_len),有数据即返回
* 2. UDP 数据报前 8 字节为报文头(源端口+源 IP),据此填充 src_addr
* 3. 无数据时(自愈收敛阶段 1.5,与 net_recv 同构):DONTWAIT / 非阻塞属性
* 3. 无数据时(与 net_recv 同构):DONTWAIT / 非阻塞属性
* 立即返回 -1(WOULDBLOCK);阻塞模式**无限等待**(30s 默认预算已删;
* 本接口为轮询自旋实现且无生产调用者,受 IWDG 监控的任务勿用无限形态)
*/
@@ -2535,7 +2535,7 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
return NET_ERR_RETURN_1(NET_ERR_INVAL);
}
/* 轮询直到:有数据 / 非阻塞(自愈收敛阶段 1.5:阻塞 = 无限等待,无默认预算) */
/* 轮询直到:有数据 / 非阻塞(阻塞 = 无限等待,无默认预算) */
while (1) {
/* 轮询一次:更新状态机与可读标志 */
net_poll();
@@ -2588,13 +2588,13 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
}
/* 非阻塞模式:NET_MSG_DONTWAIT 单次覆盖,或 socket blocking 属性为 0
* (自愈收敛阶段 1.5,与 net_recv_locked 同判据):无数据立即返回 */
* (与 net_recv_locked 同判据):无数据立即返回 */
if ((flags & NET_MSG_DONTWAIT) || (p_sock->blocking == 0U)) {
/* 置 WOULDBLOCK */
return NET_ERR_RETURN_1(NET_ERR_WOULDBLOCK);
}
/* 阻塞模式:无数据继续轮询等待(自愈收敛阶段 1.5:无限等待,无默认预算——
/* 阻塞模式:无数据继续轮询等待(无限等待,无默认预算——
* 旧 NET_RECV_TIMEOUT_MS 30s 兜底已删;唤醒源 = 数据,与 net_recv 的
* 差异是本接口为自旋实现,勿在受 IWDG 监控任务中使用无限形态) */
}
@@ -2706,7 +2706,7 @@ int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg) {
}
/*
* 函数功能:设置 Socket 阻塞/非阻塞**模式属性**(自愈收敛阶段 1.5,模式挂控制块属性,
* 函数功能:设置 Socket 阻塞/非阻塞**模式属性**(模式挂控制块属性,
* 对齐 BSD O_NONBLOCK / Python setblocking)
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
* on - 1 = 阻塞(net_socket 默认);0 = 非阻塞 int
@@ -2784,7 +2784,7 @@ int net_sock_state(int sockfd) {
return (int)s_net_socks[sockfd].state;
}
/* 自愈收敛阶段1(F-NET-3):手动自愈 API net_resync_listen / net_relisten 已删除——
/* F-NET-3:手动自愈 API net_resync_listen / net_relisten 已删除——
* RESYNC 语义并入对账⑤(net_reconcile_tick 自动认领"芯片静默回收回 LISTEN"形态,
* 200ms×2 去抖 + 1s 冷却沿用);RELISTEN 与 reconciler/D10 完全重叠且对健康监听器是
* footgun(无条件 open→USE→close 自毁 ~1s,原注释自认)。生产调用者本就为零