1、第九章 协议处理本章主要内容 缓冲区管理 常规协议( TCP/UDP)处理: TCP头部预测 分片重组 在极高的 数据速率 下, 协议处理的任何一个 环节都不能忽视 对于大量小包来说, 主要开销 是 一般性协议处理而不是数据 处理9.1 缓冲区管理 数据包到达后,首先要分配一个缓冲区 操作系统 需 提供 分配和释放缓冲区 的服务,包括: 管理空闲缓冲区 为数据包找到合适大小的缓冲空间 如果多个 连接或用户共享 一个缓存 空间, 还需提供某种形式的 公平分配 困难: 包缓冲区分配必须实时完成9.1.1 缓冲区分配 经典的 BSD UNIX包缓冲区 实现 称为 mbufs: 使用一个缓冲区链来存放
2、 一个包,每个缓冲区为一段连续的存储空间 BSD定义了三 种大小的缓冲区 : 100字节、 108字节、 2048字节( 称 cluster) Mbufs设计的出发点: 使用一个缓冲区链来存放一个包: 允许动态扩展包的缓冲空间 ,适应各种协议栈 定义不同大小的缓冲区:充分利用内存空间 缺点:访问数据和拷贝数据的开销大Sk_buff Linux操作系统 的包缓冲区实现是 sk_buff: 每个包缓冲区都是一块连续地址空间, 提前 为路径上需要添加的各种 协议 头预留了空间 Sk_buff的设计原则是 用空间换时间 : 使用连续地址空间的缓冲区,实现简单,时间开销小 包缓冲区必须 满足最 大 包
3、长,有时 会浪费空 间如何为不同大小的包分配缓冲区? 给每个包分配最大长度的包缓冲区是一种浪费 较好的方法是按需分配内存: 当一个包到来时,为其分配一块合适大小的缓存空间 动态分配内存的 困难: 用户 会 在不同的时间释放缓冲区,导致 内存中 出现 许多不连续的、 大小 不同的空闲区域 教科书上的标准算法 (如 First-Fit、 Best-Fit)可以搜索到合适大小的空闲区域,但速度太慢高速包缓冲区分配器 开发高速网络软件的工程师通常会考虑以下三种内存分配器: 隔离池分配器( Segregated Pool Allocator) Linux分配器( Linux Allocator) 批量分
4、配器( Batch Allocator)隔离池分配器 随 BSD 4.2 UNIX发 布 ,称 Kingsley malloc() 将存储 空间划分 成 一组隔离的内存池 ,同一个内存池中 的 缓冲区大小相同,为 2的幂次 内存 请求被取整到最近的 缓冲区大小 , 从 相应的 内存池链表头部取一个空闲缓冲区分配 若对应的 内存 池空间不足,分配失败 可能有内存空间浪费,但实现简单Linux分配器 Linux分配器 最初由 Doug Lea实现, 称 为dlmalloc() 内存 被 划分成 128个内存池 : 前 64个内存池,缓冲区大小分别为 16、 24、 32、 、 512字节(按 8字节步长增加) 后 64个内存池,大小为 2的幂次 分配器会 合并相邻的空闲缓冲区,放入合适的缓冲池中 Lea分配器比 Kingsley分配器 使用内存更高效,但实现更复杂批量分配器 分配器 一次性向系统请求一大块内存,用来作为包缓冲区 池(批量的含义) 当一个内存块正在使用时,后台创建另一个空闲内存块 分配器 在当前 内存块 上 采用顺序分配 : 一个指针指向上一次分配结束的位置,新的内存请求总是从当前位置开始分配 一个内存块用完,立即转移到另一个空闲内存块上