第二节 LwIP简介

这篇具有很好参考价值的文章主要介绍了第二节 LwIP简介。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本专栏使用的是LwIP 2.1.2版本 ,官方下载链接:http://savannah.nongnu.org/projects/lwip/。

LwIP 的优缺点

本专栏以LwIP 2. 1.2 为主要对象进行讲解,后续中出现的LwIP 如果没有特殊声明,均指2.1.2 版本。此时的LwIP 2. 1.2 为最新版本,可能当这本书写完的时候,LwIP 又被更新了,对于学习而言,大家其实不必纠结于是否必须用最新的版本,因为2.1.2 版本和它后面的版本在移植和应用方法上并没有什么区别。

LwIP 全名:Light weight IP,意思是轻量化的TCP/IP 协议,是瑞典计算机科学院(SICS) 的AdamDunkels 开发的一个小型开源的TCP/IP 协议栈。LwIP 的设计初衷是:用少量的资源消耗实现一个较为完整的TCP/IP 协议栈,其中“完整”主要指的是TCP 协议的完整性,实现的重点是在保持TCP 协议主要功能的基础上减少对RAM 的占用。此外LwIP 既可以移植到操作系统上运行,也可以在无操作系统的情况下独立运行。

LwIP 具有主要特性:

  1. 支持ARP 协议(以太网地址解析协议)。
  2. 支持ICMP 协议(控制报文协议),用于网络的调试与维护。
  3. 支持IGMP 协议(互联网组管理协议),可以实现多播数据的接收。
  4. 支持UDP 协议(用户数据报协议)。
  5. 支持TCP 协议(传输控制协议),包括阻塞控制、RTT 估算、快速恢复和快速转发。
  6. 支持PPP 协议(点对点通信协议),支持PPPoE。
  7. 支持DNS(域名解析)。
  8. 支持DHCP 协议,动态分配IP 地址。
  9. 支持IP 协议,包括IPv4、IPv6 协议,支持IP 分片与重装功能,多网络接口下的数据包转发。
  10. 支持SNMP 协议(简单网络管理协议)。
  11. 支持AUTOIP,自动IP 地址配置。
  12. 提供专门的内部回调接口(Raw API),用于提高应用程序性能。
  13. 提供可选择的Socket API、NETCONN API (在多线程情况下使用) 。

LwIP 在嵌入式中使用有以下优点:

  1. 资源开销低,即轻量化。LwIP 内核有自己的内存管理策略和数据包管理策略,使得内核处理数据包的效率很高。另外,LwIP 高度可剪裁,一切不需要的功能都可以通过宏编译选项去掉。LwIP 的流畅运行需要40KB 的代码ROM 和几十KB 的RAM,这让它非常适合用在
    内存资源受限的嵌入式设备中。
  2. 支持的协议较为完整。几乎支持TCP/IP 中所有常见的协议,这在嵌入式设备中早已够用。
  3. 实现了一些常见的应用程序:DHCP 客户端、DNS 客户端、HTTP 服务器、MQTT 客户端、TFTP 服务器、SNTP 客户端等等。
  4. 同时提供了三种编程接口:RAW API、NETCONN API(注:NETCONN API 即为SequentialAPI,为了统一,下文均采用NETCONN API)和Socket API。这三种API 的执行效率、易用性、可移植性以及时空间的开销各不相同,用户可以根据实际需要,平衡利弊,选择合适的API 进行网络应用程序的开发。
  5. 高度可移植。其源代码全部用C 实现,用户可以很方便地实现跨处理器、跨编译器的移植。另外,它对内核中会使用到操作系统功能的地方进行了抽象,使用了一套自定义的API,用户可以通过自己实现这些API,从而实现跨操作系统的移植工作。
  6. 开源、免费,用户可以不用承担任何商业风险地使用它。
  7. 相比于嵌入式领域其它的TCP/IP 协议栈,比如uC-TCP/IP、FreeRTOS-TCP 等,LwIP 的发展历史要更悠久一些,得到了更多的验证和测试。LwIP 被广泛用在嵌入式网络设备中,国内一些物联网公司推出的物联网操作系统,其TCP/IP 核心就是LwIP;物联网知名的WiFi模块ESP8266,其TCP/IP 固件,使用的就是LwIP。

