驱动、bootloader、文件系统

嵌入式 Linux 系统工程 084:TCP、UDP 与 socket 缓冲

展开合集目录
  1. 嵌入式 Linux 系统工程 001:Linux 系统分层与资源地图
  2. 嵌入式 Linux 系统工程 002:主机、目标板与交叉开发
  3. 嵌入式 Linux 系统工程 003:架构、ABI、大小端与工具链
  4. 嵌入式 Linux 系统工程 004:Shell、管道、重定向与退出码
  5. 嵌入式 Linux 系统工程 005:BusyBox 与 GNU 工具差异
  6. 嵌入式 Linux 系统工程 006:目录结构与虚拟文件系统
  7. 嵌入式 Linux 系统工程 007:串口、SSH 与开发网络
  8. 嵌入式 Linux 系统工程 008:建立开发板信息与版本基线
  9. 嵌入式 Linux 系统工程 009:从 Boot ROM 到用户空间
  10. 嵌入式 Linux 系统工程 010:U-Boot 环境与内核启动参数
  11. 嵌入式 Linux 系统工程 011:内核配置、编译与模块
  12. 嵌入式 Linux 系统工程 012:设备树编译、加载与生效确认
  13. 嵌入式 Linux 系统工程 013:根文件系统与 initramfs
  14. 嵌入式 Linux 系统工程 014:BusyBox init、启动脚本与 systemd
  15. 嵌入式 Linux 系统工程 015:Buildroot 工程构建与定制
  16. 嵌入式 Linux 系统工程 016:Yocto 的 layer、recipe 与镜像
  17. 嵌入式 Linux 系统工程 017:读懂 procfs 的系统与进程信息
  18. 嵌入式 Linux 系统工程 018:sysfs:设备、属性与拓扑
  19. 嵌入式 Linux 系统工程 019:设备节点、设备号与动态管理
  20. 嵌入式 Linux 系统工程 020:debugfs、tracefs 与配置依赖
  21. 嵌入式 Linux 系统工程 021:内核日志、用户日志与时间线
  22. 嵌入式 Linux 系统工程 022:uptime、负载与基础状态
  23. 嵌入式 Linux 系统工程 023:系统快照与版本对照
  24. 嵌入式 Linux 系统工程 024:工具、权限和内核能力的辨别
  25. 嵌入式 Linux 系统工程 025:进程生命周期与状态
  26. 嵌入式 Linux 系统工程 026:线程、TID 与共享资源
  27. 嵌入式 Linux 系统工程 027:调度策略、nice 与实时优先级
  28. 嵌入式 Linux 系统工程 028:CPU 亲和性与多核
  29. 嵌入式 Linux 系统工程 029:上下文切换、抢占与唤醒延迟
  30. 嵌入式 Linux 系统工程 030:信号与有序退出
  31. 嵌入式 Linux 系统工程 031:僵尸进程与子进程回收
  32. 嵌入式 Linux 系统工程 032:高 CPU、低 CPU 卡顿与 D 状态
  33. 嵌入式 Linux 系统工程 033:虚拟地址、物理内存与映射
  34. 嵌入式 Linux 系统工程 034:栈、堆、malloc 与 mmap
  35. 嵌入式 Linux 系统工程 035:RSS、PSS 与共享内存统计
  36. 嵌入式 Linux 系统工程 036:页缓存、回收、swap 与内存压力
  37. 嵌入式 Linux 系统工程 037:slab 与内核内存
  38. 嵌入式 Linux 系统工程 038:CMA、保留内存与厂商缓冲池
  39. 嵌入式 Linux 系统工程 039:OOM、碎片与分配失败
  40. 嵌入式 Linux 系统工程 040:内存泄漏、越界与峰值
  41. 嵌入式 Linux 系统工程 041:文件描述符与打开文件状态
  42. 嵌入式 Linux 系统工程 042:权限、属主、umask 与链接
  43. 嵌入式 Linux 系统工程 043:VFS、挂载点与文件系统
  44. 嵌入式 Linux 系统工程 044:块设备、分区、eMMC 与 SD
  45. 嵌入式 Linux 系统工程 045:MTD、NOR、NAND、UBI 与 UBIFS
  46. 嵌入式 Linux 系统工程 046:SquashFS、OverlayFS 与只读系统
  47. 嵌入式 Linux 系统工程 047:缓冲写入、fsync 与掉电一致性
  48. 嵌入式 Linux 系统工程 048:空间满、inode 耗尽与 I/O 慢
  49. 嵌入式 Linux 系统工程 049:阻塞、非阻塞与短读写
  50. 嵌入式 Linux 系统工程 050:select、poll 与 epoll
  51. 嵌入式 Linux 系统工程 051:pipe、FIFO 与 Unix socket
  52. 嵌入式 Linux 系统工程 052:共享内存与消息队列
  53. 嵌入式 Linux 系统工程 053:mutex、条件变量与信号量
  54. 嵌入式 Linux 系统工程 054:原子操作、内存序与数据竞争
  55. 嵌入式 Linux 系统工程 055:eventfd、timerfd 与 signalfd
  56. 嵌入式 Linux 系统工程 056:死锁、优先级反转与队列背压
  57. 嵌入式 Linux 系统工程 057:device、driver、bus 与绑定
  58. 嵌入式 Linux 系统工程 058:platform、设备树与 probe
  59. 嵌入式 Linux 系统工程 059:模块、固件加载与版本匹配
  60. 嵌入式 Linux 系统工程 060:MMIO 与资源申请
  61. 嵌入式 Linux 系统工程 061:IRQ、软中断与工作队列
  62. 嵌入式 Linux 系统工程 062:GPIO、pinctrl 与有效电平
  63. 嵌入式 Linux 系统工程 063:clock、reset、regulator 与生命周期
  64. 嵌入式 Linux 系统工程 064:DMA、IOMMU 与缓存所有权
  65. 嵌入式 Linux 系统工程 065:UART、termios 与串口使用
  66. 嵌入式 Linux 系统工程 066:I²C 设备、事务与访问工具
  67. 嵌入式 Linux 系统工程 067:SPI、spidev 与传输
  68. 嵌入式 Linux 系统工程 068:GPIO 字符设备与事件
  69. 嵌入式 Linux 系统工程 069:PWM、定时器与控制输出
  70. 嵌入式 Linux 系统工程 070:ADC、传感器与 IIO
  71. 嵌入式 Linux 系统工程 071:input、按键与触摸事件
  72. 嵌入式 Linux 系统工程 072:CAN、SocketCAN 与错误状态
  73. 嵌入式 Linux 系统工程 073:USB 枚举、描述符与端点
  74. 嵌入式 Linux 系统工程 074:USB Host、Gadget 与 UVC
  75. 嵌入式 Linux 系统工程 075:PCIe 枚举、BAR、MSI 与 DMA
  76. 嵌入式 Linux 系统工程 076:V4L2 采集与缓冲队列
  77. 嵌入式 Linux 系统工程 077:Media Controller 与摄像头拓扑
  78. 嵌入式 Linux 系统工程 078:ALSA、PCM 与音频欠载
  79. 嵌入式 Linux 系统工程 079:DRM、KMS 与显示缓冲
  80. 嵌入式 Linux 系统工程 080:厂商视频 SDK 与 NPU 资源
  81. 嵌入式 Linux 系统工程 081:网卡、MAC、PHY 与链路状态
  82. 嵌入式 Linux 系统工程 082:IP、子网、路由与邻居表
  83. 嵌入式 Linux 系统工程 083:DHCP、DNS 与时间同步
  84. 嵌入式 Linux 系统工程 084:TCP、UDP 与 socket 缓冲
  85. 嵌入式 Linux 系统工程 085:ss、抓包与协议分析
  86. 嵌入式 Linux 系统工程 086:吞吐、重传、MTU 与延迟
  87. 嵌入式 Linux 系统工程 087:Wi-Fi、蜂窝模块与重连
  88. 嵌入式 Linux 系统工程 088:防火墙、转发、NAT 与隔离
  89. 嵌入式 Linux 系统工程 089:交叉编译、sysroot 与 pkg-config
  90. 嵌入式 Linux 系统工程 090:Make、CMake 与可重复构建
  91. 嵌入式 Linux 系统工程 091:ELF、库与动态加载器
  92. 嵌入式 Linux 系统工程 092:程序无法启动的分层排查
  93. 嵌入式 Linux 系统工程 093:配置、日志与错误处理
  94. 嵌入式 Linux 系统工程 094:服务管理、依赖与恢复
  95. 嵌入式 Linux 系统工程 095:capabilities 与设备访问
  96. 嵌入式 Linux 系统工程 096:软件包、升级与回退
  97. 嵌入式 Linux 系统工程 097:strace 定位系统调用问题
  98. 嵌入式 Linux 系统工程 098:GDB 与 gdbserver
  99. 嵌入式 Linux 系统工程 099:core dump、符号与回溯
  100. 嵌入式 Linux 系统工程 100:ASan、UBSan 与内存错误
  101. 嵌入式 Linux 系统工程 101:perf 与采样分析
  102. 嵌入式 Linux 系统工程 102:ftrace、tracepoints 与时序
  103. 嵌入式 Linux 系统工程 103:eBPF 的用途、条件与替代方案
  104. 嵌入式 Linux 系统工程 104:联合定位性能瓶颈
  105. 嵌入式 Linux 系统工程 105:Oops、panic 与内核调用栈
  106. 嵌入式 Linux 系统工程 106:hung task、soft lockup 与 hard lockup
  107. 嵌入式 Linux 系统工程 107:锁检查与内核调试配置
  108. 嵌入式 Linux 系统工程 108:PREEMPT_RT 与实时延迟
  109. 嵌入式 Linux 系统工程 109:时钟源、时间戳与对齐
  110. 嵌入式 Linux 系统工程 110:频率、温度与降频
  111. 嵌入式 Linux 系统工程 111:suspend、runtime PM 与唤醒
  112. 嵌入式 Linux 系统工程 112:watchdog、pstore 与故障现场
  113. 嵌入式 Linux 系统工程 113:cgroups、限制与资源压力
  114. 嵌入式 Linux 系统工程 114:namespaces、容器与设备访问
  115. 嵌入式 Linux 系统工程 115:案例:启动和根文件系统失败
  116. 嵌入式 Linux 系统工程 116:案例:摄像头无图、花屏与丢帧
  117. 嵌入式 Linux 系统工程 117:案例:NPU 变慢与缓冲分配失败
  118. 嵌入式 Linux 系统工程 118:案例:网络视频卡顿与帧龄
  119. 嵌入式 Linux 系统工程 119:案例:长期运行的内存与句柄增长
  120. 嵌入式 Linux 系统工程 120:整机验收与故障报告
