LWIP协议栈的分析和设计

---《计算机网络与控制》论文

LWIP协议栈的分析

摘要

近些年来,随着互联网和通讯技术的迅猛发展,除了计算机之外,大量的嵌入式设备也需求接入网络。目前,互联网中使用的通讯协议基本是TCP/IP协议族,可运行于不同的网络上,本文研究的就是嵌入式TCP/IP协议栈LWIP。文章首先分析了LWIP的整体结构和协议栈的实现,再介绍协议栈的内存管理,最后讲解协议栈应用程序接口。

关键词: 嵌入式系统;协议;LWIP;以太网

Abstract

With the rapid development of internet and communication technology, Not only computers but also embeded equipments are need to connect networks. At present, the basic communication protocol using in internet is TCP/IP, it can run in different network. This paper analyses the Light-Weight TCP/IP. The process model of a protocol implementation and processing of every layer are described first, and then gives the detailed management of Buffer and memory. At last, a reference lwIP API is given.

Key words: Embedded System, Protocol, Light weight TCP/IP,Ethernet

引言

近期互联网络硬件、软件的迅猛发展,使得网络用户呈指数增长,在使用计算机进行网络互联的同时,各种家电设备、仪器仪表以及工业生产中的数据采集与控制设备在逐步地走向网络化,以便共享网络中庞大的信息资源。在电子设备日趋网络化的背景下,引人TCP/IP 协议栈,以支持嵌人式设备接人网络,成为嵌人式领域重要的研究方向。本文分析一个轻量级的嵌入式系统的TCP/IP 协议栈-LWIP,LWIP是一个比较完整和可靠的TCP/IP协议栈,具有开源,易用,系统资源要求不高等优点。

一、LWIP概览

LWIP是瑞典计算机科学院(Swedish Institute of Computer Science)开发的一套用于嵌入式系统的开放源代码TCP/IP协议栈。 LWIP的含义是Light Weight(轻型)IP协议。LWIP TCP/IP实现的重点是在保持TCP协议主要功能的基础上减少处理和内存需求,因为LWIP使用无顺数据复制并经裁剪的API,一般它只需要几十KB的RAM和40KB左右的ROM就可以运行。同时LWIP可以移植到操作系统上,也可以在无操作系统的情况下独立运行。这使LWIP协议栈适合在低端嵌入式系统中使用。

LWIP的特性如下:

1.支持多网络接口下的IP转发;

2.支持ICMP协议;

3.支持主机和路由器进行多播的Internet组管理协议(IGMP);

4.包括实验性扩展的UDP(用户数据报协议);

5.包括阻塞控制,RTT估算和快速恢复和快速转发的TCP;

6.提供专门的内部回调接口(raw API)用;

7.支持DNS;

8.支持SNMP;

9.支持PPP;

10.支持ARP;

11.IP fragment的支持;

12.支持DHCP协议,动态分配IP地址;

13.可选择的Berkeley接口API(多线程情况下);

LWIP的源代码从作者Adam Dunkels的官方网站上下载(网址为:www.sics.se/~adam/lwip/),版本号为1.3.1。以下为解压后的目录结构。LWIP的目录结构主要分为五个部分:

1.Api\ : 应用程序接口文件,包括RAW,BSD以及正式提供的3种API。

2.Arch\ :与硬件和OS有关的文件,包括网络驱动,移植需要修改的文件。

3.Core\ :ICMP,IP,TCP,UDP协议的实现文件,以及一些辅助函数,LWIP实现的核心代码。

4.Include\ :LWIP的包括文件。

https://www.360docs.net/doc/268508623.html,if\ :ARP协议和LWIP网络设备驱动程序的模板,用户为自己的网络接口设计的驱动

程序应该与ethernetif.c中给出的驱动框架相同。

二、LwIP 的整体构架和进程模型:

传统的TCP/IP协议栈的实现方法严格分层,一般每一层都是一个独立的进程。这样方法虽然

有利于协议栈的调试,但是,其最大的弊端为数据包跨层传递时会引起频繁的上下文的切换,尤其是在多任务系统中,这样导致时间的浪费而直接影响到系统的实时性。LWIP 将所有TCP/IP 协议都放在在一个进程当中,这样TCP/IP 协议栈就和操作系统内核分开了。而应用层程序既可以是单独的进程也可以驻留在TCP/IP 进程中。如果应用程序是单独的进程,可以通过操作系统的邮箱、消息队列等通讯机制和 TCP/IP 进程进行通讯。如果应用层程序驻留在 TCP/IP 程中,那应用层程序就利用内部回调函数接口(Raw API)和 TCP/IP 协议栈通讯。LWIP进程模式的主要优点是可以很方便的移植到各种操作系统上去,进行应用程序的开发。

图2 - 1 LWIP的进程模型

LwIP 的进程模型如图2-1。在图2-1 中可以看到整个 TCP/IP 协议栈都在同一个名为“tcpip_thread”任务中,而位于图中最上方的“Application layer”(应用层)和下方的“Network interface layer”(网络接口驱动层)由用户自己来实现。应用层程序既可以是独立的任务(如图中正上方的“tftp_thread”和“tcpecho_thread”),通过 mbox(消息队列)和 LWIP 进程通讯;也可以在“tcpip_thread”(如图左上角)中利用原始接口(Raw API)和 TCP/IP协议栈通讯。