LwIP 尽管有如此多的优点,但它毕竟是为嵌入式而生,所以并没有很完整地实现TCP/IP 协议栈。相比于Linux 和Windows 系统自带的TCP/IP 协议栈,LwIP 的功能不算完整和强大。但对于大多数物联网领域的网络应用程序,LwIP 已经足够了。

LwIP 的文件说明

如何获取LwIP 源码文件

LwIP 的代码已经交给Savannah 托管,LwIP 的项目主页是:http://savannah.nongnu.org/projects/lwip/。这个主页简单地介绍了一下LwIP,然后给出了许多链接,你可以通过这些链接去挖掘更多关于LwIP 的信息。在这里,我们只关注两个地方,如图中的方框所示。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

点击“Project Homepage”,会得到一个网页,如图2_2 所示。这个网页可以看成是LwIP 的官方说明文档。我们可以通过这个网页获得关于LwIP 的很多信息,包括LwIP 的使用注意、数据的拷贝、系统初始化流程、多线程中要注意的问题、优化方法、内核模块的分类介绍、内核数据结构、内核重要全局变量、内核源码文件等。这些内容专业性比较强,不建议初学时在它上面花费精力,并且里面的很多内容在我们专栏的后续章节中中会有所讲解。在这里,我们只要知道有这么个东西就行了。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip
lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

点击“Download Area”,会得到一个网页,如图2_3 所示。通过这个网页,我们可以下载到LwIP所有版本的源代码包和contrib 包。你每点击一个红色字体的资源链接,浏览器就会开启一个ftp连接,帮助你下载想要的文件到电脑中。但是这个页面提供的下载链接,在国内一般是没有响应的。这个网页最下方的黑字内容推荐我们使用另外一个下载页面:http://download-mirror.savannah.gnu.org/releases/。在这个页面下,用户可以下载到所有在Savannah 托管的开源软件,但我们只关心LwIP。利用浏览器的搜索功能,快捷键Ctrl+F,可以快速找到lwip 目录。在这里为了方便,我们直接给出最终的下载链接:http://download-mirror.savannah.gnu.org/releases/lwip/。

可能有人会问,什么是contrib 包,它与源代码包有什么不同?源代码包里面装的主要是LwIP内核的源码文件,而contrib 包里面装的是移植和应用LwIP 的一些demo,即应用示例。contrib包不属于LwIP 内核的一部分,里面的很多内容来自开源社区的贡献,因此contrib 包的版本管理不像内核源码那样严格和规范,但也是很有参考价值的。按理说,LwIP 源码面世越久,开源社区对它的贡献就越大,所以越高版本的contrib 包,提供的应用示例就越丰富,越有参考价值。在大版本区别不大的情况下,建议大家下载最新的contrib 包。后续我们会对contrib 包里面提供的应用示例进行讲解。另外,还有些“.sig”后缀的文件,这是数字签名,大家忽略就好。

LwIP 文件说明

按照上一小节的介绍,我们下载两个包:lwip-2.1.2.zip(源码包)和contrib-2.1.0.zip(contrib 包)。解压以后会得到两个文件夹,如图所示。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

我们先打开“lwip-2.1.2”文件夹,如图所示。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

该目录的内容为:

  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 文件夹,如图所示。
lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

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 文件夹,如图 所示。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

我们逐一介绍一下这些源文件的功能。

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,代理连接),此类接口我们并没有怎么使用,或者如果选择使用安全的加密传输的话,可以配合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 文件实现了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 数据包的操作。

查看LwIP 的说明文档

关于LwIP 的官方说明文档:http://www.nongnu.org/lwip/2_1_x/index.html,我就简单带大家浏览一下。打开连接,我们可以看到LwIP 的Overview(概述),这里就简单看看即可,我们可以点击左侧的“Common pitfalls”,查看一下LwIP 常见的陷阱,可能在使用中会遇到,到时候注意一下即可,在前面的章节中,我们也提到过,LwIP 可以工作在无操作系统环境也可以工作在有操作系统的环境中,Common pitfalls 中提到Mainloop Mode(主函数轮询模式)与OS Mode(操作系统模式)需要注意的一些事情,具体见图。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

