按照上一小节的介绍,我们下载两个包:lwip-2.1.2.zip(源码包)和contrib-2.1.0.zip(contrib包)。解压以后会得到两个文件夹,如图 2‑4所示。
![](https://box.kancloud.cn/07ed0d7a854552f7796a1012758e3b1d_452x62.png)
我们先打开“lwip-2.1.2”文件夹,如图 2‑5所示。
![](https://box.kancloud.cn/21194576086c5ca8b79e98074158723c_609x256.png)
该目录的内容为:
* (1)CHANGELOG文件记录了LwIP在版本升级过程中源代码发生的变化。
* (2)COPYING文件记录了LwIP这个开源软件的license。一个软件开源,不代表你能无限制地使用它,你需要在使用它的过程中遵守一定的规则,这些规则就是license。大家可以用记事本打开这个COPYING文件看看它的内容。开源软件的license有很多种,LwIP的属于BSD License。LwIP的开源程度是很高的,你几乎可以无限制地使用它。
* (3)FILES文件用于介绍当前目录下的目录信息。
* (4)README文件对LwIP进行了一个简单的介绍。
* (5)UPGRADING文件记录了LwIP每个大版本的更新,会对用户使用和移植LwIP造成的影响。所谓大版本更新指的是:1.3.x - 1.4.x – 2.0.x – 2.1.x。小版本更新,比如2.0.1 – 2.0.2 – 2.0.3,这个过程只是一些bug的修复和性能的改善,不会对用户的使用造成影响。用户只要将原有工程的目录中与LwIP相关的旧版本文件替换成新版本的文件,重新编译,就能直接使用。
* (6)doc文件夹里面是关于LwIP的一些文档,可以看成是应用和移植LwIP的指南。但是这些文档比较零散,不成体系,而且纯文本阅读起来很费劲,阅读意义不是很大。
* (7)test文件夹里面是测试LwIP内核性能的源码,将它们和LwIP源码加入到工程中一起编译,调用它们提供的函数,可以获得许多与LwIP内核性能有关的指标。这种内核性能测试功能,只有非常专业的人士才用的到。
* (8)src文件夹里面就是我们最关心的LwIP源码文件,下面会详细讲解。
打开src文件夹,如图 2‑6所示。
![](https://box.kancloud.cn/d4739271d0d39305f4b292c2959ba331_507x208.png)
* api文件夹里面装的是NETCONN API和Socket API相关的源文件,只有在操作系统的环境中,才能被编译。
* apps文件夹里面装的是应用程序的源文件,包括常见的应用程序,如httpd、mqtt、tftp、sntp、snmp等。
* core文件夹里面是LwIP的内核源文件,后续会详细讲解。
* include文件夹里面是LwIP所有模块对应的头文件。
* netif文件夹里面是与网卡移植有关的文件,这些文件为我们移植网卡提供了模板,我们可以直接使用。
LwIP内核是由一系列模块组合而成的,这些模块包括:TCP/IP协议栈的各种协议、内存管理模块、数据包管理模块、网卡管理模块、网卡接口模块、基础功能类模块、API模块。每个模块是由相关的几个源文件和头文件组成的,通过头文件对外声明一些函数、宏、数据类型,使得其它模块可以方便地调用此模块的功能。而构成每个模块的头文件都被组织在了include目录中,而源文件则根据类型被分散地组织在api、apps、core、netif目录中。
接下来,我们介绍一下core文件夹,如图 2‑7所示。
![](https://box.kancloud.cn/925c968cf0251f3e6cc4b60d6b6b1802_590x503.png)
我们逐一介绍一下这些源文件的功能。
* ipv4文件夹里面是与IPv4模块相关的源文件,它们实现了IPv4协议规定的对数据包的各种操作。ipv4文件夹中还包括一些并非属于IP协议,但会受IP协议影响的协议源文件,包括DHCP、ARP、ICMP、IGMP。
* ipv6文件夹里面是与IPv6模块相关的源文件,它们实现了IPv6协议规定的对数据包的各种操作。ipv6文件夹中还包括一些并非属于IP协议,但会受IP协议影响的协议源文件,包括DHCP、ARP、ICMP、IGMP。
* altcp.c、altcp\_alloc.c、altcp\_tcp.c等文件是应用程序分层TCP连接API,从TCPIP线程使用,是一个抽象层,可以模拟应用程序的tcp回调API,同时防止直接链接,这样,应用程序可以使用其他应用程序层协议在TCP之上而不知道细节(例如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文件实现了LwIP对网络数据包的各种操作。网络数据包在LwIP内核中以pbuf结构体的形式存在,这提高了LwIP内核对数据包处理效率,以及提高了数据包在各层之间递交的效率。pbuf结构体也是我们使用RAW/Callback API进行网络应用程序开发的关键,后续我们会详细讲解。
* raw.c文件实现了一个传输层协议的框架,我们可以在它的基础上修改和添加代码,实现自定义的传输层协议,与UDP/TCP一样,它可以与IP层直接进行交互。这类似RAW Socket。在实际的应用中,我们常用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数据包的操作。
- 说明
- 第1章:网络协议简介
- 1.1:常用网络协议
- 1.2:网络协议的分层模型
- 1.3:协议层报文间的封装与拆封
- 第2章:LwIP简介
- 2.1:LwIP的优缺点
- 2.2:LwIP的文件说明
- 2.2.1:如何获取LwIP源码文件
- 2.2.2:LwIP文件说明
- 2.3:查看LwIP的说明文档
- 2.4:使用vscode查看源码
- 2.4.1:查看文件中的符号列表(函数列表)
- 2.4.2:函数定义跳转
- 2.5:LwIP源码里的example
- 2.6:LwIP的三种编程接口
- 2.6.1:RAW/Callback API
- 2.6.2:NETCONN API
- 2.6.3:SOCKET API
- 第3章:开发平台介绍
- 3.1:以太网简介
- 3.1.1:PHY层
- 3.1.2:MAC子层
- 3.2:STM32的ETH外设
- 3.3:MII 和 RMII 接口
- 3.4:PHY:LAN8720A
- 3.5:硬件设计
- 3.6:软件设计
- 3.6.1:获取STM32的裸机工程模板
- 3.6.2:添加bsp_eth.c与bsp_eth.h
- 3.6.3:修改stm32f4xx_hal_conf.h文件
- 第4章:LwIP的网络接口管理
- 4.1:netif结构体
- 4.2:netif使用
- 4.3:与netif相关的底层函数
- 4.4:ethernetif.c文件内容
- 4.4.1:ethernetif数据结构
- 4.4.2:ethernetif_init()
- 4.4.3:low_level_init()
- 第5章:LwIP的内存管理
- 5.1:几种内存分配策略
- 5.1.1:固定大小的内存块
- 5.1.2:可变长度分配
- 5.2:动态内存池(POOL)
- 5.2.1:内存池的预处理
- 5.2.2:内存池的初始化
- 5.2.3:内存分配
- 5.2.4:内存释放
- 5.3:动态内存堆
- 5.3.1:内存堆的组织结构
- 5.3.2:内存堆初始化
- 5.3.3:内存分配
- 5.3.4:内存释放
- 5.4:使用C库的malloc和free来管理内存
- 5.5:LwIP中的配置
- 第6章:网络数据包
- 6.1:TCP/IP协议的分层思想
- 6.2:LwIP的线程模型
- 6.3:pbuf结构体说明
- 6.4:pbuf的类型
- 6.4.1:PBUF_RAM类型的pbuf
- 6.4.2:PBUF_POOL类型的pbuf
- 6.4.3:PBUF_ROM和PBUF_REF类型pbuf
- 6.5:pbuf_alloc()
- 6.6:pbuf_free()
- 6.7:其它pbuf操作函数
- 6.7.1:pbuf_realloc()
- 6.7.2:pbuf_header()
- 6.7.3:pbuf_take()
- 6.8:网卡中使用的pbuf
- 6.8.1:low_level_output()
- 6.8.2:low_level_input()
- 6.8.3:ethernetif_input()
- 第7章:无操作系统移植LwIP
- 7.1:将LwIP添加到裸机工程
- 7.2:移植头文件
- 7.3:移植网卡驱动
- 7.4:LwIP时基
- 7.5:协议栈初始化
- 7.6:获取数据包
- 7.6.1:查询方式
- 7.6.2:ping命令详解
- 7.6.3:中断方式
- 第8章:有操作系统移植LwIP
- 8.1:LwIP中添加操作系统
- 8.1.1:拷贝FreeRTOS源码到工程文件夹
- 8.1.2:添加FreeRTOS源码到工程组文件夹
- 8.1.3:指定FreeRTOS头文件的路径
- 8.1.4:修改stm32f10x_it.c
- 8.2:lwipopts.h文件需要加入的配置
- 8.3:sys_arch.c/h文件的编写
- 8.4:网卡底层的编写
- 8.5:协议栈初始化
- 8.6:移植后使用ping测试基本响应
- 第9章:LwIP一探究竟
- 9.1:网卡接收数据的流程
- 9.2:内核超时处理
- 9.2.1:sys_timeo结构体与超时链表
- 9.2.2:注册超时事件
- 9.2.3:超时检查
- 9.3:tcpip_thread线程
- 9.4:LwIP中的消息
- 9.4.1:消息结构
- 9.4.2:数据包消息
- 9.4.3:API消息
- 9.5:揭开LwIP神秘的面纱
- 第10章:ARP协议
- 10.1:链路层概述
- 10.2:MAC地址的基本概念
- 10.3:初识ARP
- 10.4:以太网帧结构
- 10.5:IP地址映射为物理地址
- 10.6:ARP缓存表
- 10.7:ARP缓存表的超时处理
- 10.8:ARP报文
- 10.9:发送ARP请求包
- 10.10:数据包接收流程
- 10.10.1:以太网之数据包接收
- 10.10.2:ARP数据包处理
- 10.10.3:更新ARP缓存表
- 10.11:数据包发送流程
- 10.11.1:etharp_output()函数
- 10.11.2:etharp_output_to_arp_index()函数
- 10.11.3:etharp_query()函数
- 第11章:IP协议
- 11.1:IP地址.md
- 11.1.1:概述
- 11.1.2:IP地址编址
- 11.1.3:特殊IP地址