LwIP应用笔记(一):LwIP移植的一些预备知识

欢迎来我的CSDN博客转转:https://blog.csdn.net/lczdk

前言

从2021年3月到6月,我利用工作之余的一些零碎时间看了看《嵌入式网络那些事》这本介绍LwIP协议的书,现在这本书也基本上看的差不多了,于是开了这个专栏,打算用几篇文章来大概总结一下收获,同时加深自己的认识。
总体来说,打算花一个月的时间更新五篇文章:

  1. 第一篇文章,也就是这篇,打算大概谈谈TCP/IP协议的一些基础知识,同时总结一下LwIP的代码结构,聊聊LwIP的初始化过程以及LwIP是如何与底层的网卡交互的,这些其实是为第二篇的移植做铺垫。
  2. 第二篇文章,会总结下如何进行LwIP无操作系统环境下的移植,完成这步后,我们就可以通过使用LwIP中的RAW API,借助回调编程的方式来开发TCP/IP应用程序了。
  3. 第三篇文章,会总结如何在存在RTOS的情况下,移植LwIP的系统模拟层,完成这步后,我们就可以通过使用上比RAW API更加简单的NETCONN API以及Socket接口层在多任务环境下开发TCP/IP应用程序。
  4. 第四篇文章,会谈一下如何基于LwIP进行初步的UDP协议编程,如果时间够的话会同时总结使用NETCONN API于RAW API在UDP协议编程中的使用流程,如果时间不够就只总结NETCONN API了。
  5. 第五篇文章,会谈一下如何基于LwIP进行初步的TCP协议编程,如果时间够的话会同时总结使用NETCONN API于RAW API在UDP协议编程中的使用流程,如果时间不够就只总结NETCONN API了。

后续如果笔者还有机会更加深入的了解LwIP的话,也会继续更新其他文章,但是这个以后可能就是以年为单位了。。。

TCP/IP协议栈与LwIP

TCP/IP作为一个网络协议栈,其通过分布在各个层次的一堆协议来共同为上层的应用层程序提供网络访问接口。对于网络相关的协议,有一个OSI模型描述了处于各个层次协议做了哪些事情,笔者曾经翻译过一篇介绍OSI模型的文章,见:【翻译】OSI模型:网络通讯中的7个层次,但是TCP/IP协议栈在这个模型出来之前就已经有了,所以有一套自己的分层方法,但是所幸两者还是能找到对应关系的。笔者自己作了一幅图,这幅图对照了TCP/IP协议栈的分层方法以及OSI模型的分层方法,并且列出了TCP/IP各个层大体是在做什么事。
在这里插入图片描述LwIP实现了网络互联层与传输层的主要协议,同时也提供了部分主要的应用层协议。而底层的网络接口层,最常见的是以太网,其分为MAC与PHY两个部分,一般由网卡负责实现,我们移植过程中的主要工作,就是将网卡驱动提供的接口包装成LwIP要求的样子,然后提供给LwIP的网络接口层使用。
下图说明了LwIP的主要文件夹结构,以及各层实现了哪些主要协议,此图基于LwIP2.1.2制作,这也是目前最新的LwIP版本,话说这个版本发布也是几年前的事了。

在这里插入图片描述

LwIP的初始化流程与移植需要做的事

有操作系统时和无操作系统时的LwIP初始化流程有部分差异,但是基本流程是一致的,下图大体说明了整个初始化流程。

在这里插入图片描述

整理LwIP的初始化流程是为了弄明白我们在移植时需要做的事,整个移植过程中,有三处地方是需要自己写代码去实现的:

  1. 声明定义一个netif结构体类型的变量用于描述网络接口;
  2. 实现一个底层网卡的初始化函数,并在执行netif_add函数时传入以用于初始化底层网卡;
  3. 轮询网卡或者响应网卡中断,将收到的数据包传入给LwIP处理;

考虑到2、3两步骤还是有一定的复杂性的,LwIP的开发人员故而提供了一些帮助。在LwIP官网的下载目录下还有一个名为contrib-2.1.0的压缩包,里面整理了开发者们贡献的各种示例代码,在contrib-2.1.0/examples/ethernetif下有个ethernetif.c,这个文件提供了底层网卡初始化函数 err_t ethernetif_init(struct netif netif) 以及网络数据包接收处理的函数 void ethernetif_input(struct netif netif) ,我们需要做的就是根据ethernetif.c文件中的提示以及实际情况完善其中的函数,然后将ethernetif_init传入netif_add函数来初始化网卡,并且在网卡收到数据包时,调用ethernetif_input从网卡读取数据并提交给LwIP处理。ethernetif.c文件内各个函数的调用关系大体如下图所示。

在这里插入图片描述

了解完这些,下一步就可以开始LwIP的移植了,我尽量早日肝出下一篇。