此外,我们还可以点击左侧的“Modules”,查看一些模块相关的说明,以及例子,比如有无操作系统相关的,如,还有基础配置,如LwIP 的内存管理模块,数据包缓冲区等会是在“Modules –>Infrastructure”页面中,具体见图。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

当然,还有很重要的一些用户常用的API 函数,也是在“Modules”中可以找到,例如Raw API,NETCONN API 和Socket API 等,具体见图。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

此外还有一些“Applications”应用层相关的说明,如HTTP、MQTT、TFTP 等,具体见图。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

还有一些数据结构相关的说明,当我们在程序中看到哪个数据结构不懂的,都可以在这里找到对应的说明,也是比较重要的,LwIP 本质就是对数据的处理,其中也使用了大量的数据结构,有空可以多研究研究它,具体见图。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

当然,我们也能通过函数名字的首字母来查找函数的作用,具体见图。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

使用vscode 查看源码

查看文件中的符号列表(函数列表)

LwIP 的源码很庞大,我们使用微软的开源软件——vs code 查看源码,并且快速找到源码的函数与定义,首先我们先安装vs code,我们可以在https://code.visualstudio.com/download 中下载时候自己电脑的vs code 版本,然后安装即可。

然后打开我们的源码文件夹,右键,选择Open with Code,这样子就能直接在vs code 打开我们整个文件夹的源码了,具体见图。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

在vs code 中,就显示了我们打开的源码,LwIP 那么多文件,我们怎么去快速找到源码文件中的某个函数呢?很简单,比如我们知道某个函数的名字的话,可以直接搜索的,这点就不必我多说,但是有时候,我们不记得某个函数的名字,只知道它在哪个文件,或者只知道在好几个文件中的某一个,那么我们就需要一个个去查找这个函数了,vs code 提供很强大的功能,就是可以快速查文件中的符号列表和函数列表,我们首先打开一个源码文件,比如tcp.c,然后我们通过快捷键“Shift+Ctrl+O”即可打开对应源码文件的符号列表和函数列表,通过查看这些列表,就能知道该源码文件中是否有我们需要的函数或者宏定义等,具体见图。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

函数定义跳转

vs code 看源码是非常方便的,比如,我们可以通过F12 按键进行跳转到定义,通过“Alt+F12”速览定义,或者通过快捷键“Ctrl+F12”进行Go to Declaration,这些操作还是很方便的,当然啦,我们也能通过鼠标右键,进行选择,具体见图。如果在查看函数之后,想返回跳转前的位置,只需要通过快捷键“Alt+ 键盘的←(前后左右的左按键)”跳回即可。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

LwIP 源码里的example

(后面LwIP 的基础例程主要直接使用或参考源码里的example 即可)

我们打开之前下载好的contrib-2.1.0 文件夹,如图所示。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

我们先讲解一下这个目录:

  1. addons 目录。LwIP 中很多模块的实现,都是可以由用户干预的,比如校验和、TCP 初始序列号。LwIP 的内核代码,通过宏编译选项的设置,可以将内核中某些模块的实现方法配置成LwIP默认的方法,或者用户自定义的方法。用户自定义的方法通常需要用户在钩子函数中实现。在实际应用中,我们采用内核默认的方法就足够了,只有在非常特定的场合下,为了性能、资源开销等因素的考虑,我们可能会需要自己实现相关的模块,或者说编写相应的钩子函数。那么这时该怎么办呢?addons 目录下的内容就为我们提供了参考。对于初学者,没必要关心这个目录。

  2. apps 目录里实现了很多应用层协议。LwIP 源码包中也有apps 目录,但源码包中apps 目录下的应用程序全部用RAW/Callback API 实现,属于内核代码的一部分。而此apps 目录里的应用程序可以是由三种API 中的任何一种实现的。读者可以把它看成是内核源码所提供的应用程序的一个补充。

  3. examples 目录里是一些LwIP 的应用示例。在使用LwIP 开发应用程序时会出现的典型问题,比如如何移植网卡、如何使用LwIP 的API、如何使用源码中提供的应用程序,对于这些问题,这个目录为我们提供了参考。我们在后续的章节中,会使用这个目录中的例子来讲解LwIP 的应用程序。

  4. ports 目录里是一些移植文件,它可以帮助我们将LwIP 移植到某个具体的操作系统中。目前这个目录所提供的移植文件,只支持FreeRTOS、UNIX、Win32。我们会在后续的章节中讲解如何移植LwIP。

LwIP 的三种编程接口

LwIP 提供了三种编程接口,分别为RAW/Callback API、NETCONN API、SOCKET API。它们的易用性从左到右依次提高,而执行效率从左到右依次降低,用户可以根据实际情况,平衡利弊,选择合适的API 进行网络应用程序的开发。以下内容将分别介绍这三种API。

RAW/Callback API

LwIP 提供了三种编程接口,分别为RAW/Callback API、NETCONN API、SOCKET API。它们的易用性从左到右依次提高,而执行效率从左到右依次降低,用户可以根据实际情况,平衡利弊,选择合适的API 进行网络应用程序的开发。以下内容将分别介绍这三种API。

RAW/Callback API

RAW/Callback API 是指内核回调型的API,这在许多通信协议的C 语言实现中都有所应用。对于从来没有接触过回调式编程的人来说,可能理解起来会比较困难,我们在后面的章节中会详细介绍它。

RAW/Callback API 是LwIP 的一大特色,在没有操作系统支持的裸机环境中,只能使用这种API进行开发,同时这种API 也可以用在操作系统环境中。这里先简要说明一下“回调”的概念。你新建了一个TCP 或者UDP 的连接,你想等它接收到数据以后去处理它们,这时你需要把处理该数据的操作封装成一个函数,然后将这个函数的指针注册到LwIP 内核中。LwIP 内核会在需要的时候去检测该连接是否收到数据,如果收到了数据,内核会在第一时间调用注册的函数,这个过程被称为“回调”,这个注册函数被称为“回调函数”。这个回调函数中装着你想要的业务逻辑,在这个函数中,你可以自由地处理接收到的数据,也可以发送任何数据,也就是说,这个回调函数就是你的应用程序。到这里,我们可以发现,在回调编程中,LwIP 内核把数据交给应用程序的过程就只是一次简单的函数调用,这是非常节省时间和空间资源的。每一个回调函数实际上只是一个普通的C 函数,这个函数在TCP/IP 内核中被调用。每一个回调函数都作为一个参数传递给当前TCP 或UDP 连接。而且,为了能够保存程序的特定状态,可以向回调函数传递一个指定的状态,并且这个指定的状态是独立于TCP/IP 协议栈的。

在有操作系统的环境中,如果使用RAW/Callback API,用户的应用程序就以回调函数的形式成为了内核代码的一部分,用户应用程序和内核程序会处于同一个线程之中,这就省去了任务间通信和切换任务的开销了。

简单来说,RAW/Callback API 的优点有两个:

  1. 可以在没有操作系统的环境中使用。
  2. 在有操作系统的环境中使用它,对比另外两种API,可以提高应用程序的效率、节省内存开销。

RAW/Callback API 的优点是显著的,但缺点也是显著的:

  1. 基于回调函数开发应用程序时的思维过程比较复杂。在后面与RAW/Callback API 相关的章节中可以看到,利用回调函数去实现复杂的业务逻辑时,会很麻烦,而且代码的可读性较差。
  2. 在操作系统环境中,应用程序代码与内核代码处于同一个线程,虽然能够节省任务间通信和切换任务的开销,但是相应地,应用程序的执行会制约内核程序的执行,不同的应用程序之间也会互相制约。在应用程序执行的过程中,内核程序将不可能得到运行,这会影响网络数据包的处理效率。如果应用程序占用的时间过长,而且碰巧这时又有大量的数据包到达,由于内核代码长期得不到执行,网卡接收缓存里的数据包就持续积累,到最后很可能因为满载而丢弃一些数据包,从而造成丢包的现象。

NETCONN API

在操作系统环境中,可以使用NETCONN API 或者Socket API 进行网络应用程序的开发。NETCONNAPI 是基于操作系统的IPC 机制(即信号量和邮箱机制)实现的,它的设计将LwIP 内核代码和网络应用程序分离成了独立的线程。如此一来,LwIP 内核线程就只负责数据包的TCP/IP封装和拆封,而不用进行数据的应用层处理,大大提高了系统对网络数据包的处理效率。

前面提到,使用RAW/Callback API 会造成内核程序和网络应用程序、不同网络应用程序之间的相互制约,如果使用NETCONN API 或者Socket API,这种制约将不复存在。

在操作系统环境中,LwIP 内核会被实现为一个独立的线程,名为tcpip_thread,使用NETCONNAPI 或者Socket API 的应用程序处在不同的线程中,我们可以根据任务的重要性,分配不同的优先级给这些线程,从而保证重要任务的时效性,分配优先级的原则具体见表格。

lwip,基于STM32的LwIP应用开发,网络,tcp/ip,网络协议,stm32,lwip

NETCONN API 使用了操作系统的IPC 机制,对网络连接进行了抽象,用户可以像操作文件一样操作网络连接(打开/关闭、读/写数据)。但是NETCONN API 并不如操作文件的API 那样简单易用。举个例子,调用f_read 函数读文件时,读到的数据会被放在一个用户指定的数组中,用户操作起来很方便,而NETCONN API 的读数据API,就没有那么人性化了。用户获得的不是一个数组,而是一个特殊的数据结构netbuf,用户如果想使用好它,就需要对内核的pbuf 和netbuf 结构体有所了解,我们会在后续的章节中对它们进行讲解。NETCONN API 之所以采取这种不人性的设计,是为了避免数据包在内核程序和应用程序之间发生拷贝,从而降低程序运行效率。当然,用户如果不在意数据递交时的效率问题,也可以把netbuf 中的数据取出来拷贝到一个数组中,然后去处理这个数组。

简单来说,NETCONN API 的优缺点是:

  1. 相较于RAW/Callback API,NETCONN API 简化了编程工作,使用户可以按照操作文件的方式来操作网络连接。但是,内核程序和网络应用程序之间的数据包传递,需要依靠操作系统的信号量和邮箱机制完成,这需要耗费更多的时间和内存,另外还要加上任务切换的时间开销,效率较低。

  2. 相较于Socket API,NETCONN API 避免了内核程序和网络应用程序之间的数据拷贝,提高了数据递交的效率。但是,NETCONN API 的易用性不如Socket API 好,它需要用户对LwIP 内核所使用数据结构有一定的了解。

SOCKET API

Socket,即套接字,它对网络连接进行了高级的抽象,使得用户可以像操作文件一样操作网络连接。它十分易用,许多网络开发人员最早接触的就是Socket 编程,Socket 已经成为了网络编程的标准。在不同的系统中,运行着不同的TCP/IP 协议,但是只要它实现了Socket 的接口,那么用Socket 编写的网络应用程序就能在其中运行。可见用Socket 编写的网络应用程序具有很好的可移植性。

不同的系统有自己的一套Socket 接口。Windows 系统中支持的是WinSock,UNIX/Linux 系统中支持的是BSD Socket,它们虽然风格不一致,但大同小异。LwIP 中的Socket API 是BSD Socket。但是LwIP 并没有也没办法实现全部的BSD Socket,如果开发人员想要移植UNIX/Linux 系统中的网络应用程序到使用LwIP 的系统中,就要注意这一点。

相较于NETCONN API,Socket API 具有更好的易用性。使用Socket API 编写的程序可读性好,便于维护,也便于移植到其它的系统中。Socket API 在内核程序和应用程序之间存在数据的拷贝,这会降低数据递交的效率。另外,LwIP 的Socket API 是基于NETCONN API 实现的,所以效率上相较前者要打个折扣。


参考资料:LwIP 应用开发实战指南—基于野火STM32文章来源地址https://www.toymoban.com/news/detail-774672.html

