| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> TCP/IP协议栈Lwip的设计与实现:之四 -> 正文阅读 |
|
[系统运维]TCP/IP协议栈Lwip的设计与实现:之四 |
接上文:TCP/IP协议栈Lwip的设计与实现:之三_龙赤子的博客-CSDN博客 目录 11.协议栈接口可以有两种方式使用TCP/IP协议栈提供的服务,或者直接调用TCP和UDP模块提供的函数,或者使用LWIP的API,这些API会在下一节讲述。 TCP和UDP模块对网络服务提供一个基本的接口。该接口基于回调函数,因此使用接口的应用程序就不能以连续的方式操作。这会使得应用程序很难编写并且代码也很难理解。为了接收数据,应用程序注册一个栈的回调函数,这个回调函数与一个特定的连接关联,当链路中有数据包到达,栈就会调用该回调函数。 更进一步,直接使用TCP和UDP模块接口的应用程序必须(至少部分)和TCP/IP栈存在于同一个进程中。这是因为回调函数不能穿过进程边界被调用的事实。这既有好处也有坏处。好处就是因为应用程序和TCP/IP栈在同一个进程空间,当发送和接收数据包时不需要进行上下文的切换,主要的缺点在于应用程序不能将它包含进任何较长的运行时计算中,因为TCP/IP处理不能与计算并行进行,因此会降低通信性能。这可以通过将应用程序分裂为两部分来克服,一部分处理通信,一部分处理计算。处理通信的部分将存在于TCP/IP进程中,主要进行计算的部分成为一个独立的进程。在下一节出现的LWIP API提供一个结构化的方式按照上述方式分解应用。 12.应用程序接口由于BSD提供的socket API的高度抽象,它并不适合于在一个很小的TCP/IP的实现中使用。特别的,BSD sockets要求将要发送的数据从应用程序拷贝一份到TCP/IP协议栈的内部缓冲区。进行数据拷贝的原因在于应用程序和TCP/IP协议栈通常存在于不同的保护区域中。大多数情况下,应用程序是一个用户进程,而TCP/IP协议栈则存在于操作系统内核中。通过避免额外的数据拷贝,API的性能可以得到极大的改善[ABM95]。同样,为了数据拷贝,额外的内存需要被分配,每个数据包使用双份的有效内存量。 LWIP API是为LWIP设计的,并利用对LWIP内部结构的了解来实现高效率。LWIP API与BSD API是非常相似的,但是操作在一个稍低的层次上。该API并不要求在应用程序和TCP/IP协议栈之间进行数据的拷贝,因为应用程序可以直接的操作内部缓冲区。 因为BSD socket容易理解,并且已经有很多程序基于它所写,所以有一个与BSD socket兼容的层次是有利的。17部分列出使用LWIP API重写的BSD socket。15部分是LWIP API的参考手册。 12.1基本概念从应用程序的观点来看,BSD socket API中的数据搬运是在连续的存储区中完成的。这对应用程序员来说是比较便利的,因为应用程序中数据的操作通常是在这样的连续的内存块中完成的。在LWIP中使用这种类型的机制并不有利,因为LWIP通常是在缓冲区中获取数据的,在这里数据被分割成较小的内存块。因此,数据在被传给应用程序之前应当先被拷贝进一个连续的内存区域。这将不仅浪费处理时间也浪费内存。所以,LWIP允许应用程序直接操作被分割的缓冲区中的数据来避免额外的数据复制。 LWIP API使用一个类似BSD socket API的抽象连接,尽管如此,它们的不同之处仍然非常值得注意;对于一个使用BSD socket API的应用程序而言,不需要意识到普通文件和网络连接的区别,而对于使用LWIP API的应用程序来说,则必须要意识到它正在使用一个网络连接这一实际情况。 网络数据以缓冲区的形式被接收,在这里,数据被分割进小的内存块。因为很多应用希望操作连续存储区的数据,所以就存在一个来实现这一便利的函数,该函数将分片的缓冲区数据拷贝到连续的内存区。 根据数据是通过TCP连接还是作为UDP数据报的方式发送,数据的发送过程是不同的。对于TCP,通过给output函数传送一个指向连续存储区的指针完成。TCP/IP协议栈将把数据分割成合适大小的包并将它们加入传输队列。当发送UDP数据报时,应用程序将明确的分配一个缓冲区并用数据来填充它。当output函数被调用时,TCP/IP协议栈就会立即发送该数据报。 12.2 API的实现由于TCP/IP栈的进程模型,API的实现被分为两部分。如图12所示,部分API作为连接到应用程序的库来实现,另一部分是在TCP/IP进程中实现的。这两部分使用操作系统仿真层提供的工序间通信(IPC)机制来进行通信。当前的实现使用如下三个IPC机制: 1.共享内存 2.消息传递 3.信号量 由于这些类型的IPC被操作系统层支持,它们就不再需要被下面的操作系统来直接支持。因为操作系统并不天生支持它们,因此操作系统仿真层仿真实现它们 通常设计时使用的原则是让尽可能多的工作在应用进程中完成而不是在TCP/IP进程来做。这一点是重要的,因为所有的进程使用TCP/IP进程进行它们的TCP/IP通信。抑制与应用相连的API部分的代码覆盖区并不如此重要,这部分代码可以在进程间共享,即使共享库不被操作系统支持,其代码存储在ROM中。嵌入式系统通常带有大量的ROM,而处理能力却不足。 缓冲管理被定位于API实现的库部分。缓冲区的创建、复制以及释放都在应用进程中。共享内存被用来在应用进程和TCP/IP进程间传送缓冲数据。应用程序通信中所使用的缓冲数据类型是一个抽象的pbuf数据类型。 缓冲区使用与分配内存形成对照的参考内存,仍然使用共享内存进行传送。因此要能使之工作,则在进程间共享参考内存必须成为可能。使用LWIP的嵌入式系统所使用的操作系统通常被设想为没有实现任何形式的存储保护,所以实现这一点没有问题。 获取网络连接的函数作为API的一部分实现,这部分API是在TCP/IP进程中实现的API。运行于应用进程中的API的函数通过使用一个简单的通信协议传送一个消息给TCP/IP进程中的API实现,这个消息包括应当完成的操作类型以及操作所需的任何参数。操作则被TCP/IP进程中的API实现执行,返回值通过消息传递发送给应用进程。 13.代码统计分析这部分分析LWIP的代码,包括编译后的目标代码尺寸和原代码行数等方面。代码已经在两种架构的处理器上编译: 1.Intel Pentium III处理器,今后作为Intel x86处理器提及。使用gcc 2.95.2在FreeBSD4.1下编译,编译优化选项是打开的。 2.6502处理器[Nab,Zak83]。使用cc65 2.5.5[VB]编译,编译优化选项也是打开的。 Intel x86有7个32位的寄存器并使用32位的指针。6502主要用于嵌入式系统,有一个8位累加器以及2个8位索引寄存器,并使用16位指针。 13.1代码行数表一总结了LWIP源代码的行数,图13展示了它们之间比例关系。Support functions项目包括缓冲和内存管理的函数以及计算Internet校验和的函数。检验和函数是用通用C来实现算法的,当实际配置的时候应该用处理器相关的实现来代替。API项包括了与应用相连的API和与TCP/IP栈相连的两部分API。操作系统仿真层不包括在该分析中,因为它的大小随下层的操作系统的不同而有很大的变化,因此也就没有比较的意义。 由于目的是进行比较,所以所有的注视和空白行都从原文件删除了。同样,该比较中也没有包括头文件。我们可以看到,TCP远远大于其他协议的实现,API和支持函数和起来的大小与TCP相当。 13.2目标代码大小表2总结了相对于Intel x86的编译后目标代码的尺寸,图14则展示了它们的相对比例关系。我们可以看到项目的顺序与表一有所不同。这里,API大于支持函数项目,尽管支持函数项目有更多的代码。我们也可以看出TCP占据了编译代码的48%而仅仅占源代码的42%。对TCP模块的汇编输出的检查展现了产生此种现象的一个可能的原因,TCP模块包含有大量的非关联化指针,这扩大了汇编代码,因此增加了目标代码的大小。因为每个函数中许多指针重复关联于两倍或三倍,这可以通过修改源代码来优化以达到这些指针仅仅关联一次并被放进一个本地变量中。如此做法在减少编译代码的大小的同时,也就使用了更多的RAM来作为本地变量的空间,这些RAM被分配于协议栈上。 表3展示了当在6502上进行编译后的目标代码的大小,图14则是比例关系的展现。我们可以看到,TCP、API以及支持函数几乎都是Intel x86下目标代码的两倍大小,而IP、UDP和ICMP则近似是同样大小。我们也可以看出支持函数项目大于API,与表2相反。但是API与支持函数之间在尺寸上的差别要小一点。 TCP模块尺寸的增加是因为6502天生不支持32位整数,因此每个32位操作都被编译器扩大成许多行的汇编代码。TCP序列号是32位的整型并且TCP模块有大量的序列号计算。 这里的TCP大小可以和其他TCP/IP栈的TCP模块的大小进行比较,比如FreeBSD4.1上的流行的BSD TCP/IP栈以及源于Linux2.2.10的独立的TCP/IP栈。这两个都是基于Intel x86并使用gcc编译的,优化选项同样是打开的。LWIP中TCP的实现大小接近于6600字节,FreeBSD4.1中TCP实现的目标代码大小大概是27000字节,是LWIP的4倍。在Linux2.2.10中更大,为39000字节,大概是LWIP的6倍。LWIP和其他两种实现的代码尺寸上的巨大差别产生于FreeBSD和Linux的实现中都包含了像SACK[MMFR96]这样更多的TCP特性以及部分BSD socket API的实现。 之所以不对IP部分的实现进行比较是因为在FreeBSD和Linux的IP实现中包含了更多的特性。举个例子,FreeBSD和Linux在它们的IP实现中都包含支持防火墙和通道,另外,它们的实现中支持动态路由表,这在LWIP中没有实现。 LWIP API大概是LWIP的六分之一,因为LWIP可以被使用而不用包含API,在将LWIP配置在只有很小代码存储器的系统上时,这一部分可以被忽略,也就是不用。 14.性能分析LWIP的性能无论是RAM使用还是代码效率在这篇论文中都没有正式的测试,这已经在将来的工作中考虑了。尽管如此,简单的测试还是进行了。结果表明,运行一个简单的HTTP/1.0服务的LWIP能够满足至少10个同时的WEB页面请求,而RAM的使用不足4KB。在那些测试中,仅仅被协议、缓冲系统以及应用程序使用的内存被考虑,因此,设备驱动使用的内存应当添加到上面的数据中,也就是说实际上不仅仅是小于4KB的RAM被使用。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 12:06:09- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |