2024 年 12 月 24 日
FreeRTOS-Plus-TCP 的设计:第 1 部分——整体情况
本帖由 Nikhil Kamath 于 2024 年 12 月 24 日发布
多年来,FreeRTOS-Plus-TCP 一直是嵌入式系统中广受欢迎的 TCP/IP 协议栈。本系列博客将深入介绍 FreeRTOS-Plus-TCP (v4.x.x),将其架构和内部工作原理分解成易于理解的部分。虽然您可以在不了解这些细节的情况下启动并运行 FreeRTOS-Plus-TCP 应用程序,但了解协议栈如何与您的应用程序代码进行交互将提供宝贵的见解,尤其是在微调配置选项以提高性能或为特定需求定制行为时。本系列博客假设读者对网络概念有基本的了解。如果您需要复习这些概念或是新手,我们建议您查看我们的网络术语表:https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/networking_basics.html
打好基础
在深入探讨 TCP 握手和数据包传输的复杂细节之前,让我们先建立对基本构建单元的扎实理解。可以将 FreeRTOS-Plus-TCP 想象为一个组织严密的团队,每个成员都有其专门的职责:
IP 任务:
团队的领导者,负责协调所有网络活动。IP 任务运行 TCP/IP 协议栈。它:
- 处理网络事件: 处理来自网卡(NIC)驱动程序(如新数据包到达)和套接字 API(如应用程序要发送数据)的事件。
- 管理定时器: 跟踪各种协议的超时时间(例如,ARP 缓存条目、DHCP 租约续订、TCP 重传)。
- **处理套接字请求:**IP 任务接收应用程序任务通过套接字 API 发出的请求。它处理这些请求, 管理每个套接字的状态,分配和释放网络缓冲区,并确保线程安全操作。
套接字 API:
作为应用程序与 IP 任务之间的通信桥梁,它提供以下功能:
- 创建套接字: 建立用于发送和接收数据的通信端点。
- 发送和接收数据: 向其他设备传输数据或从其他设备接收数据。
- 建立和管理 TCP 连接: 连接服务器、监听传入连接以及接受客户端连接。
套接字 API 负责处理与 IP 任务交互的底层细节,使您能够专注于应用程序逻辑。
网络事件队列:
可以将其想象为 IP 任务办公室外的一条井然有序的队列。网络接口(特别是接收任务)和套接字 API 都使用这个队列向 IP 任务传递消息和请求。这样可以确保 IP 任务能够以结构化的方式逐一处理所有事件,避免多个任务同时使用网络时可能产生的冲突或混乱。
FreeRTOS-Plus-TCP 协议套件:
这是整个操作的核心,包含 TCP/IP 协议栈的核心模块。它包括负责以下功能的模块:
- ARP(地址解析协议): 类似于电话簿,将 IP 地址(逻辑地址)转换为 MAC 地址(物理地址)。
- **DHCP(动态主机配置协议):**自动从 DHCP 服务器获取 IP 配置(如设备的 IP 地址、子网掩码等)。
- ICMP(互联网控制消息协议): 管理错误消息以及著名的“ping”实用程序。
- UDP(用户数据报协议): 负责无连接的数据报通信,数据包无需建立正式连接即可发送。
- **TCP(传输控制协议):**可靠的面向连接通信的主力,采用了以下机制:
- 滑动窗口: 通过允许数据包无序到达并按正确顺序重新组装来提高效率。
- 重传: 通过重新发送丢失或损坏的数据包,确保数据可靠送达。
- 存活: 定期检查连接是否仍然有效。
- **DNS(域名系统):**将人类可读的域名(如 www.freertos.org
)转换为 IP 地址。
网络接口:
可以将其视为现场代理,直接与物理网络硬件(例如以太网控制器)交互。其任务包括:
- **网络接口驱动程序:**该软件组件充当 FreeRTOS-Plus-TCP 协议栈与实际硬件(以太网控制器)之间的翻译器。它负责处理以下任务:
- 发送和接收以太网帧:通过网络传输的原始数据包。
- 管理链路状态:跟踪网络电缆是否连接以及连接是否处于活动状态。
- 配置硬件功能:初始化和配置网络接口硬件,与 PHY 进行配置和协商,设置网络硬件的特定功能。
- **接收任务:**这个专用任务在后台默默工作,不断等待传入的网络流量:
- 处理网络中断:当数据包到达时,硬件会触发中断。该任务立即行动,将数据包数据抓取到网络缓冲区中,并将其推送到网络事件队列中,以便 IP 任务进一步处理。 此外,接收任务会分析接收到的数据包数据,以确定网络接口上最合适的端点与网络缓冲区关联。在硬件发出传输完成中断时,接收任务会释放已提交的网络缓冲区,将其返回到空闲缓冲区池中。
- 定期网络检查:如果在一定时间内没有发生中断,接收任务会执行检查,以确认网络链路是否仍然正常运行。它会相应地更新 FreeRTOS+TCP 的网络状态。
- 为 IP 任务准备数据:接收任务将数据整齐地打包到网络缓冲区(一种用于保存网络数据包的特殊容器)中,并添加重要的元数据。然后,它将此数据包发送给 IP 任务进行进一步处理。
网络缓冲区管理:
可以将其视为物流专家,负责高效地管理网络数据包的存储空间。它提供:
- 网络缓冲区池: 可以将这些缓冲区视为用于存储以太网帧的容器。
- **缓冲区分配和释放功能:**确保在需要时缓冲区随时可用,并在使用后进行回收。
任务优先级和线程安全:
FreeRTOS-Plus-TCP 专注于线程安全,这意味着它可以处理多个使用网络的任务,而不会出现混乱。网络事件队列是其中的关键部分,允许 IP 任务按顺序处理所有事项。
为了确保系统平稳运行,建议的任务优先级为: **最高优先级:**接收任务:此任务具有最高优先级,因为它直接响应硬件中断。它需要快速处理传入的数据包,以便网络接口为接收下一个数据包做好准备。 **中等优先级:**IP 任务:IP 任务也非常重要,但它处理更为复杂的操作,因此其优先级稍低。这允许接收任务在不受干扰的情况下执行其作业。 **最低优先级:**应用程序任务:使用套接字 API 发送和接收数据的应用程序任务以最低优先级运行。这样可以防止它们干扰高优先级任务处理的时间敏感网络操作。
数据包的旅程
假设您正在从 FreeRTOS-Plus-TCP 设备发送一条消息:
- 您的应用程序调用 FreeRTOS_send()(用于 TCP)或 FreeRTOS_sendto()(用于 UDP)来传输数据。
- 套接字 API 队列请求:套接字 API 打包请求,包括数据和目标信息,并通过网络事件队列将其发送给 IP 任务。对于 TCP,数据被添加到套接字的传输缓冲区。对于 UDP (没有零拷贝),数据被复制到网络缓冲区。使用 UDP 零拷贝时,缓冲区只需准备好发送即可。
- IP 任务接收到请求,检查目标地址,并可能使用 ARP 来解析 MAC 地址。
- 对于 TCP,IP 任务从缓冲区管理模块检索网络缓冲区,并用 TCP 流缓冲区中的数据填充该缓冲区。对于 UDP,直接通过套接字 API 获取网络缓冲区,并传递给 IP 任务,后者使用它进行进一步处理。
- IP 任务将数据和目标信息传递给相应的协议模块(TCP 或 UDP)。
- 协议模块准备数据以进行传输:
- TCP:如果数据超过最大段大小(MSS),则将其分成多个段。
- UDP:将数据视为单个数据报。
- 校验和计算:协议模块(TCP 或 UDP)向数据添加其标头。如果未启用校验和卸载,协议模块将计算并设置校验和。如果启用了卸载,NIC 驱动程序将处理校验和计算。
- IP 任务通过添加 IP 标头和协议数据(TCP 或 UDP 段/数据报)来准备网络缓冲区。
- 网络缓冲区被移交给 NIC 驱动程序,后者计算校验和(如果启用了)并将数据作为以太网帧发送。
接收过程与上述步骤相反,NIC 驱动程序将收到的帧传递给 IP 任务,后者解码数据并通过套接字 API 将其传递给应用程序。
接下来……
在下一篇文章中,我们将揭秘 IP 任务如何处理事件、管理定时器,并确保整个 FreeRTOS-Plus-TCP 协议栈平稳运行。敬请期待!
致谢
如果没有 AWS 同事们的支持,这篇博客就不可能完成。特别感谢 Actory Ou 和 Tony Josi,他们为图表编制提供了宝贵的帮助,并进行了详尽的审阅。