嵌入式 Linux 系统工程 084:TCP、UDP 与 socket 缓冲的封面

第 84 / 120 课 · 网络配置与排障。返回课程合集。

机制与资源关系

TCP 提供有序字节流,应用仍需消息边界和超时协议;UDP 保留数据报边界但不保证送达。send 成功通常表示本地接受数据,不证明远端应用处理完成。缓冲大小不能补足长期吞吐缺口。

TCP、UDP 与 socket 缓冲的观察路径

实际用法与观察入口

以下是操作说明;先确认执行环境、工具帮助和目标对象。设备名、PID、地址及项目名示例需要按实际替换,不能将整段命令当通用板端脚本执行。

cat /proc/net/sockstat
cat /proc/net/snmp
ss -s

输出解读与排查顺序

区分连接建立、发送排队、网络传输和业务确认。接收端处理慢可能压缩 TCP 窗口;UDP 则可能出现本地队列丢弃。统计需按窗口和连接关联。

情境推演

发送 100 字节后对端分 40、60 两次收到属于正常 TCP 行为。接收器应按协议重组;对端完成业务后返回应用 ACK 才能证明已处理,而非只依赖 send 返回。

练习与参考分析

设计长度前缀协议并考虑分两次收到头部。参考结论:一次 recv 不保证得到完整业务帧,必须保存解析状态并限制声明长度。