到了这里,关于第二节 LwIP简介的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • lwip:使用lwip UDP分包发送大量数据所遇问题以及解决方法(HPM6750、STM32)

    最近在调试HPM6750的项目时,考虑到调试方便需要将一些中间数据上传至PC分析,而且数据量又比较大,准备使用UDP分包发送,在调试的时候发现如下几个问题: sdk提供的lwip例程在使用时,分包会出现后一包的数据覆盖前一包数据的情况; 分包后,UDP首部校验和错误; sdk将

    2024年04月13日
    浏览(36)
  • STM32F407+FreeRTOS+LWIP UDP组播

    MCU:STM32F407ZET6 网卡:LAN8720A LWIP版本:V1.1.0 FreeRTOS 版本:V10.2.1 MII_RX_CLK/RMII_REF_CLK ------PA1                   MII_TXD0 ------PB12 MII_MDIO  ------PA2                                                 MII_TXD1 ------PB13 MII_RESET ------PA3                

    2024年04月26日
    浏览(83)
  • STM32 LWIP UDP 一对一 一对多发送

    之前没有接触过网络的通信,工作需要 UDP 接收和发送通信,在网上没有找到一对一、一对多的相关例程;于是在技术总监对我的指导,用正点原子板子给的例程是从官方的程序修改的,实现了Lwip UDP通信一对一、一对多的发送程序,可以随便指定发送 ip地址 、发送 端口号

    2024年02月15日
    浏览(48)
  • 【LWIP】stm32用CubeMX(6.4版)配置LwIP+Ping+TCPclient+TCPserver发送信息到PC(操作部分)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 这是我写的第一篇博客,欢迎大家给点鼓励和提出建议! 本人由于理想和爱好,辞去土木工作,于不到一个月前入职某科技公司开始从事嵌入式,专业能力和刚毕业的大学生一样都是很薄弱的。然后被

    2024年02月03日
    浏览(29)
  • 【STM32】关于LWIP高频率快速发送大量数据(1MB以上)卡死问题解决 + 提高LWIP发送速率的办法

    STM32型号:STM32F47VGTx 初始LWIP版本:1.4.1 PHY: ksz8051 最近遇到了个问题,从sd卡读数据存储到一个1024大小的数组,每次读200个字节,while循环读取,每次读取完成后立即通过lwip的conn_write接口通过tcp方式发送出去。但是会出现发送速率只有9kb/s的情况,而且高频率快速发送大量数

    2024年02月04日
    浏览(39)
  • stm32 freeRTOS lwip TCP快速发送,内存泄露问题

    现象1: 发送缓慢,tcp_write之后要等200多ms才能过发送出去,而且粘包严重。 解决办法 tcp_write之后,立马调用tcp_output ,tcp就会立马发送。 现象2: 持续快速发送和接受TCP数据出现断言 而且出现TCP断连,死机情况。 其实就是一句话 主程序和以太网中断程序中对PCB-unsent 之类的

    2024年02月08日
    浏览(34)
  • STM32 + RT-Thread + LwIp + DM9000

    开发板:STM32F103ZET6(战舰) RT-Thread:5.0.0 LwIp:2.1.2 网卡芯片:DM9000 编译环境:keil 我简单了解了一下,在嵌入式中,网络芯片的使用方式大致有三种,如下: (MCU + MAC + PHY) (MUC + MAC) —— PHY MCU —— (MAC + PHY) 注意: 我用括号里面的表示在同一块芯片中 移植 RT-Thread 不是此文

    2024年02月07日
    浏览(44)
  • STM32H743+LWIP+LAN8720+STM32cubeMX6.8.0

    最详细 一步到位 带程序 无偿分享   经历一个星期的痛苦,程序终于调试ping通了 网上的H743的博客我一个一个试一个一个试,到最后没有一个正常ping通,写本篇博客的目的就是为了后续再进行调试的人不在踩坑,听懂掌声,哈哈哈。 废话就不多说了,正文开始: 1、打开S

    2024年02月07日
    浏览(42)
  • STM32F4-ETH通信(lwip)——学习笔记

    一、关键知识点: 1、国际标准组织将整个以太网通信结构制定了 OSI 模型,总共分层七个层,分别 为应用层、表示层、会话层、传输层、网络层、数据链路层以及物理层,每个层功能不同,通信 中各司其职,整个模型包括硬件和软件定义。OSI 模型是理想分层,一般的网络系

    2024年02月03日
    浏览(39)
  • STM32H743使用CubeMX配置Lwip、Freertos

    硬件:野火挑战者开发板STM32H743IIT6 软件版本: CubeMX 6.7.0 STM32CubeH7 Firmware Package V1.11.0 / 04-Nov-2022 原理图: 时钟树参数仅供参考 MPU配置需要查相关资料,一知半解 修改GPIO与硬件原理图对应,串口参数默认 参数配置与硬件对应 此处网络收发地址非常重要!!! 使能中断 串口

    2024年02月07日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包