LWIP的数据流程主要分为接收和发送两种情况。

●接收数据时:数据包从一个网络接口被接收,如果网络接口驱动通过low_level_input函数读到这个数据包,简单的区分是ARP包还是IP包。如果是ARP包,将调用ARP的功能处理这个包。通常将更新一个ARP地址映射表,然后将数据包发送给IP_input函数处理。如是查一个IP包,将把数据包发送给ip_input函数处理。IP_input函数将数据包进行简单的处理(如计算校验和)后,分析该包是发送到本机的正常数据包,IP_input则根据包的类型,分别发送给udp_input、tcp_input、icmp_input函数处理。如果是发送给UDP或TCP协议的数据包,UDP、TCP协议的处理函数将做相应

的处理,最后发送给应用程序。

●发送数据流程:当应用程序需要发送一个数据包的时候,它将调用UDP和TCP协议处理函数udp_sender或tcp_write函数发送该数据包。UDP和TCP协议的处理函数接收数据后,将数据打包、分段,然后发送给IP层ip_output_if函数(需要时,将调用ip_route函数进行路由选择),该函数把数据打包、封装,然后调用网络接口驱动的low_level_output函数传给网络接口。

三、LWIP协议栈的实现

3.1 网络接口

LwIP使用一个与BSD中相似的网络接口结构来表示底层网络驱动,结构体的原型定义如下所示。struct netif {

struct netif *next;

char name[2];

int num;

struct ip_addr ip_addr;

struct ip_addr netmask;

struct ip_addr gw;

void (* input)(struct pbuf *p, struct netif *inp);

int (* output)(struct netif *netif, struct pbuf *p,

struct ip_addr *ipaddr);

void *state;

}

next指针用于将网络接口链入到全局链表中。Name域用于表示网络接口的类型,只用于这个接口在运行时由人工操作进行配置。Name由设备驱动设置并且应该反映硬件的种类。num用来区分相同类别的不同网络接口。三个IP 地址ip_addr,netmask与gw分别用来表示IP地址,子网掩码,网关。State表示设备驱动所包含的网络接口状态,由设备驱动设置。

当设备驱动接受到一个信息包的时候需要调用input指向的函数。而网络接口通过output指针与设备驱动连接。这个指针指向处于设备驱动中的发送信息包的函数,这个函数将在一个信息包发送出去后,被IP层调用。指针output将在设备驱动初始化的时候赋值。

3.2 IP处理

LwIP仅实现了IP层大部分的基本功能,能够发送、接收以及转发信息包,但是不能接收和发送 IP分片包,也不能处理携带 IP参数选项的信息包。不过对大多数的应用来说,这不会引起任何问题。

●接收信息包

收到的IP信息包,由网络设备驱动调用ip_input()函数开始处理。在这里完成对IP版本字段及包头长度的初始完整性检查,同时还要计算和验证包头校验和。协议栈假定代理会重新组合IP分片包为一个完整的包。接下来,函数检查目的地址是否与网络接口的IP地址相符以确定信息包是否到达预定主机。网络接口在链表中被排序并且采用了线性检索。如果一个到达的信息包被发现已经到达了目的主机,则由协议字段来决定信息包应该传送到哪一个上层协议。

●发送信息包

外发的信息包由ip_output()函数处理,该函数使用ip_route()函数查找适当的网络接口来传送信息包。当外发的网络接口确定后,信息包传给以外发网络接口为参数的ip_output_if()函数。

在这里,所有的IP包头字段被填充,并且计算 IP包头校验和。IP信息包的源及目标地址作为参数被传递给ip_output_if()函数。

●转发信息包

如果没有网络接口的地址与到达的信息包的目标地址相同,信息包应该被转发。这项工作由ip_forward()函数完成。在这里,TTL字段值被减少(Time To Live的简写,生存时间的意思,译者注),当减为0 的时候,将会给IP 信息包的最初发送者发送ICMP错误信息,并抛弃该信息包。最后,信息包被转发到适当的网络接口。查找适当的网络接口的算法与发送信息包使用的算法相同。

●ICMP处理

网际控制报文协议ICMP(Intemet Control Message Protoc01)总是与IP协议配置在一起,它运行在IP协议之上,发送一些控制信息,帮助Intemet处理差错。ICMP处理是相当简单的。由ip _input()收到的ICMP包被移交到icmp—input(),它解析ICMP报头并且进行适当的处理。ICMP处理过程如图3-1所示

图3 - 1 ICMP处理

3.3UDP处理

用户数据报协议UDP(User Datagram Protoc01)较为简单,输出处理也较简单,基本的UDP处理过程被分割为三个功能函数来实现:如图3-2所示。

◆udp_input()函数与UDP输入有关

◆udp_send()及udp_output()则用于UDP输出

图3 - 2 UDP处理

3.4TCP处理

传输层控制协议TCP为应用层提供可靠的二进制数据流服务。TCP协议比这里描述的其它协议

都要复杂,基本TCP处理如图3-3所示,被划分成六个函数:函数tcp_input()、tcp_process()、tep_receive()与TCP输入处理有关;tep_write()、top_enqueue()、tcp_output()对输出进行处理。

当应用程序想要发送TCP数据时,函数tcp_write()将被调用,函数tcp_write()将控制权交给tcp_enqueue(),该函数将数据分成合适大小的TCP段(如果必要),并放进发送队列。接下来函数top_output()将检查数据是否可以发送。也就是说,如果接收器的窗口有足够的空间并且拥塞窗口足够大,则使用ip_route()和ip_output_if()两个函数发送数据。

当ip_input()对IP报头进行检验且把TCP段移交给tcp_input()函数后,输入处理开始。在该函数中将进行初始检验(也就是checksumming和TCP剖析)并决定该段属于哪个TCP连接。该段于是由tcp_process()处理,它实现TCP状态机和其他任何必须的状态转换。如果一个连接处于从网络接收数据的状态,函数tcp_receive()将被调用。如果那样,tcp_receive()将把段上传给应用程序。如果段构成未应答数据(先前放入缓冲区的)的ACK,数据将从缓冲被移走并且收回该存储区。同样,如果接收到请求数据的ACK,接收者可能希望接收更多的数据,这时tcp_output()将被调用。

图3 -3 TCP处理

四、LWIP协议栈的内存管理

4.1 LWIP协议栈中pbuf 介绍

TCP / IP是一种基于O S I 参考模型的分层网络体系结构,它由应用层、运输层、网络层、数据链路层、物理层组成。各层之间消息的传递通过数据报的形式进行。由于各层之间报头长度不一样,当数据在不同协议层之间传递时,对数据进行封装和去封装、增加和删除操作将十分频繁。因此,必须有一种能适应数据动态增删、但在逻辑上又呈现连续性的数据结构,以满足在各协议层之间传递数据而不需要进行内存拷贝。嵌人式TCP/IP协议栈要求简单高效,并减少对内存的需求。这些都需要相应的内存管理机制实现。

LwI P利用pbuf 结构实现数据传递,它与BSD中的Mbuf 很相似。pbuf 的主要用途是保存在应用程序和网络接口间互相传递的用户数据。

pbuf 的内部结构为:

struct pbuf{

struct pbuf *next; / *指向下一个pbuf * /

void *payload; / *指向p b u f 数据中的起始位置* 1 ul6_t tot_len; / * 该pbuf和后续pbuf中数据.长度的总和 */

u16_t len; / * 该pbuf 中数据的长度* /

u16-t flags; / * pbuf 的类型* /

ul6_t ref; / * 该pbuf 被引用的次数* /

}

4.2 LWIP 内存管理的实现

在运行 TCP/IP 协议栈的嵌人式系统中,可以把整个系统的存储区域分为协议栈管理的存储器和应用程序管理的存储器两部分。

4.2.1 协议栈管理的存储器

协议栈管理的存储器是指TCP/IP 内核能够操作的内存区域,主要用于装载待接收和发送的网络数据分组。当接收到分组或者有分组要发送时,TCP/IP 协议栈为这些分组分配缓存; 接收到的分组交付给应用程序或者分组已经发送完毕后,对分配的缓存回收重用。协议栈分配的缓存必须能容纳各种大小的报文,例如从仅仅几个字节的ICMP 回答报文到几百个字节的TCP 分段报文。

LWIP 中的pbuf 有四种类型; PBUF_POOL 、PBUF_RAM 、PBUF_ROM 、PBUF_REF 。这四种类型的pbuf 都是从TCP/IP 协议栈管理的存储器中分配的,其中PBUF_ROM 和PBUF_REF 与应用程序管理的存储区域密切相关。PBUF_POOL 是具有固定容量的pbuf ,主要供网络设备驱动使用,为收到的数据分组分配缓存。在协议栈管理的内存中初始化了一个pbuf 池(PBUF_POOL),具有相同尺寸的pbuf 都是从这个pbuf 池中分配得到。一般使用多个PBUF_POOL 链接成一个链表,用于存储数据分组 。如图1所示。

图4 – 1 PBUF_POOL 链表

LwIP 用一个宏定义一个PBUF_POOL 的大小。一个分组需要分

配几个PBUF_POOL ,而在数据较少时分配一个PBUF_POOL 即可。由

于分配一个PBUF_POOL 类型的pbuf 很快,适合在中断处理中使用,

所以PBUF_POOL 主要供网络设备驱动使用,为收到的数据分组分配缓存。

应用程序发送动态产生的数据时,可以用PBUF_RAM 类型的

pbuf 。PBUF_RAM 在事先划分好的内存堆中分配。对该内存堆的操

作类似于C 语言中的malloc/free 。内存堆分配的结构如图4-2所

示。图2中每个被分配的存储块附带了一个小结构,该结构的两个指针指向相邻的内存块。used 标识位用来指示该内存块的分配情况,阴影部分表示已经被分配了,此时used 为1。当需要一块N 字节的存储块时,就对整个存储堆进行搜索。如果找到一块未用的

( used =0 )并且容量不小于N 字节的区域就表示分配成功,并且置use 为I 。而分配的内存块使用完后需要释放,为了不产生碎片,相邻且未用的内存块需要进行合并。

PBUF_POOL 和PBUF_RAM

都可以根据需要从存储器中动态分配,这种分配机制又称为动态存储器

分配机制。该分配机制不仅能为应用程序的数据分配存储空间,而且能为协议首部分配存储空间。在层与层之间传递数据时,真正需要修改的只是数据的格式,使之符合各层的规范,而数据本身不需要变动。实际上数据格式反应的是各层的首部,当数据在各层之间传送时,需要动态地添加和移去相应的首部,用动态分配机制可以很好地实现。

4.2.1 应用程序管理的存储器

应用程序管理的存储器是指应用程序管理、操作的存储区域,二般从该区域为应用程序发送数据分配缓存。虽然该存储区域不由TCP/IP协议栈管理,但在不严格分层的协议栈中,该存储区域必须与TCP/IP管理的存储器协同工作。为节省内存,LWIP不采取分级访问模式,而是通过指针访问数据。这样就不需要为数据的传递分配存储空间。应用程序发送的数据在交付LWIP后,LWIP 就认为这些数据是不能被改动的,因此应用程序的数据被认为是永远存在并且不能被改变的。这一点与ROM很相似。类型名PBUF_ROM也由此而来。如图4-3所示,PBUF_ROM的数据指针payload指向External memory( 外部存储区)。External memory指不由TCP/IP协议栈管理的存储区,它可以是应用程序管理的存储器为用户数据分配的缓存,也可以是ROM区域,如静态网页中的字符串常量等。由于由应用程序交付的数据不能被改动,因此就需要动态地分配一个PBUF_RAM来装载协议的首部,然后将PBUF_RAM(首部)添加到PBUF_ROM(数据)的前面。这样就构成了一个完整的数据分组。

图4 - 3 PBUF RAM与PBUF ROM的连接

图4-3中的PBUF_ROM还可以是PBUF_REF 。PBUF_REF和PBUF_ROM的特性非常相似,都可以实现数据的零拷贝。但是当发送的数据需要排队时就表现出PBUF_REF的特性了。例如在发送分组时,待发送的分组需要在ARP队列中排队,假如这些分组中有PBUF_ROM类型的pbuf,则说明该类型pbuf 中的数据位于应用程序的存储区域,是通过指针被PBUF_ROM引用的。这样直到分组被处理之前,被引用的应用程序的这块存储区域都不能另作它用。在此情况下要用到PBUF_REF类型的pbuf。在排队时,LWIP会为PBUF_REF类型的pbuf分配缓存(PBUF_POOL或PBUF_RAM),并将引用的应用程序的数据拷贝到分配的缓存中。这样应用程序中被引用数据的存储区域就能被释放。

pbuf结构实现了层与层之间的数据传递,但其非常消耗内存,并且需要TCP/IP协议栈为之分配存储空间,例如协议控制udp_pcb,tcp-pcb等。通常,嵌人式T C P/IP协议栈都不是严格分层的,尽量减少对内存的需求是实现嵌人式 TCP/IP的重点,内核的内存管理机制直接关系到嵌人式TCP/IP协议栈的性能。

五、LWIP的应用编程接口(API)

LwIP 为我们提供了三种应用程序接口(API函数)来实现 TCP/IP 协议栈,它们分别是:

1. low-level "core" / "callback" or "raw" API.

是一种低水平的、基于回调函数的 API(后面直接称 RAW API),整个通信流程依靠协议栈里的回调函数来驱动。因为回调函数的调用不能超越任务边界,这样应用程序和TCP/IP 协议栈必须运行在同一个任务中,而用户不再增加其它的任务,应用程序直接在TCP/IP任务空间运行。因此,就要避免调用诸如挂起、等待的函数,以防止整个TCP/IP任务被挂起。

RAW API 接口函数不仅在程序代码的执行时间上更快,而且在运行中它也占用更少的

内存资源。唯一的缺点是应用程序的编写比较困难,并且代码较难理解。尽管如此,在 CODE

和 RAM 都较小的嵌入式系统中,这也是我们优先考虑采用的方法。

2.higher-level "sequential" API / LWIP API

是一种高水平的、连续的 API,LWIP API为我们提供了一种通用的方法,它与BSD标准的 socket API非常相似,程序的执行过程同样是基于"open-read-write-close"模型的,但操作相对低级。API 不需要在应用程序和协议栈之间复制数据,因为应用程序可以巧妙的直接处理内部缓冲区。(充分利用 LwIP 的内部结构以实现其设计目标)

因为 BSD Socket API 易于理解,并且很多应用程序为它而写,所以 LwIP保留一个 BSD Socket 兼容层是很有用的。尽管 LwIP 与BSD Socket API 非常相似,但是它们之间仍然存在着值得注意的区别,使用 BSD Socket API 的应用程序不必知道普通文件和网络连接的差别,而使用 LwIP API 的应用程序就必须知道正在使用的是一个网络连接。它不适合于应用在比较小的嵌入式系统中,因为它的实现要求应用程序必须支持多线程。

从本质上讲,TCP/IP 协议栈的通信过程是事件驱动的,因此,TCP/IP 的代码和用户应用程序的代码,应该在不同的线程里面。当然,在不同的应用程序中,这两种 API 我们可以同时采用。实际上,sequential API就是一种利用 RAW API 来实现的一种属于协议本体的应用程序。

3. BSD Socket API

