Lwip 协议栈的设计与实现
(中文版)
Swedish Institute of Computer Science
February 20, 2001tcp ip协议在设计时
作者:Adam Dunkels    adam@sics.se  翻译:果农(QQ:10205001)
核桃(QQ:329147)
佳旭(QQ:3232253)
整理:佳旭(QQ:3232253)
本文为QQARM TCPIP LCD(号:10988210)版权所有未经作者许可不得用于商业用途
摘要
LWIP是TCP/IP协议栈的一种实现。LWIP的主要目的是减少存储器利用量和代码尺寸,使LWIP适合应用于小的、资源有限的处理器如嵌入式系统。为了减少处理器和存储器要求,lwIP 可以通过不需任何数据拷贝的API进行裁减。
本文叙述了lwIP的设计与实现。叙述了协议实现及子系统中所使用的算法和数据结构如存储和缓冲管理系统。还包括LWIP API的参考手册和使用LWIP 的一些代码例子。
目录
1 Introduction (1)
2 Protocol layering (1)
3 Overview (2)
4 Process model (2)
5 The operating system emulation layer (3)
6 Buffer and (3)
6.1 Packet buffers -pbufs (3)
6.2 Memory management (5)
7 .. (5)
8 IP processing (7)
8.1 Receiving packets (7)
8.2 Sending packets (7)
8.3 Forwarding packets (8)
8.4 ICMP processing (8)
9 (8)
10 (9)
10.1 Overview (9)
10.2 Data structures (10)
10.4 Queuing and transmitting data (12)
10.4.1 Silly window avoidance (13)
10.5 Receiving segments (13)
10.5.1 Demultiplexing (13)
10.5.2 Receiving data (14)
10.6 Accepting new connections (14)
10.7 Fast retransmit (14)
10.8 Timers (14)
10.9 Round-trip time estimation (15)
10.10Congestion control (15)
11 Interfacing the stack (15)
12 Application .. (16)
12.1 Basic concepts (16)
12.2 Implementation of the API (17)
13 Statistical code analysis (17)
13.1 Lines of code (18)
13.2 Object code size (19)
14 (20)
15 (21)
15.1 Data types (21)
15.1.1 Netbufs (21)
15.2 Bu®er functions (21)
15.2.1 netbuf new() (21)
15.2.2 netbuf delete() (21)
15.2.3 netbuf alloc() (22)
15.2.4 netbuf free() (22)
15.2.5 netbuf ref() (22)
15.2.6 netbuf len() (23)
15.2.7 netbuf data() (23)
15.2.8 netbuf next() (23)
15.2.9 netbuf ¯rst() (24)
15.2.10 netbuf copy() (24)
15.2.11 netbuf chain() (24)
15.2.12 netbuf fromaddr() (24)
15.2.13 netbuf fromport() (25)
16 Network connection functions (25)
16.0.14 netconn new() (25)
16.0.15 netconn delete() (25)
16.0.16 netconn type() (25)
16.0.17 netconn peer() (25)
16.0.18 netconn addr() (26)
16.0.19 netconn bind() (26)
16.0.20 netconn connect( (26)
16.0.21 netconn listen() (26)
16.0.22 netconn accept() (26)
16.0.23 netconn recv() (27)
16.0.24 netconn write() (28)
16.0.25 netconn send() (29)
16.0.26 netconn close() (30)
17 BSD socket library (30)
17.1 The representation of a socket (30)
17.2 Allocating a socket (30)
17.2.1 The socket() call (30)
17.3 Connection setup (31)
17.3.1 The bind() call (31)
17.3.3 The listen() call (32)
17.3.4 The accept() call (32)
17.4 Sending and receiving data (33)
17.4.1 The send() call (33)
17.4.2 The sendto() and sendmsg() calls (34)
17.4.3 The write() call (34)
17.4.4 The recv() and read() calls (35)
17.4.5 The recvfrom() and recvmsg() calls (36)
18 Code examples (36)
18.1 Using the API (36)
18.2 Directly interfacing the stack (39)
Bibliography (41)
1 序论
在过去的几年里,人们对计算机互连和计算机无线互连支持设备的兴趣不断的增长,计算机逐渐与日常使用的设备无缝结合,并且价格不断下降。同时,无线网络技术如Bluetooth [HNI+98] 和 IEEE 802.11b WLAN [BIG+97]不断显现。这也在一些领域譬如医疗保健、安全保卫、交通运输、加工业等引起了许多新引人入胜的情节。小的设备如传感器能被联入现有的网络如全球因特网,并可以在任何地方对其进行监控。
在过去的几年里,互联网技术证明自己具有足够的灵活性来合并不断改变的网络的环境。与当初为低速网络譬如ARPANET网而产生的互联网相比,今天的大范围连接的互联网技术在带宽和误码率方面都与原来有着巨大的差异。由于互联网的大量应用,把将来的无线互连网络应用于现有的互连网络将会给我们带来巨大的收益。并且,大面积互连的互联网也是一强劲趋势。
自从人们经常对像传感器这样的小设备有小的物理外形和便宜的价格的要求,实现一较少的处理和存储要求的互连协议就成为必须解决的问题。本文描述了一种称为LWIP的小到足以满足最小系统要求的TCP/IP协议栈的设计与实现。
本文结构如下编排:第2,3和4部分对lwIP栈作一个概述,第5部分叙述操作系统模拟层,第6部分叙述缓存和存储管理。第7部分介绍lwIP抽象的网络接口,第8,9,和10部分叙述IP,UDP,和TCP协议的实现。第11和12部分叙述怎样与lwIP进行接口并介绍lwIP API。第13和14部分分析了实现过程。最后,15部分提供了lwIP API用户参考手册,17和18部分展示了多种代码例子。
2 协议分层(Protocol layering)
TCP/IP协议被设计为分层结构,各协议层分别解决通信问题的一部份。这一分层对于协议的设计、实现可起一个指导作用,各个协议可分开实现。然而协议严格的按分层结构来实现,各层之间的通讯可能会导致总体性能的降低 [[Cla82a] 。 为克服这些问题, 协议的某些内部方面可传达给其它协议共享,但必须
注意,保证只有那些重要信息才在各层共享。
尽管底层协议或多或少可以进行交叉存取,大部分TCP/IP协议,还是在应用层协议与底层协议之间进行严格的区分。在大部分操作系统中,底层协议被作为与应用层程序具有通讯接口的操作系统内核的一部分。应用程序被看作是TCP/IP协议的抽象,网络通讯与进程间通讯或者文件I/O只有很小的差别。这意味着,因为应用程序不知道被底层协议所使用的缓冲机制,它不能利用缓冲机制对经常使用的数据进行缓冲。同样,当应用程序发送数据时,在数据被网络代码处理前,必须把这些数据从应用程序存储区被拷贝到内部缓冲区。
最小系统中使用的操作系统像lwIP的目标系统在内核和应用进程之间常常并不存在严格的保护屏障。这就允许应用程序和底层协议之间使用一种更宽松的方案,通过共享内存。特别地,应用层可以意识到底层协议所使用的缓存处理机制。因此,应用可以更有效地重用缓冲区。而且,
既然应用进程和网络代码可以使用相同的内存,应用可以直接读写内部缓存,因此节省了执行拷贝的开销。
3 总述(Overview)
正如其他TCP/IP协议的实现,分层协议的设计为LWIP的设计与实现提供一向导。每一个协议都作为一
个模块来实现,提供一些与其他协议的接口函数。尽管各层分开实现,但正如上面所讨论的,为了同时提高处理速度和内存利用两方面的性能,一些层在设计时违背这一原则。例如:当检验一接收到的TCP段(segment)的校验和(checksum)和分解TCP段时,源和目的IP 地址必须被告知TCP模块。LWIP实现时不是通过函数调用把IP地址传递给TCP,而是TCP模块通过获取IP报头的结构进而自己提取这一信息。
LWIP有几个模块组成,除了实现TCP/IP协议的各个模块(IP、ICMP、UDP、和 TCP),同时设计了许多支持模块。这些支持模块组成了操作系统模拟层(第5章)、缓冲和存储管理子系统(第6章)、网络接口函数(第7章)和一些处理因特网校验和的函数。LWIP还包括关于API的摘要(第12章)。
4 进程模型(Process model)
协议实现的过程模型以把系统划分成为不同的过程的方法进行描述。用于实现通讯协议的过程模型使每个协议作为孤立的过程运行。这种模型使用严格的协议分层,协议之间的通讯结点必须被严格定义。虽然这种方法有其诸多优势如协议能在运行时被增加,代码一般容易理解和调试,但也有不利因素。 严格的分层,正如先前所述,并不总是实现协议的最好方法。 同时,更重要的,每跨越一层,必须做一次上下文切换。这将意味着,接受一个TCP段要进行三次上下文切换:从网络接口的驱动,到IP处理,再到TCP处理,最终到应用处理。根据网络接口的设备驱动程序,对于IP过程,对于TCP过程和最后。 在大多数操作系统中一个上下文切换所花的代价都是相当昂贵的。
另一个较普通的方法是把通信协议封装在操作系统的内核。 在这种内核实现通讯协议的情况下,应用程序通过系统调用完成通讯。 通讯协议之间不严格区分,但可以使用交叉协议分层技术。
lwIP所使用的过程模型是:把所以协议封装到一个单一的过程中,从而与操作系统内核分开。应用程序可能也驻留在lwIP处理过程中,或者在单独的过程中。 TCP/IP栈和应用程序之间的通信可以通过函数调用实现,也可以通过更为抽象的API。
以上两种LWIP的实现方法各有其优缺点。把LWIP作为一个过程的主要优点是便于在不同的操作系统上移植。由于LWIP的设计目标是面向小的操作系统,这些操作系统一般不支持进程外交换(swapping out processes)或者虚拟存储,这样由于LWIP处理过程交换或者翻页到磁盘而引起的不得不等待磁盘响应造成的延迟将不再是一个问题。尽管在获得服务响应前必须等待调度仍然是一个问题,但是,在LWIP设计时,这并没有妨碍它在一操作系统内核中实现。
5 操作系统模拟层
为了使lwIP便于移植,与操作系统有关的功能函数调用和数据结构没有在代码中直接使用。而是当需要这样的函数时,操作系统模拟层将加以使用。操作系统模拟层向诸如定时器、处理同步、消息传送机制等的操作系统服务提供一套统一的接口。原则上,移植lwIP到其他
操作系统时,仅仅需要实现适合该操作系统的操作系统模拟层。
操作系统模拟层提供了由TCP使用的定时器功能。操作系统模拟层提供的定时器是一次性的定时器,当超时发生时,调用一个已注册函数至少要200ms的间隔。
进程同步机制仅提供了信号量。即使在操作系统底层中信号量不可用,也可以通过其他信号原语像条件变量或互锁来模拟。
信息传递的实现使用一种简单机制,用一种称为“邮箱”的抽象方法。邮箱做两种操作:邮寄和提取。邮寄操作不会阻塞进程;邮寄到邮箱的消息由操作系统模拟层排入队列直到另一个进程来提取它们。即使操作系统底层对邮箱机制不支持,也容易用信号量实现。
6 缓冲和存储管理
通讯系统中的存储和缓冲管理必须能够适应大小变化的缓冲区,从几百字节的包含完全大小TCP段的缓冲区到仅仅包含几个字节的短的ICMP回报。而且,为了避免拷贝它应当尽可能让缓冲区的数据内容驻留在内存中,网络子系统不管理像应用存储或ROM这样的内存。
6.1包缓冲器-pbufs
Pbuf在lwIP的内部表示一包,也是为了最小限度的使用栈这一特殊需要而设计。 Pbufs类似于用于BSD实现的mbufs。 pbuf结构既支持分配动态内存来保存包内容,也支持把包数据存储在静态存储区。Pbuf
s能在一张列表中一起被连在一起,称为一个pbuf链,这样一个包可以跨越若干个pbufs。
Pbufs具有三种类型,PBUF RAM,PBUF ROM,和PBUF POOL。图1中pbuf描绘了PBUF RAM类型,和储存的被pbuf子系统管理的数据包。图2中的pbuf是被链在一起的pbuf的一个例子,在其中链的第一个pbuf具有PBUF RAM类型(where the first pbufin the chain is of the PBUF RAM type),而第二个具有PBUF ROM类型,这意味着它具有不被pbuf系统管理的存储数据。第三种类型的pbuf ,PBUF POOL如图3所示,包括从共有的固定大小的pbufs分配的固定大小的pbufs (consists of fixed size pbufs allocated from a pool of fixedsize pbufs.)。一个pbuf链可能包括多重类型的pbufs。
三种类型有不同的使用。 PBUF_POOL主要被网络设备驱动程序使用,因为对操作系统来说分配单一的pbuf速度较快并且适合用于中断管理(suitable foruse in an interrupt handler)。当应用程序发送位于被应用程序管理的存储区的数据时,PBUF_ROM被使用。在pbuf被移交到TCP/IP 栈后,数据不能修改,因此这一pbuf类型,这类型主要用于数据位于ROM时(因此名称为PBUF_ROM )。PBUF_ROM pbuf中的数据可能会用到的头存储在PBUF_RAM pbuf中,它链接在PBUF_ROM pbuf的前面,如图2所示。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。