TCP/IP 协议栈 LwIP 的设计与实现 - 1 -
摘要
LwIP 是 TCP/IP 协议栈的一个实现。它的目的是减少内存使用率和代码大小,使 LwIP 适
用于资源受限系统比如嵌入式系统。为了减少处理和内存需求,
LwIP 使用不需要任何数据
复制的经过裁剪的
API。
本文描述了
LwIP 的设计与实现。描述了在协议栈实现中以及像内存与缓冲管理这样的
子系统中使用的算法和数据结构。本文还包括
LwIP 的参考手册以及使用 LwIP 的代码例子。
1 简介
最近几年,人们对计算机互联以及计算机无线网络支撑设备的兴趣一直不断的增长。计
算机逐渐与日常使用的设备无缝集成在了一起,并且价格一直在下降。与此同时,无线网络
技术比如蓝牙(Bluetooth)[HNI+98]及 IEEE 802.11b WLAN[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 节提供 LwIP API 的参考手
册,17、18 节提供例子代码。
2 协议层
TCP/IP 协议族以分层的方式设计,每一层分别解决通讯问题的一部分。设计实现协议
族——层可以提供指引,因为每一种协议可以被独立的实现。然而严格的按照分层的方式实
现协议族,会因为协议层之间的通讯造成总体性能下降。要解决这个问题,协议的某些内部
方面对其它协议来说应该可知,不过要注意的是,只有重要的信息在各层之间共享。
大部分的 TCP/IP 实现在应用层和底层协议层之间进行了严格的划分,而底层协议之间
却可以进行或多或少的交叉存取。在大部分的操作系统中,底层协议族作为拥有应用层进程
通讯入口的操作系统内核的一部分被实现。应用程序是
TCP/IP 实现的抽象表示,网络通讯
与进程间通讯和文件 I/O 没多少差别。这意味着,因为应用层不知道底层协议使用的缓冲机
制,那它就不能利用这些信息去做一些事情,比如,重新使用常用数据缓冲区。同样,当应
用层发送数据,在被网络代码处理之前,这些数据必须由应用层进程内存空间复制到内部缓
冲区。
像 LwIP 的目标系统这样的最小限度系统所使用的操作系统,通常不能在内核与应用层
进程之间维持一个严格的保护屏障。这就允许使用一种比较松散的通讯机制,通过共享内存
翻译 焦海波 6/2/2006
ARM技术论坛推荐资料 www.armjishu.com
TCP/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 协议实现方法。同样更重要的是,
数据跨层传递时将不得不产生进程切换(context switch)。对于接收一个 TCP 段来说,将会
引起三次进程切换,从网络设备驱动层进程到 IP 进程,从 IP 进程到 TCP 进程,最终到应
用层进程。对于大部分操作系统来说,进程切换得代价可是相当昂贵的。
另外一种比较普遍的方法是协议栈驻留在操作系统内核中,应用进程通过系统调用
(system
calls)与协议栈通讯。各层协议不必被严格的区分,但可以使用交叉协议分层技术。
LwIP 则采取将所有协议驻留在同一个进程的方式,以便独立于操作系统内核之外。应
用程序既可以驻留在 LwIP 的进程中,也可以使用一个单独的进程。应用程序与 TCP/IP 协
议栈通讯可以采用两种方法:
一种是函数调用,这适用于应用程序与 LwIP 使用同一个进程
的情况;另一种是使用更抽象的 API。
LwIP 在用户空间而不是操作系统内核实现,既有优点也有缺点。把 LwIP 作为一个进
程的主要优点是可以轻易的移植到不同的操作系统中。由于 LwIP 被设计运行在小系统里,
通常它既不支持进程换出(
swapping out processes,这里译者将其翻译为进程换出,指得是操作系统将
不具备运行条件的进程从内存换出到外存,以腾出内存空间,译者注
)也不支持虚拟内存。因此就不
会产生因 LwIP 进程的一部分被交换或分页到磁盘上(
paged out to disk,即用到了虚拟内存,译者
注
),进程因等待磁盘激活而造成延时的问题。不过在获取一个偶然发生的服务请求之前因
任务调度产生的等待延时依然是一个问题,不过在 LwIP 的设计中,这并没有妨碍它以后在
操作系统内核实现。
5 操作系统模拟层
为了方便 LwIP 移植,属于操作系统的函数调用及数据结构并没有在代码中直接使用,
而是用操作系统模拟层来代替对这些函数的使用。操作系统模拟层使用统一的接口提供定时
翻译 焦海波 6/2/2006
ARM技术论坛推荐资料 www.armjishu.com
TCP/IP 协议栈 LwIP 的设计与实现 - 3 -
器、进程同步及消息传递机制等诸如此类的系统服务。原则上,移植 LwIP,只需针对目标
操作系统修改模拟层实现即可。
TCP 用到的定时器功能由操作系统
模拟层提供。这个定时器是一个时间间隔至少为
200ms 的单脉冲定时器(
one-shot timer,单脉冲定时器,指的是当时钟启动时,它把存储寄存器的值复
制到计数器中,然后晶体的每一个脉冲使计数器减 1。减至 0 时,产生一个中断,并停止工作,直至软件
重新启动它,译者注
),当时间溢出发生时就会调用一个已注册的函数。
进程同步机制仅提供了信号量。即使信号量不被底层的操作系统支持也可以使用其它基
本的同步方式来模拟,比如条件变量或者加锁。
消息传递通过一个简单机制来实现,它使用一个被称作邮箱的抽象方法。邮箱有两种操
作:邮递(post)
与提取(fetch),邮递操作不会阻塞进程;相反,投递到邮箱的消息被操
作系统模拟层放到队列中直至其它进程将它们取出。即使底层的操作系统本身并不支持邮箱
机制,采用信号量的方式也是很容易实现的。
6 缓冲与内存管理
通讯系统里的内存与缓冲管理模块首要考虑的是如何适应不同大小的内存需求,一个
TCP 段可能有几百个字节,而一个 ICMP 回显数据却仅有几个字节。还有,为了避免复制,
应该尽可能的让缓冲区中的数据内容驻留在不能被网络子系统管理的存储区中,比如应用程
序存储区或者 ROM。
6.1 包缓冲区 pbufs
pbuf 是 LwIP 信息包的内部表示,为最小限度协议栈的特殊需求而设计。pb
ufs 与 BSD
实现中使用的 mbufs 相似。pbuf 结构即支持动态内存分配保存信息包内容,也支持让信息
包数据驻留在静态存储区。pbufs 可以在一个链表中链接在一起,被称作一个 pbuf 链,这样
一个信息包可以穿越几个 pbufs。
pbufs 有三种类型:PBUF RAM、PBUF ROM、
PBUF POOL。图 1 所示的 pbuf 为
PBUF RAM 类型,包数据存储在由 pbuf 子系统管理的存储区中:
翻译 焦海波 6/2/2006
ARM技术论坛推荐资料 www.armjishu.com
TCP/IP 协议栈 LwIP 的设计与实现 - 4 -
图 1 一个 PBUF RAM 类型的 pbuf,其数据保存在由 pbuf 子系统管理的存储区中
图 2 所示的 pbuf 是一个被链接的 pbuf 例子,在这个 pbuf 链中第一个 pbuf 是 PBUF RAM 类
型,第二个是 PBUF ROM 类型,这意味着它所拥有的数据存储在 pbuf 子系统不能管理的存
储区:
图 2 一个 PBUF RAM 类型的 pbuf 链接了一个数据存储在外部存储区的 PBUF ROM 类型的 pbuf
第三种 pbuf 类型,PBUF POOL,图 3 所示,它由分配自固定大小的 pbufs 池里的固定大小
的 pbufs 组成。一个 pbuf 链可以由 pbufs 的不同类型组成。
翻译 焦海波 6/2/2006
ARM技术论坛推荐资料 www.armjishu.com