BSD Socket API 在连续的内存区域处理数据非常便于编写应用程序。因为应用程序内的数据处理通常是在这样的连续内存区域内进行的。但是,对于 LwIP,采用这种机制不具备任何优势。特别是 BSD Socket 需要将要发送的数据从应用程序复制到 TCP/IP 协议栈的内部缓冲区。复制数据的原因是应用程序与TCP/IP 协议栈通常驻留在不同的受保护空间。大多数情况是应用程序是一个用户进程,而TCP/IP 协议栈则驻留在操作系统内核。通过避免额外的复制操作,API 的性能可以大幅度提升。同样,为了复制数据,系统还需要为此分配额外的内存,这样每一个信息包都需要使用双倍的内存。

虽然LWIP提供了一些接口函数,但操作相对低级,使用起来不方便,不利用于后续开发。由于BSD SOCKET API很容易理解且己经有很多人为它写过应用程序,且应用程序使用BSD SOCKET API时候不需要知道普通文件和网络连接之间的差别,所以为了便要理解和应用,LWI 提供了基于LWIP接口函数的BSD SOCKET API,但没有任何容错机制,没有select()与poll()函数。以下就一些重要的SOCKET API函数做一介绍。

(1) socket()函数用于创建网络通信的套接字,并返回该套接字的整数描述符。函数原型为int socket(int domain, int type, int protocol),其中参数domain 代表协议族或地址族,对于TCP/IP 为PF_INET或AF_INET;type代表服务类型,对于TCP为SOCK_STREAM(流式),对于UDP 为SOCK -DGRAM(数据报);protocol代表使用的协议号,对于TCP 为IPPROTO_TCP,对于UDP 为IPPROTO_UDP,传递0表示根据协议族和给定的服务类型选择默认的协议号。若socket 成功返回,返回大于或等于0的有效套接字描述符,返回一1 表示发生了差错。

(2) bind()函数将BSD socket绑定到本地(本机)地址上。在调用bind()时,本地IP地址和端口号将被指定。

(3) connect()允许调用者为先前创建的套接字指明远程端点的地址。如果套接字使用TCP,该函数就

使用三次握手建立连接;如果套接字使用UDP,则仅指明远程端点,但不向它传送任何数据报。(4) listen()使套接字处于被动状态(即准备接受传入的连接请求)。在服务器处理某个请求时,协议软件应将后续收到的请求排队,listen 也设置排队的连接请求的数目。listen只用于TCP套接字。(5) accept()函数被用来等待TCP socket 口上的输入连接。在此之前,这个TCPsocket 口通过调用listen()已经被设置成监听状态,对accept()调用一直被阻塞,直到与远程主机建立连接。

(6) send()数在UDP和TCP两种连接中被用来发送数据。在调用send()前,数据接收器必须被设置成正在使用connect(),应用程序在调用send()后可以直接修改发送的数据。

(7) sendto()调用函数与send()调用函数类似,但是在参数调用中他们允许应用程序指定数据接收器。sendto()仅能在UDP连接中使用,实现这功能要使用netconnconnect()来设置数据包接收器。如果以前socket 口被连接,必须重设远程IP 地址和端口号。

(8) write()调用函数通过连接来发送数据并且能在UDP和TCP连接中使用。

参考文献

[1]W.Richard Stevens著. TCP/IP详解卷1:协议. 范建华等译. 机械工业出版社.2000

[2]Gary R.Wright,W.Richard Stevens著. TCP/IP详解卷2:实现.. 陆雪莹等译. 机械工业出版社.2000

[3]W.Richard Stevens著. TCP/IP 详解卷三:TCP 事务协议,HTTP,NNTP和UNIX域协议. 胡谷雨,昊礼发等译. 机械工业出版社.2000

[3]Jan Axelson. 编著.嵌入式Ethernet和internet通信设计技术. 骆丽,张岳强,欧小龙译.北京:北京航空航天大学出版社, 2006.1

[4]焦海波,刘健康.编著.嵌入式网络系统设计—基于Atmel ARM7,北京:北京航空航天大学出版社, 2008.4

[5] A dam Dunkels. Design and Implementation of the lwIP TCP/IP Stack, Feb 20, 2001

[6] https://www.360docs.net/doc/268508623.html,brosse. 编著 . 嵌入式实时操作系统uC/OS-II(第二版).邵贝贝等译. 北京:北京航空航天大学出版社, 2003.5

[7]Douglass https://www.360docs.net/doc/268508623.html,er,David L.Stevens著. 用TCP/IP进行网际互连第二卷—设计、实现与内核:ANSI C版(第三版). 张娟王海等译北京:电子工业出版社, 2008.10

[8]BSD Sockets Interface Programmer’sGuide Edition 6. HP Company

[9] Guido Moritz, Steffen Prüter, Web services on Deeply Embedded Devices with Real-Time Processing Proc on ETFA '08. IEEE

[10]邱书波,陈伟,基于ARM的轻量级TCP/IP协议栈的研究及移植计算机应用与软件,2009.8

[11] 王海波,基于以太网的LED图文显示系统的设计,大连理工大学硕士学位论文,2006.12

[11] 彭义波,uCOS与TCPIP协议栈的分析与移植,华中师范大学硕士学位论文,2005.6

[12] 付晓军,夏应清,何轩,嵌入式LWIP协议栈的内存管理,嵌入式技术,2005.10

和以下相关网站:

https://www.360docs.net/doc/268508623.html,/projects/lwip

https://www.360docs.net/doc/268508623.html,/wiki/LwIP_Wiki

https://www.360docs.net/doc/268508623.html,

