0x01 缘由 公司产品开发过程中,通过外包核心的抓包等技术,其中用到了内存池技术,所以研究下开源的dpdk内存池技术。学习一些基础,为将来可能使用打下基础。 0x02 概述 内存池是固定大小对象的分配器。 在DPDK中,它通过名称标识,并 使用mempool句柄存储空闲对象。 默认的mempool句柄是基于环的。 它 提供了一些其他可选服务,例如单核本地缓存一部分数据和一个对齐帮助器 以确保对象被填充以将它们均匀地扩展到所有DRAM或DDR3通道上。这个技术在Mbuf Library库中使用。(翻译:prog_guide-17.05.pdf) DPDK的内存管理与硬件关系紧密,并为应用的高效存取服务。在DPDK中,数据包的内存操作对象被抽象画为Mbuf结构,而有限的rte_mbuf结构对象则存储在内存池中。内存池使用环形缓存区来保存空闲对象。内存池在内存中的逻辑表现如下图:
文章图片
当一个网络帧被网卡接收时,DPDK的网卡驱动将其存储在一个高效的环形缓冲区中,同时在Mbuf的环形缓冲区中创建一个Mbuf对象。当然,两个行为都不涉及向系统申请内存,这些内存已经在内存池被穿件时就申请好了。Mbuf对象被创建好后,网卡驱动根据分析出的帧信息将其初始化,并将其和实际帧逻辑相连。对网络帧的分析处理都集中于Mbuf,仅在必要的时候访问实际网络帧。这就是内存池的双环形缓存区结构。 为增加对Mbuf的访问效率,内存池还拥有内存通道/Rank对齐辅助方法。内存池还允许用户设置核心缓存区大小来调节环形内存块的读写频率。 实践证明,在内存对象之间补零,以确保每个对象和内存的一个通道和Rank起始处对齐,能大幅减少未命中的发生概率且增加存取效率。在L3转发和流分类应用中尤为如此。内存池以更大内存占有量的代价来支持此项技术。在创建一个内存池时,用户可选择是否启用该技术。 多核CPU访问同一个内存池或者同一个环形缓存区时,因为每次读写时都要进行CAS操作来保证期间的数据未被其他核心修改,所以存取效率较低。DPDK的解决方法是使用单核本地缓存一部分数据,实时对环形缓存区进行块读写操作,以减少访问环形缓存区的次数。单核CPU对自己缓存的操作无须中断,访问效率因而得到提高。当然,这个方法也并非全是好处:该方法要求每个核CPU都有自己私用的缓存(大小可有用户定义,也可以为0,或禁用该方法),而这些缓存在绝大部分时间都没有能得到100%运用,因此一部分内存空间将被浪费。(摘录:深入浅出 DPDK) 0x03 API描述 rte_mempool_create 创建一个内存池 rte_mempool_get 可以获得池中的元素,其实就是从ring取出可用元素的地址。 rte_mempool_put 可以释放元素到池中。 rte_mempool_in_use_count 查看池中已经使用的元素个数 rte_mempool_avail_count 查看池中可以使用的元素个数 0x04 l2fwd使用 step 1: 创建内存池
/* create the mbuf pool */
l2fwd_pktmbuf_pool =
rte_mempool_create("mbuf_pool", NB_MBUF,
MBUF_SIZE, 32,
sizeof(struct rte_pktmbuf_pool_private),
rte_pktmbuf_pool_init, NULL,
rte_pktmbuf_init, NULL,
rte_socket_id(), 0);
if (l2fwd_pktmbuf_pool == NULL)
rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
step 2: 内存池与网卡队列绑定
/* init one RX queue */
fflush(stdout);
ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
rte_eth_dev_socket_id(portid),
NULL,
l2fwd_pktmbuf_pool);
if (ret < 0)
rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n",
ret, (unsigned) portid);
0x05 详细原理 详细原理请参考前辈们的解读,再此不做深入探究。传送:http://blog.csdn.net/xy010902100449/article/details/47283017 http://blog.csdn.net/chen98765432101/article/details/70248559 http://www.cnblogs.com/yhp-smarthome/p/6687175.html
推荐阅读
- Linux|109 个实用 shell 脚本
- linux笔记|linux 常用命令汇总(面向面试)
- Linux|Linux--网络基础
- linux|apt update和apt upgrade命令 - 有什么区别()
- linux|2022年云原生趋势
- Go|Docker后端部署详解(Go+Nginx)
- 开源生态|GPL、MIT、Apache...开发者如何选择开源协议(一文讲清根本区别)
- GitHub|7 款可替代 top 命令的工具