




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
嵌入式操作系统VxWorks中网络协议存储池原理及实现周卫东 蔺妍 刘利强(哈尔滨工程大学自动化学院,黑龙江 哈尔滨,150001) 摘 要 本文讨论了网络协议存储池的基本原理和在嵌入式操作系统中的实现方法。为在嵌入式系统中实现TCPIP协议栈,提供了一种有效、简洁、可靠的缓冲区管理。 关键词 VxWorks; mBlk; clBlk; 网络协议存储池 VxWorks操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实时操作系统(RTOS)。它以良好的持续发展能力、高性能的内核 以及卓越的实时性被广泛的应用在通信、军事、航空、航天等高精尖技术及实时性要求极高的领域中。VxWorks操作系统有着优越的网络性能,而缓冲区的数 据拷贝是影响网络性能的主要因素。 众所周知,缓冲区在网络协议栈中有两个作用:第一,提供载体,使分组或报文可以在各协议层中流动;第二,为各级缓冲区提供空间。缓冲区的设立使得 TCPIP协议栈支持异步IO操作,异步操作对于协议栈的I0性能是非常重要的。在网络输出的过程中每一层需要在数据的首部或者尾部添加数据头和数 据尾来对数据进行封装使得接收端对应的层能够进行正确的接收,在输入的过程中每层都需要将本层的数据头和数据尾去掉而最终还原成发送端发送的数据。上述的 封装去封装和拷贝操作使得网络协议对内核的存储器管理能力提出了很多要求。这些要求包括能方便地操作可变长缓存,能在缓存头部和尾部添加数据(如低层封 装来自高层的数据),能从缓存中移去数据(如当数据包向上经过协议栈时要去掉首部),并能尽量减少这些操作所作的数据复制。1 使用netBufLib管理存储池的基本原理 网络协议存储池使用mBlk结构、clBlk结构、簇缓冲区和netBufLib提供的函数进行组织和管理。mBlk和clBlk结构为簇缓冲区 (cluster)中数据的缓冲共享和缓冲链接提供必要的信息。netBufLib例程使用mBlk和clBlk来管理cluster和引用 cluster中的数据,这些结构体中的信息用于管理cluster中的数据并且允许他们通过引用的形式来实现数据共享,从而达到数据“零拷贝”的目的。1.1 结构体mBlk和clBlk及其数据结构 mBlk是访问存储在内存池中数据的最基本对象,由于mBlk仅仅只是通过clBlk来引用数据,这使得网络层在交换数据时就可以避免数据复制。只需把一 个mBlk连到相应mBlk链上就可以存储和交换任意多的数据。一个mBlk结构体包括两个成员变量mNext和mNextPkt,由它们来组成纵横两个 链表:mNext来组成横的链表,这个链表中的所有结点构成一个包(packet);mNextPkt来组成纵的链表,这个链表中的每个结点就是一个包 (packet),所有的结点链在一起构成一个包队列,如图1所示。图1 包含两个数据包的mBlk链 结构体mBlk和clBlk的数据结构如下所示:struct mBlkM_BLK_HDR mBlkHdr; /* header */M_PKT_HDR mBlkPktHdr; /* pkthdr */CL_BLK * pClBlk; /* pointer to cluster blk */ M_BLK;struct clBlkCL_BLK_LIST clNode;/* union of next clBlk */UINT clSize;/* cluster size */int clRefCnt;/*countof the cluster */struct netPool * pNetPool; /* pointer to the netPool */ CL_BLK;/* header at beginning of each mBlk */struct mHdrstruct mBlk * mNext;/* next buffer in chain */ struct mBlk * mNextPkt;/* next chain in queue/record */char *mData; /* location of data */int mLen;/* amount of data in this mBlk */UCHAR mType;/* type of data in this mBlk */UCHAR mFlags; /* flags; see below */ M_BLK_HDR;/* record/packet header in first mBlk of chain; valid if M_PKTHDR set */struct pktHdrstruct ifnet * rcvif;/* rcv interface */int len; /* total packet length */ M_PKT_HDR;1.2 网络协议存储池的初始化 VxWorks在网络初始化时给网络协议分配存储池并调用netPoolInit()函数对其初始化,由于一个网络协议通常需要不同大小的簇,因此它的存 储池也必须包含很多簇池(每一个簇池对应一个大小的簇)。如图2所示。另外,每个簇的大小必须为2的方幂,最大可为64KB(65536),存储池的常用 簇的大小为64,128,256,512,1024比特,簇的大小是否有效取决于CL_DESC表中的相关内容,CL_DESC表是由 netPoolInit()函数调用设定的。图2 网络协议存储池初始化后的结构1.3 存储池的链接及释放 存储池在初始化后,由netPool结构组织几个下一级子池:一个mBlk池、一个clBlk池和一个cluster池。mBlk池就是由很多mBlk组 成的一条mBlk链;clBlk池就是由很多clBlk组成的一条clBlk链。cluster池由很多的更下一级cluster子池构成,每一个 cluster子池就是一个cluster链。每一个cluster链中的所有cluster的大小相同,不同链中的cluster大小不同。但要实现不 同进程访问同一簇而不需要作数据的拷贝,还需要把mBlk结构,clBlk结构和簇结构链接在一起。创建这三级结构一般要遵循这样五步: a.调用系统函数netClusterGet()预定一块簇缓冲区; b.调用系统函数netClBlkGet()预定一个clBlk结构; c.调用系统函数netMblkGet()预定一个mBlk结构; d.调用系统函数netClBlkJoin()把簇添加到clBlk结构中; e.调用系统函数netMblkClJoin()把clBlk结构添加到mBlk结构中。这样,就构成了最后的缓冲区。 在缓冲区中的数据使用完毕后要及时的释放内存,这一过程只需要调用系统函数netMblkC1ChainFree()释放存有数据的mBlk链表。例如当 数据向上层传送时,在本层中可以释放已经不再使用的mBlk链表,由于在clBlk中记录着指向本模块的mBlk的个数,虽然释放了mBlk链表,但是这 并不表示将cluster中的数据释放掉了,上层复制的链表仍然控制着这些数据,直到clBlk中的mBlk计数为0时才真正的将数据占用的簇释放掉,将 数据占用的内存空间释放、归还给系统将来使用。2 网络协议存储池与数据的封装处理 VxWorks操作系统之所以采用mBlkclBlkcluster这样的网络数据存储结构,目的就是减少数据拷贝的次数,提高网络数据的传输速率。图3 存储带有1460个字节数据的mBlk 在网络输出的过程中当从上层向下层传递数据时,下层协议需要对数据进行封装使得接收端对应的层能够进行正确的接收。下面通过实例分析网络数据的封装过程。例如要在如图3所示的mBlk链中添加IP和UDP的首部。 在mBlk链表中封装数据的方法是分配另外一个mBlk,把它放在链首,并将分组首部复制到这个mBlk。IP首部和UDP首部被放置在新mBlk的最 后,这个新mBlk就成了整个链表的首部。如果需要,它允许任何其它低层协议(例如添加以太网首部)在IP首部前添加自己的首部,不需要再复制IP和 UDP首部。在第一个mBlk中的mBlkHdr.mData指针指向首部的起始位置,mBlkHdr.mLen的值是28。在分组首部和IP首部之间有 72字节的未用空间留给以后的首部,通过适当地修改mBlkHdr.mData指针和mBlkHdr.mLen添加在IP首部的前面。注意,分组首部已经 移到新mBlk中了,分组首部必须放在mBlk链表的第一个mBlk中。在移动分组首部的同时,在第一个mBlk设置M_PKTHDR标志。在第二个 mBlk中分组首部占用的空间现在未用。最后,改变在此分组首部中的长度成员mBlkPktHdr.len,成员mBlkPktHdr.len的值是这个 分组的mBlk链表中所有数据的总长度:即所有通过mBlkHdr.mNext指针链接的mbuf的mBlkHdr.mLen值的和。本例中由于增加了 28个字节变成了1488。如图4所示。图4 添加完IP和UDP首部的mBlk 这样,当报文在协议栈中流动时,不会拷贝报文链,而只需把指向mBlk的指针通过参数传递。当报文需要进人缓冲区时,也是通过链表的指针操作将报文插入或添加到队列中。3 结论 网络协议存储池的职责有两个:为协议栈提供合适的缓冲区,如果太大会浪费系统资源,太小会影响协议栈的吞吐量;提供合适的数据结构装载网络报文,既可以使 协议栈方便地处理报文,又可以减少缓冲区拷贝的次数。减少拷贝次数不仅降低了CPU的负荷,还可以降低存储器的消耗。本文剖析了嵌入式操作系统 VxWorks中网络协议存储池的原理,实现了数据能够动态增删、但在逻辑上又呈现连续性的数据结构。能够满足在各协议层之间传递数据而不需要进行内存拷 贝。参考文献1 翟东海,李力.mbuf的实现原理剖析及其在网络编程中的应用J.计算机工程与应,2004(8):104-106.2 美DouglasEComer著张娟等译用TCPIP进行网际互联第二卷:设计、实现与内核(第三版)M北京:电子工业出版社,200105.3 美GaryRWright WRichardStevens著陆雪莹,蒋慧等译TCPIP详解卷2:实现M北京:机械工业出版社200007:10504 Wind River System Inc.VxWorks Network收稿日期:8月25日 修改日期:9月2日VxWorks任务追踪实例分析VxWorks中如果稍有不慎,就可能导致task suspend,如果运气好,shell没有被挂起,则可以通过系统的一些命令追踪一下挂起的原因。其中用到的主要命令是i、tt、ti、d等。首先从出错信息开始:0xfc8125b8 (t_Lcd): memPartFree: invalid block 0xfdfc6f38 in partition 0xfe508894.由于memPartFree了一个非法的内存块,导致了任务挂起,我们需要确定到底是哪条语句导致了这个异常的产生,可能是什么原因引起的。首先,需要通过“i”命令察看任务状态:- iNAME ENTRY TID PRI STATUS PC SP ERRNO DELAY- - - - - - - - -tExcTask excTask fdffec80 0 PEND fe3c5f50 fdffeb60 3006b 0tLogTask logTask fdffc298 0 PEND fe3c5f50 fdffc188 0 0tShell shell fdf5fa48 1 READY fe1f3afc fdf5f628 0 0t_Lcd fe392a30 fc8125b8 100 SUSPEND fe1f24b0 fc8120b8 d0003 0可以看到任务t_Lcd的状态为SUSPEND,即被挂起的状态。其他各项的含义都比较清楚,ENTRY是任务的入口函数,如果没有symbol,则直接显示地址,TID是任务的ID号,一般用任务的栈底地址表示,PC是当前的指令位置,SP是当前栈顶位置。然后通过”tt”来追溯函数调用过程:- tt t_Lcdfe3c14f4 vxTaskEntry +68 : fe392a30 ()fe392b48 initLcdComponent+2e8: fe392bdc ()fe392bec initLcdComponent+38c: fe392bfc ()fe39333c initLcdComponent+adc: lcdShowPassWord ()fe398590 lcdShowPassWord+84 : saveModifiedSetting ()fe3a3790 saveModifiedSetting+220: saveSettingValue (1)fe1fd6d0 saveSettingValue+148: fe1fc428 (0, 5, ffffffff)fe1fc888 getDeviceSettingValue+64c: fclose ()fe1aab48 fclose +ec : free ()fe1bb7d4 free +1c : memPartFree ()fe1bb2dc memPartFree +148: taskSuspend ()我们可以了解到函数的调用过程,vxTaskEntry()?-fe392a30()-fe392bdc ()-fe392bfc ()-lcdShowPassWord ()-saveModifiedSetting ()-saveSettingValue (1)-fe1fc428 (0, 5, ffffffff)-fclose ()-free ()-memPartFree ()-taskSuspend ()。其他相关信息:第一栏是发生跳转(即函数调用)后的返回地址,稍后会作详细解释,第二栏是离返回地址最近的symbol和偏移量,一般情况下会是发 起调用的那个函数的名称,除非该函数是内部函数,系统中没有symbol,第三栏是被调用的函数。再来查看一下t_Lcd任务的栈里的内容,从前面的任务信息里已经得知当前栈顶位置为fc8120b8,通过“d”命令显示该地址的内容。- d 0xfc8120b0fc8120b0: fc81 25b8 fc81 25b8 fc81 20c8 fe1f 24b0 *.%.%. .$.*fc8120c0: fe50 8894 fdfc 6f30 fc81 20e8 fe1b b2dc *.P.o0. .*fc8120d0: fdf2 6b08 0000 0100 0000 000c 0000 0000 *.k.*fc8120e0: 0000 0000 fdf1 ed80 fc81 20f8 fe1b b7d4 *. .*fc8120f0: fd9a 3538 fdf1 ed80 fc81 2108 fe1a ab48 *.58.!.H*fc812100: fd9a 3538 fc81 2108 fc81 2238 fe1f c888 *.58.!.8.*fc812110: 0000 0000 0000 0005 ffff ffff 0000 0600 *.*fc812120: 0000 000a fdf1 ed80 4230 312e 7874 6373 *.B01.xtcs*fc812130: 5f62 7566 2e69 6c32 0000 0000 0000 0000 *_buf.il2.*这里我们可以看到一些熟悉的地址,注意看最后两列,在这里可以找到”tt”中显示的第一栏地址即函数调用的返回地址。两个返回地址之间是该函数的栈空间,用于保存栈指针、局部变量或者相关寄存器的值。要具体了解这些值是怎么来的,就要用到反汇编了。反汇编通过objdump命令来实现,不同类型的cpu会有不同的可执行文件,例如objdumpppc -D vxworks xx.s反汇编的结果可能会很大,耐心等待吧。我们来看一下fclose()里调用free()的这一过程,在汇编代码里查找返回地址fe1aab48。fe1aaa5c :fe1aab44: 48 01 0c 75 bl fe1bb7b8 fe1aab48: 38 00 00 00 li r0,0bl是无条件跳转指令,free()执行完之后,应返回fe1aab48继续执行。查找fe1bb7b8,看看free被调用时干了些什么?fe1bb7b8 :fe1bb7b8: 94 21 ff f0 stwu r1,-16(r1)fe1bb7bc: 7c 08 02 a6 mflr r0fe1bb7c0: 90 01 00 14 stw r0,20(r1)fe1bb7c4: 7c 64 1b 78 mr r4,r3fe1bb7c8: 3c 60 fe 51 lis r3,-431fe1bb7cc: 38 63 88 94 addi r3,r3,-30572fe1bb7d0: 4b ff f9 c5 bl fe1bb194 fe1bb7d4: 80 01 00 14 lwz r0,20(r1)fe1bb7d8: 7c 08 03 a6 mtlr r0fe1bb7dc: 38 21 00 10 addi r1,r1,16fe1bb7e0: 4e 80 00 20 blr虽然不同类型cpu的汇编指令不同,但还是可以大致猜出其中的含义。stwu指 令将r1保存到地址(r1-16)位置,然后让将r1减去16保存到r1中,完成了保存并更新栈指针的过程;第2、3条语句将返回地址保存到r1+20的 位置;下面几条语句实际上是准备参数的过程,r3,r4一般用来保存函数的形参值,随后调用了memPartFree。从memPartFree返回后, 先从堆栈上读取返回地址,然后将栈顶下移16字节,即恢复到原来的位置,最后跳转到返回地址。对着内存内容校验一下,fclose调用free后的返回地址为fe1aab48,按照上面的分析,这个地址会被free()函数保存在r1+20 的位置,因此r1+20=fc8120fc,r1=fc8120e8,而free中将r1减去了16,所以刚进入free()时,r1应该等于 fc8120f8,这个数值会被保存在fc8120e8处,事实正是如此。这里栈内空间的利用有点交叉混杂,暂时没有弄的太明白,并且free()中没有用到过fc8120f0-fc8120f8空间的内存,推测可能是栈的大小至少为16字节所以留空了,里面的内容是历史遗留产物,是否如此,还有待进一步的研究。以上是比较通用的分析过程,本来还涉及到结合c代码的分析,跟具体的例子结合太紧密,就不赘述了,有一点可以提一下,想追溯函数调用过程中某一参数 的运行值,可能会在调用者的栈中,也可能
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 一次误会记事作文8篇
- 一次难忘的暑假旅行:记事作文(12篇)
- 非谓语动词的区别与语法功能:高一英语进阶教学
- 酒店会议培训场地服务合同
- 《数字孪生技术及应用》课件 第七章 典型应用案例
- 六十岁劳务合同范本
- 八段锦教学活动方案
- 公交公司党日活动方案
- 小白兔与大森林的神奇传说童话作文(11篇)
- 英语句型结构实践训练
- 高层建筑防火涂料施工标准方案
- 2024年重庆市初中学业水平考试生物试卷含答案
- 胎盘滞留病因介绍
- 设施设备维护保养检测制度流程
- 盐酸装卸车操作规程(3篇)
- 机械类中职学业水平考试专业综合理论考试题库(含答案)
- 业主自治组织运作研究-洞察分析
- 上海市民办文绮中学 2024-2025学年六年级上学期第二次阶段测试数学试卷
- 离婚协议书(直接打印完整版)
- 王阳明读书分享
- 学校食堂食品召回制度
评论
0/150
提交评论