Xmodem协议详解以及源代码剖析

研究 Xmodem 协议必看的 11个问题 Xmodem 协议作为串口数据传输主要的方式之一,恐怕只有做过 bootloader 的才有机会接触一下, 网上有关该协议的内容要么是英语要么讲解不详细。笔者以前写 bootloader 时研究过 1k-Xmodem ,参考了不少相关资料。这里和大家交流一下我对 Xmodem 的理解,多多指教! 1. Xmodem 协议是什么? XMODEM协议是一种串口通信中广泛用到的异步文件传输协议。分为标准Xmodem 和 1k-Xmodem 两种,前者以 128字节块的形式传输数据,后者字节块为 1k 即 1024字节,并且每个块都使用一个校验和过程来进行错误检测。在校验过程中如果接收方关于一个块的校验和与它在发送方的校验和相同时,接收方就向发送方发送一个确认字节 (ACK。由于 Xmodem 需要对每个块都进行认可, 这将导致性能有所下降, 特别是延时比较长的场合, 这种协议显得效率更低。 除了 Xmodem ,还有 Ymodem , Zmodem 协议。他们的协议内容和 Xmodem 类似,不同的是 Ymodem 允许批处理文件传输,效率更高; Zmodem 则是改进的了Xmodem ,它只需要对损坏的块进行重发,其它正确的块不需要发送确认字节。减少了通信量。 2. Xmodem 协议相关控制字符 SOH 0x01 STX 0x02 EOT 0x04 ACK 0x06 NAK 0x15

CAN 0x18 CTRLZ 0x1A 3.标准 Xmodem 协议(每个数据包含有 128字节数据帧格式 _______________________________________________________________ | SOH | 信息包序号 | 信息包序号的补码 | 数据区段 | 校验和 | |_____|____________|___________________|__________|____________| 4. 1k-Xmodem (每个数据包含有 1024字节数据帧格式 _______________________________________________________________ | STX | 信息包序号 | 信息包序号的补码 | 数据区段 | 校验和 | |_____|____________|___________________|__________|____________| 5.数据包说明 对于标准 Xmodem 协议来说,如果传送的文件不是 128的整数倍,那么最后一个数据包的有效内容肯定小于帧长,不足的部分需要用 CTRL- Z(0x1A来填充。这里可能有人会问,如果我传送的是 bootloader 工程生成的 .bin 文件, mcu 收到后遇到0x1A 字符会怎么处理?其实如果传送的是文本文件,那么接收方对于接收的内容是很容易识别的,因为 CTRL-Z 不是前 128个 ascii 码, 不是通用可见字符, 如果是二进制文件, mcu 其实也不会把它当作代码来执行。哪怕是 excel 文件等,由于其内部会有些结构表示各个字段长度等,所以不会读取多余的填充字符。否则 Xmodem太弱了。对于 1k-Xmodem ,同上理。 6.如何启动传输?

LWIP协议栈的分析和设计

---《计算机网络与控制》论文 LWIP协议栈的分析

摘要 近些年来,随着互联网和通讯技术的迅猛发展,除了计算机之外,大量的嵌入式设备也需求接入网络。目前,互联网中使用的通讯协议基本是TCP/IP协议族,可运行于不同的网络上,本文研究的就是嵌入式TCP/IP协议栈LWIP。文章首先分析了LWIP的整体结构和协议栈的实现,再介绍协议栈的内存管理,最后讲解协议栈应用程序接口。 关键词: 嵌入式系统;协议;LWIP;以太网 Abstract With the rapid development of internet and communication technology, Not only computers but also embeded equipments are need to connect networks. At present, the basic communication protocol using in internet is TCP/IP, it can run in different network. This paper analyses the Light-Weight TCP/IP. The process model of a protocol implementation and processing of every layer are described first, and then gives the detailed management of Buffer and memory. At last, a reference lwIP API is given. Key words: Embedded System, Protocol, Light weight TCP/IP,Ethernet 引言

lwip各层协议栈详解

竭诚为您提供优质文档/双击可除lwip各层协议栈详解 篇一:lwip协议栈源码分析 lwip源码分析 -----caoxw 1lwip的结构 lwip(lightweightinternetprotocol)的主要模块包括:配置模块、初始化模块、netif模块、mem(memp)模块、netarp模块、ip模块、udp模块、icmp模块、igmp模块、dhcp模块、tcp模块、snmp模块等。下面主要对我们需要关心的协议处理进行说明和梳理。配置模块: 配置模块通过各种宏定义的方式对系统、子模块进行了配置。比如,通过宏,配置了mem管理模块的参数。该配置模块还通过宏,配置了协议栈所支持的协议簇,通过宏定制的方式,决定了支持那些协议。主要的文件是opt.h。 初始化模块: 初始化模块入口的文件为tcpip.c,其初始化入口函数为: voidtcpip_init(void(*initfunc)(void*),void*arg)

该入口通过调用lwip_init()函数,初始化了所有的子模块,并启动了协议栈管理进程。同时,该函数还带有回调钩子及其参数。可以在需要的地方进行调用。 协议栈数据分发管理进程负责了输入报文的处理、超时处理、api函数以及回调的处理,原型如下: staticvoidtcpip_thread(void*arg) netif模块: netif模块为协议栈与底层驱动的接口模块,其将底层的一个网口设备描述成协议栈的一个接口设备(netinterface)。该模块的主要文件为netif.c。其通过链表的方式描述了系统中的所有网口设备。 netif的数据结构描述了网口的参数,包括ip地址、mac 地址、link状态、网口号、收发函数等等参数。一个网口设备的数据收发主要通过该结构进行。 mem(memp)模块: mem模块同一管理了协议栈使用的内容缓冲区,并管理pbuf结构以及报文的字段处理。主要的文件包括mem.c、memp.c、pbuf.c。 netarp模块: netarp模块是处理arp协议的模块,主要源文件为etharp.c。其主要入口函数为: err_tethernet_input(structpbuf*p,structnetif*netif)

LwIP协议栈源码详解

LwIP协议栈源码详解 ——TCP/IP协议的实现 Created by.. 老衲五木 at.. UESTC Contact me.. for_rest@https://www.360docs.net/doc/268508623.html, 540535649@https://www.360docs.net/doc/268508623.html,

前言 最近一个项目用到LwIP,恰好看到网上讨论的人比较多,所以有了写这篇学习笔记的冲动,一是为了打发点发呆的时间,二是为了吹过的那些NB。往往决定做一件事是简单的,而坚持做完这件事却是漫长曲折的,但终究还是写完了,时间开销大概为四个月,内存开销无法估计。。 这篇文章覆盖了LwIP协议大部分的内容,但是并不全面。它主要讲解了LwIP协议最重要也是最常被用到的部分,包括内存管理,底层网络接口管理,ARP层,IP层,TCP层,API 层等,这些部分是LwIP的典型应用中经常涉及到的。而LwIP协议的其他部分,包括UDP,DHCP,DNS,IGMP,SNMP,PPP等不具有使用共性的部分,这篇文档暂时未涉及。 原来文章是发在空间中的,每节每节依次更新,后来又改发为博客,再后来就干脆懒得发了。现在终于搞定,于是将所有文章汇总。绞尽脑汁的想写一段空前绝后,人见人爱的序言,但越写越觉得像是猫儿抓的一样。就这样,PS:由于本人文笔有限,情商又低,下里巴人一枚,所以文中的很多语句可能让您很纠结,您可以通过邮箱与我联系。共同探讨才是进步的关键。 最后,欢迎读者以任何方式使用与转载,但请保留作者相关信息,酱紫!码字。。。世界上最痛苦的事情莫过于此。。。 ——老衲五木

目录 1 移植综述------------------------------------------------------------------------------------------------------4 2 动态内存管理------------------------------------------------------------------------------------------------6 3 数据包pbuf--------------------------------------------------------------------------------------------------9 4 pbuf释放---------------------------------------------------------------------------------------------------13 5 网络接口结构-----------------------------------------------------------------------------------------------16 6 以太网数据接收--------------------------------------------------------------------------------------------20 7 ARP表-----------------------------------------------------------------------------------------------------23 8 ARP表查询-----------------------------------------------------------------------------------------------26 9 ARP层流程-----------------------------------------------------------------------------------------------28 10 IP层输入-------------------------------------------------------------------------------------------------31 11 IP分片重装1--------------------------------------------------------------------------------------------34 12 IP分片重装2--------------------------------------------------------------------------------------------37 13 ICMP处理-----------------------------------------------------------------------------------------------40 14 TCP建立与断开----------------------------------------------------------------------------------------43 15 TCP状态转换-------------------------------------------------------------------------------------------46 16 TCP控制块----------------------------------------------------------------------------------------------49 17 TCP建立流程-------------------------------------------------------------------------------------------53 18 TCP状态机----------------------------------------------------------------------------------------------56 19 TCP输入输出函数1-----------------------------------------------------------------------------------60 20 TCP输入输出函数2-----------------------------------------------------------------------------------63 21 TCP滑动窗口-------------------------------------------------------------------------------------------66 22 TCP超时与重传----------------------------------------------------------------------------------------69 23 TCP慢启动与拥塞避免-------------------------------------------------------------------------------73 24 TCP快速恢复重传和Nagle算法-------------------------------------------------------------------76 25 TCP坚持与保活定时器-------------------------------------------------------------------------------80 26 TCP定时器----------------------------------------------------------------------------------------------84 27 TCP终结与小结----------------------------------------------------------------------------------------88 28 API实现及相关数据结构-----------------------------------------------------------------------------91 29 API消息机制--------------------------------------------------------------------------------------------94 30 API函数及编程实例-----------------------------------------------------------------------------------97

lwip协议栈源码分析

LWIP源码分析 ----- caoxw 1 LWIP的结构 LWIP(Light weight internet protocol)的主要模块包括:配置模块、初始化模块、NetIf 模块、mem(memp)模块、netarp模块、ip模块、udp模块、icmp 模块、igmp模块、dhcp 模块、tcp模块、snmp模块等。下面主要对我们需要关心的协议处理进行说明和梳理。 配置模块: 配置模块通过各种宏定义的方式对系统、子模块进行了配置。比如,通过宏,配置了mem管理模块的参数。该配置模块还通过宏,配置了协议栈所支持的协议簇,通过宏定制的方式,决定了支持那些协议。主要的文件是opt.h。 初始化模块: 初始化模块入口的文件为tcpip.c,其初始化入口函数为: void tcpip_init(void (* initfunc)(void *), void *arg) 该入口通过调用lwip_init()函数,初始化了所有的子模块,并启动了协议栈管理进程。同时,该函数还带有回调钩子及其参数。可以在需要的地方进行调用。 协议栈数据分发管理进程负责了输入报文的处理、超时处理、API函数以及回调的处理,原型如下: static void tcpip_thread(void *arg) NetIf模块: Netif模块为协议栈与底层驱动的接口模块,其将底层的一个网口设备描述成协议栈的一个接口设备(net interface)。该模块的主要文件为netif.c。其通过链表的方式描述了系统中的所有网口设备。 Netif的数据结构描述了网口的参数,包括IP地址、MAC地址、link状态、网口号、收发函数等等参数。一个网口设备的数据收发主要通过该结构进行。 Mem(memp)模块: Mem模块同一管理了协议栈使用的内容缓冲区,并管理pbuf结构以及报文的字段处理。主要的文件包括mem.c、memp.c、pbuf.c。 netarp模块: netarp模块是处理arp协议的模块,主要源文件为etharp.c。其主要入口函数为: err_t ethernet_input(struct pbuf *p, struct netif *netif) 该入口函数通过判断输入报文p的协议类型来决定是按照arp协议进行处理还是将该报文提交到IP协议。如果报文是arp报文,该接口则调用etharp_arp_input,进行arp请求处理。 如果是ip报文,该接口就调用etharp_ip_input进行arp更新,并调用ip_input接口,将报文提交给ip层。 在该模块中,创建了设备的地址映射arp表,并提供地址映射关系查询接口。同时还提供了arp报文的发送接口。如下:

LwIP协议栈开发嵌入式网络的三种方法分析

LwIP协议栈开发嵌入式网络的三种方法分析 摘要轻量级的TCP/IP协议栈LwIP,提供了三种应用程序设计方法,且很容易被移植到多任务的操作系统中。本文结合μC/OS-II这一实时操作系统,以建立TCP服务器端通信为例,分析三种方法以及之间的关系,着重介绍基于raw API的应用程序设计。最后在ST公司STM32F107微处理器平台上验证,并给出了测试结果。 关键词LwIP协议栈;μC/OS-II;嵌入式网络;STM32F107; 随着嵌入式系统功能的多样化以及网络在各个领域的中的广泛应用,具备网络功能的嵌入式设备拥有更高的使用价值和更强的通用性。然而大部分嵌入式设备使用经济型处理器,受内存和速度限制,资源有限,不需要也不可能完整实现所有的TCP/IP协议,有时只需要满足实际需求就行。LwIP是由瑞典计算机科学研究院开发的轻量型TCP/IP协议栈,其特点是保持了以太网的基本功能,通过优化减少了对存储资源的占用。LwIP是免费、开源的,任何人可以使用,能够在裸机的环境下运行,当然设计的时候也考虑了将来的移植问题,可以很容易移植到多任务操作系统中。本文介绍了以ARM微处理器STM32F107和PHY接口DP83848为平台,构建的嵌入式系统中,采用LwIP和嵌入式操作系统μC/OS-II,使用协议栈提供的三种应用程序接口,实现嵌入式设备的网络通信功能。 1LwIP和μC/OS-II介绍 1.1 LwIP协议栈 LwIP协议是瑞士计算机科学院的Adam Dunkels等开发的一套用于嵌入式系统的开放源代码TCP/IP协议栈。LwIP含义是light weight(轻型)IP协议,在实现时保持了TCP协议的主要功能基础上减少对RAM的占用,一般它只需要几十K的RAM和40K左右的ROM 就可以运行,这使LwIP协议栈很适合在低端嵌入式系统中使用。 LwIP协议栈的设计才用分层结构的思想,每一个协议都作为一个模块来实现,提供一些与其它协议的接口函数。所有的TCP/IP协议栈都在一个进程当中,这样TCP/IP协议栈就和操作系统内核分开了。而应用程序既可以是单独的进程也可以驻留在TCP/IP进程中,它们之间利用ICP机制进行通讯。如果应用程序是单独的线程可以通过操作系统的邮箱、消息队列等,与协议栈进程通讯。如果应用程序驻留在协议栈进程中,则应用程序可以通过内部回调函数和协议栈进程通讯。 1.2 μC/OS-II实时操作系统 μC/OS-II是一个源码公开、可移植、可固化、可裁剪及占先式的实时多任务操作系统,是专门为嵌入式应用设计的实时操作系统内核,已广泛的应用在各种嵌入式系统中。 μC/OS-II是多任务系统,内核负责管理各个任务,每个任务都有其优先级,μC/OS-II 最多可以管理64个任务,其每个任务都拥有自己独立的堆栈。μC/OS-II提供了非常丰富的系统服务功能,比如信号量、消息邮箱、消息队列、事件标志、内存管理和时间管理等,这些功能可以帮助用户实现非常复杂的应用。 1.3 LwIP协议栈移植到μC/OS-II LwIP协议栈在设计的时候就考虑到了将来的移植问题,因此把所有与硬件、操作系统、编译器有关的部分都全部独立起来,形成了一个操作系统模拟层。操作系统模拟层用进程间的信号量、邮箱机制处理通信问题,而μC/OS-II是一个基于任务调度的嵌入式实时操作系

相关文档
最新文档