独立实验包

主机内存中的拆包练习;不建立 TCP 连接,不模拟重传或拥塞。 默认入口、源文件和实际运行记录都在下载包中。

实验:TCP、UDP 与 socket 缓冲

查看完整代码:main.c
#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#define CHECK(x) do { if (!(x)) { fprintf(stderr, "check failed: %s at line %d (errno=%d)\n", #x, __LINE__, errno); exit(EXIT_FAILURE); } } while (0)

/* A deliberately fragmented stream: length prefix (big endian) plus body. */
int main(void) {
    const unsigned char wire[]={0,0,0,5,'h','e','l','l','o'};
    unsigned char received[sizeof(wire)]={0};
    const size_t fragments[]={2,3,1,3}; size_t offset=0;
    for (size_t i=0;i<sizeof(fragments)/sizeof(fragments[0]);++i) {
        CHECK(offset+fragments[i] <= sizeof(received));
        memcpy(received+offset,wire+offset,fragments[i]); offset+=fragments[i];
        if (offset < 4) continue;
        uint32_t length=((uint32_t)received[0]<<24)|((uint32_t)received[1]<<16)|
                        ((uint32_t)received[2]<<8)|received[3];
        CHECK(length <= sizeof(received)-4);
        if (offset < 4+length) continue;
        CHECK(length == 5 && memcmp(received+4,"hello",5) == 0);
    }
    CHECK(offset == sizeof(wire));
    puts("2/3/1/3-byte fragments reconstructed one bounded hello frame");
    return 0;
}
下载代码

在项目根目录执行;下载包解压后,在解压目录执行 sh run.sh。

cd 'content/posts/驱动、bootloader、文件系统/嵌入式Linux系统工程/084-TCP、UDP 与 socket 缓冲/code' && sh run.sh

官方资料与版本边界

内核、工具和厂商 BSP 的支持范围需分别核对。参考资料可能对应较新版本;不要据此推定旧 BSP 支持所有接口。

上一课:DHCP、DNS 与时间同步 · 下一课:ss、抓包与协议分析