转自:http://www.cnblogs.com/MerlinJ/p/4081986.html,作为记录参考
DPDK以两种方式对外提供内存管理方法,一个是rte_mempool,主要用于网卡数据包的收发;一个是rte_malloc,主要为应用程序提供内存使用接口。本文讨论rte_mempool。rte_mempool由函数rte_mempool_create()负责创建,从rte_config.mem_config->free_memseg[]中取出合适大小的内存,放到rte_config.mem_config->memzone[]中。
本文中,以l2fwd为例,说明rte_mempool的创建及使用。
一、rte_mempool的创建
1 l2fwd_pktmbuf_pool = 2 rte_mempool_create("mbuf_pool", NB_MBUF, 3 MBUF_SIZE, 32, 4 sizeof(struct rte_pktmbuf_pool_private), 5 rte_pktmbuf_pool_init, NULL, 6 rte_pktmbuf_init, NULL, 7 rte_socket_id(), 0);
“mbuf_pool”:创建的rte_mempool的名称。
NB_MBUF:rte_mempool包含的rte_mbuf元素的个数。
MBUF_SIZE:每个rte_mbuf元素的大小。
1 #define RTE_PKTMBUF_HEADROOM 128 2 #define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) 3 #define NB_MBUF 8192
1 struct rte_pktmbuf_pool_private { 2 uint16_t mbuf_data_room_size; /**< Size of data space in each mbuf.*/ 3 };
rte_mempool由函数rte_mempool_create()负责创建。首先创建rte_ring,再创建rte_mempool,并建立两者之间的关联。
1、rte_ring_create()创建rte_ring无锁队列
1 r = rte_ring_create(rg_name, rte_align32pow2(n+1), socket_id, rg_flags);
具体步骤如下:
a、需要保证创建的队列数可以被2整除,即,count = rte_align32pow2(n + 1);
b、计算需要为count个队列分配的内存空间,即,ring_size = count * sizeof(void *) + sizeof(struct rte_ring);
struct rte_ring的数据结构如下,
1 struct rte_ring { 2 TAILQ_ENTRY(rte_ring) next; /**< Next in list. */ 3 4 char name[RTE_RING_NAMESIZE]; /**< Name of the ring. */ 5 int flags; /**< Flags supplied at creation. */ 6 7 /** Ring producer status. */ 8 struct prod { 9 uint32_t watermark; /**< Maximum items before EDQUOT. */ 10 uint32_t sp_enqueue; /**< True, if single producer. */ 11 uint32_t size; /**< Size of ring. */ 12 uint32_t mask; /**< Mask (size-1) of ring. */ 13 volatile uint32_t head; /**< Producer head. */ 14 volatile uint32_t tail; /**< Producer tail. */ 15 } prod __rte_cache_aligned; 16 17 /** Ring consumer status. */ 18 struct cons { 19 uint32_t sc_dequeue; /**< True, if single consumer. */ 20 uint32_t size; /**< Size of the ring. */ 21 uint32_t mask; /**< Mask (size-1) of ring. */ 22 volatile uint32_t head; /**< Consumer head. */ 23 volatile uint32_t tail; /**< Consumer tail. */ 24 #ifdef RTE_RING_SPLIT_PROD_CONS 25 } cons __rte_cache_aligned; 26 #else 27 } cons; 28 #endif 29 30 #ifdef RTE_LIBRTE_RING_DEBUG 31 struct rte_ring_debug_stats stats[RTE_MAX_LCORE]; 32 #endif 33 34 void * ring[0] __rte_cache_aligned; /**< Memory space of ring starts here. 35 * not volatile so need to be careful 36 * about compiler re-ordering */ 37 };
c、调用rte_memzone_reserve(),在rte_config.mem_config->free_memseg[]中查找一个合适的free_memseg(查找规则是free_memseg中剩余内存大于等于需要分配的内存,但是多余的部分是最小的),从该free_memseg中分配指定大小的内存,然后将分配的内存记录在rte_config.mem_config->memzone[]中。
d、初始化新分配的rte_ring。
1 r->flags = flags; 2 r->prod.watermark = count; 3 r->prod.sp_enqueue = !!(flags & RING_F_SP_ENQ); 4 r->cons.sc_dequeue = !!(flags & RING_F_SC_DEQ); 5 r->prod.size = r->cons.size = count; 6 r->prod.mask = r->cons.mask = count-1; 7 r->prod.head = r->cons.head = 0; 8 r->prod.tail = r->cons.tail = 0; 9 10 TAILQ_INSERT_TAIL(ring_list, r, next); // 挂到rte_config.mem_config->tailq_head[RTE_TAILQ_RING]队列中
2、创建并初始化rte_mempool
a、计算需要为rte_mempool申请的内存空间。包含:sizeof(struct rte_mempool)、private_data_size,以及n * objsz.total_size。
1 mempool_size = MEMPOOL_HEADER_SIZE(mp, pg_num) + private_data_size; 2 if (vaddr == NULL) 3 mempool_size += (size_t)objsz.total_size * n;
objsz.total_size = objsz.header_size + objsz.elt_size + objsz.trailer_size; 其中,
objsz.header_size = sizeof(struct rte_mempool *);
objsz.elt_size = MBUF_SIZE;
objsz.trailer_size = ????
b、调用rte_memzone_reserve(),在rte_config.mem_config->free_memseg[]中查找一个合适的free_memseg,在该free_memseg中分配mempool_size大小的内存,然后将新分配的内存记录到rte_config.mem_config->memzone[]中。
c、初始化新创建的rte_mempool,并调用rte_pktmbuf_pool_init()初始化rte_mempool的私有数据结构。
1 /* init the mempool structure */ 2 mp = mz->addr; 3 memset(mp, 0, sizeof(*mp)); 4 snprintf(mp->name, sizeof(mp->name), "%s", name); 5 mp->phys_addr = mz->phys_addr; 6 mp->ring = r; 7 mp->size = n; 8 mp->flags = flags; 9 mp->elt_size = objsz.elt_size; 10 mp->header_size = objsz.header_size; 11 mp->trailer_size = objsz.trailer_size; 12 mp->cache_size = cache_size; 13 mp->cache_flushthresh = (uint32_t) 14 (cache_size * CACHE_FLUSHTHRESH_MULTIPLIER); 15 mp->private_data_size = private_data_size; 16 17 /* calculate address of the first element for continuous mempool. */ 18 obj = (char *)mp + MEMPOOL_HEADER_SIZE(mp, pg_num) + 19 private_data_size; 20 21 /* populate address translation fields. */ 22 mp->pg_num = pg_num; 23 mp->pg_shift = pg_shift; 24 mp->pg_mask = RTE_LEN2MASK(mp->pg_shift, typeof(mp->pg_mask)); 25 26 /* mempool elements allocated together with mempool */ 27 mp->elt_va_start = (uintptr_t)obj; 28 mp->elt_pa[0] = mp->phys_addr + 29 (mp->elt_va_start - (uintptr_t)mp); 30 31 mp->elt_va_end = mp->elt_va_start; 32 33 RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, mp); //挂到rte_config.mem_config->tailq_head[RTE_TAILQ_MEMPOOL]队列中
d、调用mempool_populate(),以及rte_pktmbuf_init()初始化rte_mempool的每个rte_mbuf元素。
3、总结
相关数据结构的关联关系如下图:
二、rte_mempool的调用
未完,待续。。。。
错误之处,欢迎指出。
一旦你对计划感到满意,你可以直接在Copilot Workspace中运行你的代码,跳入底层的GitHub Codespace,并调整所有代码更改直到你对最终结果感到满意。在去年GitHub Universe的早期展示后,今天,我们正重新想象开发者体验的本质,推出了GitHub Copilot Workspace的技术预览版:一个原生支持Copilot的开发环境。然后剩下的就是提交你的拉取请求,运行你的GitHub Actions,进行安全代码扫描,并请求你的团队成员进行人工代码审查。而且完全可以编辑……
文章浏览阅读1.2k次,点赞6次,收藏29次。提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档。_微机原理复试常见问题
注释很详细,直接上代码……
文章浏览阅读5.6k次,点赞10次,收藏19次。Hbase 作为 NoSQL 数据库的代表,属于三驾马车之一 BigTable 的对应实现,HBase 的出现很好地弥补了大数据快速查询能力的空缺。在前面咱们也有介绍过 HBase 的数据模型,感兴趣的小伙伴可以翻看下。谈谈你对HBase数据模型的认识?HBase 的核心架构由五部分组成,分别是 HBase Client、HMaster、Region Server、ZooKeeper 以及 HDFS。它的架构组成如下图所示。下面我们对 HBase 架构组成的每一部分详细介绍一下。1.HBas_hbase架构
文章浏览阅读3.7w次,点赞171次,收藏430次。这篇博客介绍Java环境的配置,主要是安装JDK,以及path、JAVA_hOME、CLASSPAT的配置,还会介绍配置这些的原因。_windows java环境配置
文章浏览阅读2.3k次。本实验需要使用SEED互联网仿真器(已集成到docker配置文件)。启动docker容器,配置文件在/Labsetup/outputs/目录下。由于要配置很多docker容器,所以构建+启动过程会比较漫长。.随着docker启动,仿真器也随之运行,仿真器所用到的设备均为docker容器。..._bgp seed
文章浏览阅读307次。结构型模式结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。结构型模式分为以下 7 种:代理模式适配器模式装饰者模式桥接模式外观模式组合模式享元模式5.1 代理模式5.1.1 概述由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能_设计模式符合
文章浏览阅读3.6k次,点赞30次,收藏128次。本篇目录前言参数的调用方式传值调用传址调用传引用调用示例说明使用二级指针/一级指针创建链表时的对比主函数中作此调用使用二级指针创建链表使用一级指针创建链表会成功吗销毁链表时二级指针和一级指针的对比使用二级指针销毁链表使用一级指针销毁链表会成功吗总结完整代码参考来源前言在学习数据结构时,在链表初始化或者销毁链表的时候,经常使用二级指针或者一级指针的引用,这是为什么呢?同样是指向内存单元的地址,为什么就不能使用一级指针呢?使用一级指针去初始化或者是销毁链表的时候,究竟会发生什么呢?到底什么时候该用二级指针,_链表初始化为什么要二级指针
文章浏览阅读3.6k次,点赞9次,收藏24次。准备工作:1.下载专业版本的Pycharm。这里为大家提供18版本的链接: https://pan.baidu.com/s/1-GYSJvUx9JoUujPfu3EPwA密码: p283 或者直接去官网下载: https://www.jetbrains.com/pycharm/download/download-thanks.html?platform=windows2.安装并..._pycharm连接服务绘图
文章浏览阅读8.7k次。更改 MATLAB 当前文件夹 或 将其文件夹添加到 MATLAB 路径。出错_manually add this path to the matlab path
文章浏览阅读5.5k次。在AppStore中的应用越来越重视动画效果的使用,一个良好动画效果可以让两个状态之间平滑地过度,也可以利用动画吸引住用户的眼球_oc uiview animate 关键帧
文章浏览阅读8.7k次。代码错误的原因和调试方法_代码报错