物联网中嵌入式TCP/IP协议栈的设计技巧
2011-01-23刘波涛
刘波涛
(长江大学 计算机科学学院,湖北 荆州 434023)
当前,物联网技术正受到研究者的广泛关注[1],而在物联网技术中的一个关键问题[2-4],就是要实现嵌入式设备联入Internet.嵌入式设备接入Internet的方法很多,其中一种方法[5-8]就是在嵌入式设备中实现裁剪后的TCP/IP协议栈.通用计算机系统有足够的资源支持系统在内核中实现复杂的标准TCP/IP协议栈,而这对只有有限资源的嵌入式系统来说,既不可能也没有必要.因此,针对嵌入式系统的特点,把握嵌入式TCP/IP协议栈设计的技巧就显得尤为重要.
1 嵌入式系统的特点
在理解嵌入式TCP/IP协议栈设计技巧前,需了解嵌入式系统的特点,特别是其资源较少的特点.
嵌入式系统与通用计算机系统的本质区别在于系统应用的不同,嵌入式系统是将计算机系统嵌入到对象系统中.因此,嵌入式系统与通用计算机系统相比,主要具有以下特点[9]:第一,嵌入式系统是面向特定应用的系统.嵌入式系统与通用型系统的最大区别就在于嵌入式系统大多为特定用户群设计的系统,因此它通常都具备低功耗、体积小、集成度高等特点,并且可以满足不同应用的特定需求;第二,嵌入式系统的硬件和软件都必须进行高效地设计,量体裁衣、去除冗余,这样才能更具竞争力;第三,为了提高执行速度和系统可靠性,嵌入式系统中的软件一般都固化在Flash或ROM中,而不是存储在磁盘中;第四,嵌入式系统本身不具备二次开发能力,即设计完成后用户通常不能对其中的程序功能进行修改,必须有一套开发工具和环境进行再次开发.
2 嵌入式TCP/IP协议栈设计技巧
正因为嵌入式系统不像通用计算机那样有丰富的系统资源,因此必须针对嵌入式系统的特点,来设计协议栈的实现技巧,否则协议栈实现的再好,但由于缺乏嵌入式系统的支持,也将是徒劳无功.
2.1 零拷贝
TCP/IP协议栈的工作过程如图1所示.数据以一定的单位(通称为数据包)在发送端一方由应用进程交给协议栈,数据包在协议栈从上层至下层被依次封装,即将上层的整个数据包作为下层的数据部分,再添加下层的首部,而作为新的数据包;在接收端,数据包则经由协议栈从下层至上层被依次解包:即将下层的首部剥去,并根据其内容将数据部分交付上层的协议处理,最后应用层的数据交由应用进程处理[10].
图1 TCP/IP协议栈的工作过程
为了保证协议栈中层与层之间的封装性,一般TCP/IP的实现过程中多采用层层拷贝的原则.也就是说,在封包时,将上层协议的数据包从上层协议拷贝到下层协议的数据空间中;而在解包时,将数据包从下层协议拷贝到上层协议的数据空间中.而对应于嵌入式系统,特别是资源极其有限的单片机系统及SOC片上的系统,如果在封包或解包时按上述方法来拷贝数据,则需要很多的缓冲区并且耗费大量嵌入式CPU拷贝时间.显然,这是不明智的.
因此,笔者设计的数据包封装及解封装采用了如下方法:在层与层之间交换信息时,以数据缓冲区首指针作为函数参数进行传递;在封装时,上层协议在分配空间时充分考虑以后下层协议的封装,并在缓冲区首部多分配一些必要的空间,便于下层协议在不需要从上层拷贝的情况下直接填充该层的首部.例如,HTTP协议在分配数据空间时多分配54字节用于随后的TCP、IP和Ethernet协议首部的填充;在解封装时,也将收到的原始数据包首地址直接传给向上层协议,便于上层协议获取下层协议的一些必要信息.如让TCP层知道数据包的源IP地址,以便于填充TCP传输控制块的目的IP地址字段.因此,这种方式不仅节约了系统的资源,而且会因为不需要拷贝数据包而提高了系统的处理速度.
2.2 动态内存管理
不管是零拷贝还是层层拷贝,都需要分配一定的内存来支持实现.嵌入式系统不像通用计算机那样,内存资源丰富,一般内存较少,因此更应该“精打细算”.考虑到Internet网络中接收和发送的数据包大小不一,即收到的和发送的数据包长度都不是一个定值,例如以太网数据包的长度范围值是64至1518字节,因此对内存的分配应该采用动态的方式进行管理.有如下两种方案可供选择:方案一,是每次分配一个固定长度的缓存.让该缓存能够容纳一个最大的数据包,且在该缓存中设置一个字段用来存储其有效数据的长度,显然这种方案实现简单,但是浪费了宝贵内存资源;方案二,是按需分配合适大小的缓存,而不管该缓存是用于底层接收数据还是用于上层发送数据,这种方案节约了内存资源.因此,笔者建议采用方案二来实现数据包缓存的动态分配.
需要注意的是,动态管理内存就肯定会面临“内存泄露”的风险,它最终会将系统的可用内存耗尽,最终会使嵌入式设备崩溃、停止运行.为避免这个风险的出现,嵌入式TCP/IP协议栈实现过程中,应该遵从“谁分配谁释放”的原则来进行内存的动态管理.例如,HTTP有数据包需要发送,那么在它依次调用完TCP发送模块函数、IP发送模块函数、驱动发送函数后,应该释放它申请的动态内存.
2.3 模块化设计
因为TCP/IP协议栈本身就是一个分层的软件系统,故应该按协议将协议栈实现分为若干个模块文件,让每个模块实现一层每一个协议的功能,如图2所示.在图2中,在头文件(*.H)中定义了该模块对外的接口变量及函数接口声明,而在源文件(*.C)中则定义了相关的变量和函数.要引用某模块的变量或调用其中的函数时,只需包含此模块的头文件即可.这样设计之后,分工明确,程序清晰,可读性好,便于程序的维护及修改.
图2 协议栈实现的文件目录
图3 嵌入式TCP/IP软件构成层次图
2.4 分层设计
嵌入式处理器多种多样,嵌入式设备类型丰富,厂家众多,因此,在进行嵌入式软件的设计过程中应该充分考虑这一点,实现尽可能的方便移植.为了使嵌入式TCP/IP协议栈具备良好的可移植性,以便适应多种目标平台,可将实现分为硬件无关层和硬件依赖层,如图3所示.在图3中,硬件无关层的实现使用高级语言完成,例如C语言,以方便将硬件无关层相关代码移植到所有其他能够编译C代码的硬件平台上;在硬件依赖层中使用特殊机制,例如C语言中的#define宏定义来重新定义数据类型,这样就可根据移植环境的变化来重新定义数据类型,以尽量消除系统对于具体编译器的依赖;依赖层和无关层间采用统一的接口交互信息,当硬件平台改变时,只需改动硬件依赖层的各驱动程序实现,在其接口函数名称与参数不变的情况下,硬件无关层无需改变,从而屏蔽了硬件实现的差异.
2.5 其他技巧
由于嵌入式的系统运行速度和内存容量有限,在设计时还应遵循下列原则:尽量避免使用全局变量或外部变量,全局变量或外部变量在整个程序运行期间都要占用内存,所以要尽量少用全局变量或外部变量,而尽量多地用局部变量.因此,建议采用函数参数传递的方式来共享信息;占用内存较多的变量应该定义在外部RAM中.因嵌入式处理器的内部RAM可用存储空间非常有限,占用过多的内部RAM会使嵌入式处理的硬件堆栈溢出,从而导致函数调用失败.如实现嵌入式TCP/IP协议栈中的TCP传输控制块数组较大,就应当定义在外部RAM中.
图4 测试内存泄露时输出的信息
图5 客户端动态获取服务传感器温度
3 测试结果
遵循前述设计思路,笔者在单片机W78E58B上实现了一个嵌入式TCP/IP协议栈[5],并在此基础上实现了一个嵌入式Web服务器.采用的测试方法是将该此嵌入式Web服务器与PC机在RJ-45口及串口分别对接.将嵌入式Web服务的调试信息从串口输出,并由串口精灵显示[11].图4显示的是对其进行内存泄露的测试.笔者对系统的内存块进行相关记录和统计:Len字段记录是本次分配的内存长度,UsedMemLen字段记录的是所用内存总长度,FreeMemLen字段记录的是空闲内存的长度;每一条信息表明了某个内存块分配或释放所在函数名及所处时刻.如由图4可知,每条信息对应的UsedMemLen与FreeMemLen之和是一个定值,也就是说,笔者遵照这一思路设计的嵌入式Web服务器不存在内存泄露的风险.
对嵌入式Web服务器进行相关功能测试,如图5所示.由图可知,嵌入式Web服务器能完成数据的下载及上传功能,遵照这一思路设计的嵌入式TCP/IP协议栈运行稳定可靠.
4 结论
本文总结了在实现嵌入式TCP/IP协议栈的过程中,应该注意的设计技巧.并做了相关测试,验证了该技巧的可行性.这为嵌入式设备中顺利实现嵌入式TCP/IP协议栈,从而实现物联网技术打下了坚实的基础.
[1]刘书艳.十年后,物联网风行[N].中华工商时报,2010-3-5(7).
[2]International Telecommunication Union UIT.ITU Internet Reports 2005:The Internet of Things[R].2005.
[3]王保云.物联网技术研究综述[J].电子测量与仪器学报,2009,23(12):1-7.
[4]AMARDEO C,SARMA,J G.Identities in the Future Internet of Things[J].Wireless Pers Commun 2009,49:353-363.
[5]冯翠丽,刘波涛.一种嵌入式TCP/IP协议栈的设计与实现[J].长江大学学报,2008,5(4):331-333.
[6]陈立家,焦战立,熊文龙.基于精简TCP/IP协议栈网络服务器的实现[J].武汉理工大学学报,2007,31(3):565-568.
[7]任会平,王平,徐橼.低成本嵌入式web服务器的研究[J].微计算机信息,2008,24(10):23-25.
[8]陈立家,焦战立,熊文龙.基于精简TCP/IP协议栈网络服务器的实现[J].武汉理工大学学报,2007,31(3):565-568.
[9]牛茹.基于嵌入式系统的农业数据采集传输关键技术研究[D].咸阳:西北农林科技大学,2008.
[10]刘波涛,贾菡,冯翠丽,等.嵌入式Web服务器中TCP/IP协议栈的裁剪设计[J].西安通讯学院学报,2008,7(4):28-30.
[11]刘波涛,冯翠丽,王青海,等.应用RTL8019AS的嵌入式Web服务器硬件实现[J].长江大学学报,2008,5(1):75-78.