您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > TCPIP协议栈的设计与实现【中文】
TCP/IP协议栈LwIP的设计与实现DesignandImplementationoftheLwIPTCP/IPStack[瑞典]AdamDunkels著adam@sics.se翻译焦海波marsstory99@hotmail.comSwedishInstituteofComputerScienceFebruary20,2001TCP/IP协议栈LwIP的设计与实现-1-摘要LwIP是TCP/IP协议栈的一个实现。它的目的是减少内存使用率和代码大小,使LwIP适用于资源受限系统比如嵌入式系统。为了减少处理和内存需求,LwIP使用不需要任何数据复制的经过裁剪的API。本文描述了LwIP的设计与实现。描述了在协议栈实现中以及像内存与缓冲管理这样的子系统中使用的算法和数据结构。本文还包括LwIP的参考手册以及使用LwIP的代码例子。1简介昀近几年,人们对计算机互联以及计算机无线网络支撑设备的兴趣一直不断的增长。计算机逐渐与日常使用的设备无缝集成在了一起,并且价格一直在下降。与此同时,无线网络技术比如蓝牙(Bluetooth)[HNI+98]及IEEE802.11bWLAN[BIG+97]正逐渐的出现在人们的视野中。这些新技术的出现,在许多诸如卫生保健、安全保密、运输及工业处理等领域提供了一个非常诱人的应用前景。一些像传感器一类的轻便设备可以连入互联网,以便随时随地进行监控。在过去的近十年的时间里,互联网技术被证明拥有足够的灵活性以适应不断变化的网络环境。从原始的ARPNET一类的低速网络发展起来的互联网,发展到今天,在带宽和误码率方面拥有巨大差异的光纤连接技术已经使互联网实现了巨大的跨越。相当多的以互联网为基础的应用技术被开发出来。因此,未来的无线网络——使用已经存在的互联网技术成为人们的首选。同样,互联网在全球范围内的连通性也成为了人们选择它的动机之一。一些轻便设备,比如在身体上使用的传感器,体积小而且便宜,内部的运算及存储资源有限,因此就必须在资源受限的情况下实现及处理Internet协议。本文讲述的就是在这样的条件下如何占用尽量少的资源实现一个轻型的TCP/IP协议栈,我们把该协议栈叫做LwIP。本文的章节安排是这样的:第2、3、4节对LwIP做一个总体上的描述,第5节是关于操作系统模拟层的内容,第6节是内存和缓冲区管理,第7节介绍LwIP网络接口抽象层,第8、9、10介绍IP、UDP、TCP协议的实现,第11、12节介绍如何与LwIP协议栈接口及LwIP提供的API,第13、14节将分析协议栈的实现,第15、16节提供LwIPAPI的参考手册,17、18节提供例子代码。2协议层TCP/IP协议族以分层的方式设计,每一层分别解决通讯问题的一部分。设计实现协议族——层可以提供指引,因为每一种协议可以被独立的实现。然而严格的按照分层的方式实现协议族,会因为协议层之间的通讯造成总体性能下降。要解决这个问题,协议的某些内部方面对其它协议来说应该可知,不过要注意的是,只有重要的信息在各层之间共享。大部分的TCP/IP实现在应用层和底层协议层之间进行了严格的划分,而底层协议之间却可以进行或多或少的交叉存取。在大部分的操作系统中,底层协议族作为拥有应用层进程通讯入口的操作系统内核的一部分被实现。应用程序是TCP/IP实现的抽象表示,网络通讯与进程间通讯和文件I/O没多少差别。这意味着,因为应用层不知道底层协议使用的缓冲机制,那它就不能利用这些信息去做一些事情,比如,重新使用常用数据缓冲区。同样,当应用层发送数据,在被网络代码处理之前,这些数据必须由应用层进程内存空间复制到内部缓冲区。像LwIP的目标系统这样的昀小限度系统所使用的操作系统,通常不能在内核与应用层进程之间维持一个严格的保护屏障。这就允许使用一种比较松散的通讯机制,通过共享内存翻译焦海波6/2/2006TCP/IP协议栈LwIP的设计与实现-2-的方式实现应用层与底层协议族之间的通讯。特别的,应用层能够了解底层协议使用的缓冲处理机制将使应用层可以更加有效的重复使用缓冲区。同样,既然应用层与网络代码可以使用相同的内存区,那么应用层就可以直接读写内部缓冲区,从而避免了内存复制产生的性能损失。3概览与许多其它的TCP/IP实现一样,LwIP也是以分层的协议为参照——设计实现TCP/IP。每一个协议作为一个模块被实现,同时还提供了几个函数作为协议的入口点。尽管这些协议是被独立实现的,但是有些层却不是这样,就像上面讨论的,这样做的目的是为了在处理速度与内存占用率方面提升性能。比如,当验证一个到达的TCP段的校验和并且分解这个TCP段时,TCP模块必须知道该TCP段的源及目的IP地址。因为TCP模块知道IP头的结构,因此它就可以自己提取这个信息,从而取代了通过函数调用传递IP地址信息的方式。LwIP由几个模块组成,除TCP/IP协议的实现模块外(IP,ICMP,UDP,TCP),还有包括许多相关支持模块。这些支持模块包括:操作系统模拟层(见第5节)、缓冲与内存管理子系统(见第6节)、网络接口函数(见第7节)及一组Internet校验和计算函数,LwIP还包括一个API概要说明,详见第12节.4进程模型TCP/IP协议栈的进程模型指的是采用何种方法把系统分成不同的进程。首先要说的一种进程模型是TCP/IP协议族的每一个协议作为一个独立的进程存在。这种模型,必须符合协议的每一层,同时必须指定协议之间的通讯点。虽然,这种实现方法有它的优势,比如每一种协议可以随时参与到系统运行中,代码比较容易理解,调试方便,但是它的缺点也很明显。像前文描述过的,这种进程模型并不是昀好的TCP/IP协议实现方法。同样更重要的是,数据跨层传递时将不得不产生进程切换(contextswitch)。对于接收一个TCP段来说,将会引起三次进程切换,从网络设备驱动层进程到IP进程,从IP进程到TCP进程,昀终到应用层进程。对于大部分操作系统来说,进程切换得代价可是相当昂贵的。另外一种比较普遍的方法是协议栈驻留在操作系统内核中,应用进程通过系统调用(systemcalls)与协议栈通讯。各层协议不必被严格的区分,但可以使用交叉协议分层技术。LwIP则采取将所有协议驻留在同一个进程的方式,以便独立于操作系统内核之外。应用程序既可以驻留在LwIP的进程中,也可以使用一个单独的进程。应用程序与TCP/IP协议栈通讯可以采用两种方法:一种是函数调用,这适用于应用程序与LwIP使用同一个进程的情况;另一种是使用更抽象的API。LwIP在用户空间而不是操作系统内核实现,既有优点也有缺点。把LwIP作为一个进程的主要优点是可以轻易的移植到不同的操作系统中。由于LwIP被设计运行在小系统里,通常它既不支持进程换出(swappingoutprocesses,这里译者将其翻译为进程换出,指得是操作系统将不具备运行条件的进程从内存换出到外存,以腾出内存空间,译者注)也不支持虚拟内存。因此就不会产生因LwIP进程的一部分被交换或分页到磁盘上(pagedouttodisk,即用到了虚拟内存,译者注),进程因等待磁盘激活而造成延时的问题。不过在获取一个偶然发生的服务请求之前因任务调度产生的等待延时依然是一个问题,不过在LwIP的设计中,这并没有妨碍它以后在操作系统内核实现。5操作系统模拟层为了方便LwIP移植,属于操作系统的函数调用及数据结构并没有在代码中直接使用,而是用操作系统模拟层来代替对这些函数的使用。操作系统模拟层使用统一的接口提供定时翻译焦海波6/2/2006TCP/IP协议栈LwIP的设计与实现-3-器、进程同步及消息传递机制等诸如此类的系统服务。原则上,移植LwIP,只需针对目标操作系统修改模拟层实现即可。TCP用到的定时器功能由操作系统模拟层提供。这个定时器是一个时间间隔至少为200ms的单脉冲定时器(one-shottimer,单脉冲定时器,指的是当时钟启动时,它把存储寄存器的值复制到计数器中,然后晶体的每一个脉冲使计数器减1。减至0时,产生一个中断,并停止工作,直至软件重新启动它,译者注),当时间溢出发生时就会调用一个已注册的函数。进程同步机制仅提供了信号量。即使信号量不被底层的操作系统支持也可以使用其它基本的同步方式来模拟,比如条件变量或者加锁。消息传递通过一个简单机制来实现,它使用一个被称作邮箱的抽象方法。邮箱有两种操作:邮递(post)与提取(fetch),邮递操作不会阻塞进程;相反,投递到邮箱的消息被操作系统模拟层放到队列中直至其它进程将它们取出。即使底层的操作系统本身并不支持邮箱机制,采用信号量的方式也是很容易实现的。6缓冲与内存管理通讯系统里的内存与缓冲管理模块首要考虑的是如何适应不同大小的内存需求,一个TCP段可能有几百个字节,而一个ICMP回显数据却仅有几个字节。还有,为了避免复制,应该尽可能的让缓冲区中的数据内容驻留在不能被网络子系统管理的存储区中,比如应用程序存储区或者ROM。6.1包缓冲区pbufspbuf是LwIP信息包的内部表示,为昀小限度协议栈的特殊需求而设计。pbufs与BSD实现中使用的mbufs相似。pbuf结构即支持动态内存分配保存信息包内容,也支持让信息包数据驻留在静态存储区。pbufs可以在一个链表中链接在一起,被称作一个pbuf链,这样一个信息包可以穿越几个pbufs。pbufs有三种类型:PBUFRAM、PBUFROM、PBUFPOOL。图1所示的pbuf为PBUFRAM类型,包数据存储在由pbuf子系统管理的存储区中:翻译焦海波6/2/2006TCP/IP协议栈LwIP的设计与实现-4-图1一个PBUFRAM类型的pbuf,其数据保存在由pbuf子系统管理的存储区中图2所示的pbuf是一个被链接的pbuf例子,在这个pbuf链中第一个pbuf是PBUFRAM类型,第二个是PBUFROM类型,这意味着它所拥有的数据存储在pbuf子系统不能管理的存储区:图2一个PBUFRAM类型的pbuf链接了一个数据存储在外部存储区的PBUFROM类型的pbuf第三种pbuf类型,PBUFPOOL,图3所示,它由分配自固定大小的pbufs池里的固定大小的pbufs组成。一个pbuf链可以由pbufs的不同类型组成。翻译焦海波6/2/2006TCP/IP协议栈LwIP的设计与实现-5-图3一个来自于pbuf池中的被链接的PBUFPOOLpbuf这三种类型拥有不同的使用目的。PBUFPOOL主要用于网络设备驱动层,因为分配一个pbuf的操作可以快速完成,所以非常适合用于中断处理。PBUFROM类型的pbufs用于应用程序要发送的数据放置在应用程序管理的存储区的情况。在pbuf已经移交给TCP/IP协议栈后,这些数据是不能被编辑修改的,因此这种pbuf类型主要用于数据被放置在ROM中的情况(因此名字是PBUFROM)。为PBUFROM类型的pbuf数据预置的包头存储在一个PBUFRAM类型的pbuf中,这个pbuf被链接到这个PBUFROM类型的pbuf前面,如图2所示。PBUFRAM类型的pbuf还用于应用程序发送的数据被动态生成的情况。在这种情况下。pbuf系统不仅为应用数据分配内存,还要给为这些数据预置的包头分配内存,见图1。pbuf系统不可能预先知道为这些数据预置什么样的包头,因而考虑昀坏的情况。包头大小在编译时是可配置的。其实,收到的pbufs是PBUFPOOL类型,发送出的pbufs是PBUFROM或PBUFRAM类型。pbuf的内部结构参见图1到图3。pbuf结构包括两个指针,两个长度字段,一个标志字段和一个引用计数(referencecount)。next字段是一个指向pbuf链中下一个pbuf的指针。payload指针指向pbuf中数据的开始位置。len字段包含pbuf中数据内容的长度。tot_len字段包含当前pbuf的长度与在这个pbuf链中随后的所有pbufs的len字段之和。换句话说,tot_len字段是len字段与pbuf链中随后一个pbuf的tot_len字段的和。
本文标题:TCPIP协议栈的设计与实现【中文】
链接地址:https://www.777doc.com/doc-5104675 .html