lwIP(Light weight IP)是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。LwIP是Light Weight (轻型)IP协议,有无操作系统的支持都可以运行。LwIP 的设计初衷是:用少量的资源消耗实现一个较为完整的 TCP/IP 协议栈,其中“完整”主要指的是 TCP 协议的完整性,实现的重点是在保持 TCP 协议主要功能的基础上减少对 RAM 的占用,它只需十几KB的RAM和40K左右的ROM就可以运行。这样就可以让lwIP适用于资源有限的小型平台例如嵌入式系统。
目前 lwIP 最新版本 2.1.3
官网:http://savannah.nongnu.org/projects/lwip/
点击“Group Homepage”查看LwIP的官方说明文档。
点击“Download Area”下载LwIP的资源。
contrib 包不属于 LwIP 内核的一部分,装的是移植和应用 LwIP 的一些 demo,即应用示例。
“.sig”后缀的文件是数字签名。
下载并解压,目录结构如下:
src/ - lwIP TCP/IP 协议栈 源码.
doc/ - lwIP 文档.
test/ -测试 LwIP 内核性能的源码,将它们和 LwIP 源码加入到工程中
一起编译,调用它们提供的函数,可以获得许多与 LwIP 内核性能有关的指标(在实际使用时一般用不到!可直接删除)
lwip-2.1.3/src,打开 src 文件夹,如下图所示
api 文件夹里面装的是 NETCONN API 和 Socket API 相关的源文件,只有在操作系统的环境中,才能被编译。如果您使用低级 回调/raw API ,则不需要。
非线程安全的API,callback style,可实现最高性能和最小内存占用。程序执行由回调函数驱动,然后当与该应用程序相关的活动发生时,由 lwIP 核心调用。特定应用程序可以注册以通过回调函数通知诸如可用的传入数据,发送的传出数据,错误通知,轮询计时器到期,连接关闭等事件。应用程序可以提供回调函数以执行任何或所有的处理这些事件。每个回调都是从TCP/IP代码中调用的普通C函数。每个回调函数都作为参数传递当前的TCP或UDP连接状态。此外,为了能够保持程序特定状态,使用独立于 TCP/IP 状态的程序指定参数调用回调函数。Raw API(有时称为Native API)是一种事件驱动的API,旨在在没有实现零拷贝发送和接收的操作系统的情况下使用。核心堆栈还使用此API进行各种协议之间的交互。它是在没有操作系统的情况下运行lwIP时唯一可用的API.
apps 文件夹里面装的是应用程序的源文件,包括常见的应用程序,如 httpd、mqtt、tftp、sntp、snmp 等。
core 文件夹里面是TCP/IP协议栈核心:协议实现,内存和缓冲区管理以及低级Raw API。
ipv4 文件夹实现了 IPv4 协议规定的对数据包的各种操作。ipv4 文件夹中还包括一些并非属于 IP 协议,但会受 IP 协议影响的协议源文件,包括 DHCP、ARP、ICMP、IGMP。
ipv6 文件夹实现了 IPv6 协议规定的对数据包的各种操作。ipv6 文件夹中还包括一些并非属于 IP 协议,但会受 IP 协议影响的协议源文件,包括 DHCP、ARP、ICMP、IGMP。
altcp.c、altcp_alloc.c、altcp_tcp.c 等文件是应用程序分层 TCP 连接 API,从 TCPIP 线程使用,是一个抽象层,可以模拟应用程序的 tcp 回调 API,同时防止直接链接,这样,应用程序可以使用其他应用程序层协议在 TCP 之上而不知道细节(例如 TLS,代理连接),此类接口我们并没有怎么使用,或者如果选择使用安全的加密传输的话,可以配合 mbed TLS 使用。
def.c 文件定义了一些基础类函数,比如主机序和网络序的转换、字符串的查找和比较、整数转换成字符串等,这些函数会被 LwIP 内核的很多模块所调用。在 include 目录里面的def.h 文件对外声明了 def.c 所实现的函数,同时定义了许多宏,能实现一些基础操作,比如取最大值、取最小值、计算数组长度等,这些宏同样也被内核的许多模块所调用。我们经常可以看到某个内核的源文件在开始的地方#include “def.h”。
dns.c 文件实现了域名解析的功能,有了它,用户就可以在知道服务器域名的情况下,获得该服务器的 IP 地址。很多时候我们只记得服务器域名而不记得服务器 IP 地址,例如“www.baidu.com”就是一个域名,通过 dns 功能,我们就可以得到与服务器域名对应的IP 地址,这给用户使用带来很大的方便。
inet_chksum.c 文件提供了 LwIP 所需的校验和功能,在 IP、UDP、TCP 协议的实现中,需要计算校验和。
init.c 文件对 LwIP 的用户宏配置进行了检查,会将配置错误和不合理的地方,通过编译器的#error 和#warning 功能表示出来。另外,init.c 定义了 lwip_init 初始化函数,这个函数会依次对 LwIP 的各个模块进行初始化。
ip.c 文件实现了 IP 协议相关的函数,但只是封装了 ipv4 和 ipv6 文件夹中的函数。
mem.c 文件实现了动态内存池管理机制,使得 LwIP 内核的各个模块可以灵活地申请和释放内存。
memp.c 文件实现了静态内存堆管理机制,使得 LwIP 内核的各个模块可以快速地申请和释放内存。
netif.c 文件实现了网卡的操作,比如注册/删除网卡、使能/禁能网卡、设置网卡 IP 地址等等。netif.c 与 include 目录中的 netif.h 文件共同构成了 LwIP 的 netif 模块,它对网卡进行了抽象,使得 LwIP 内核可以方便地管理多个特性各异的物理网卡。
pbuf.c 文件包含了协议栈内核使用的数据包管理函数,数据包pbuf管理的实现是整个协议栈中很有特色的地方,采用特殊的数据包pbuf 结构,可以避免数据在各个层次之间递交时的拷贝,这既提高了数据递交效率,也节省了内存空间。
raw.c 文件实现了一个传输层协议的框架,我们可以在它的基础上修改和添加代码,实现自定义的传输层协议,与 UDP/TCP 一样,它可以与 IP 层直接进行交互。这类似 RAWSocket。在实际的应用中,我们常用 UDP 和 TCP 作为传输层协议。但有时,底层网络开发人员会嫌 UDP 的可靠性太差,或者 TCP 虽然可靠性强,但是很耗费时间和内存,他们需要根据实际需求,平衡利弊,定义自己的传输层协议。LwIP 的 raw 模块可以满足他们的需求。
stat.c 文件实现了 LwIP 内核的统计功能,使用户可以实时地查看 LwIP 内核对网络数据包的处理情况。
sys.c 文件和 sys.h 文件构成了 LwIP 的 sys 模块,它提供了与临界区相关的操作。
tcp.c、tcp_in.c 和 tcp_out.c 文件实现了 TCP 协议,包括对 TCP 连接的操作、对 TCP 数据包的输入输出操作和 TCP 定时器,它们和 include 目录中名称带 tcp 的头文件共同构成了LwIP 的 TCP 模块。TCP 模块的实现是 LwIP 的最大特点,它以很小的资源开销几乎实现了TCP 协议中规定的全部内容。TCP 协议是非常复杂的协议,这几个与 TCP 模块相关的文件占据了 LwIP 内核的绝大部分。
timeouts.c 定义了 LwIP 内核的超时处理机制。LwIP 内核中多个模块的实现需要借助超时处理机制,包括 ARP 表项的时间统计、IP 分片报文的重装、TCP 的各种定时器、实现各种应用层协议需要的超时处理。
udp.c 文件包含了实现UDP 协议的相关函数,包括UDP 控制块管理、UDP 数据包发送函数、UDP 数据包接收函数等
include 文件夹里面是 LwIP 所有模块对应的头文件。
netif 文件夹里面是与网卡移植有关的文件,这些文件为我们移植网卡提供了模板,我们可以直接使用。
examples 目录里是一些 LwIP 的应用示例。在使用 LwIP 开发应用程序时会出现的典型问题,比如如何移植网卡、如何使用 LwIP 的 API、如何使用源码中提供的应用程序,对于这些问题,这个目录为我们提供了参考。