rte_mempool内存管理

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、总结

相关数据结构的关联关系如下图:

时间: 2024-12-05 06:03:25

rte_mempool内存管理的相关文章

DPDK内存管理-----(二)rte_mempool内存管理

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的创建及使

[转]dpdk内存管理

转自 dpdk内存管理 --初始化(hugepage)    https://www.cnblogs.com/MerlinJ/p/4074391.html dpdk内存管理--rte_mempool内存管理  https://www.cnblogs.com/MerlinJ/p/4081986.html dpdk内存管理-- rte_malloc内存管理   https://www.cnblogs.com/MerlinJ/p/4092432.html 原文地址:https://www.cnblog

DPDK内存管理(1)

1 前言 DPDK将利用hugepage预留的物理内存统一的组织管理起来,然后以库的方式对外提供使用的接口.下图展示了DPDK中内存有关的模块的相互关系. rte_eal            是统一的组织管理者(当然rte_eal不只是做内存的工作) rte_malloc       对外提供分配释放内存的API,分配的内存都是rte_eal中管理的内存 rte_ring          提供无锁队列,他之间使用了rte_eal管理的内存 rte_mempool  利用rte_eal中的内存

DPDK内存管理(1)(转)

1 前言 DPDK将利用hugepage预留的物理内存统一的组织管理起来,然后以库的方式对外提供使用的接口.下图展示了DPDK中内存有关的模块的相互关系. rte_eal            是统一的组织管理者(当然rte_eal不只是做内存的工作) rte_malloc       对外提供分配释放内存的API,分配的内存都是rte_eal中管理的内存 rte_ring          提供无锁队列,他之间使用了rte_eal管理的内存 rte_mempool  利用rte_eal中的内存

linux内存管理

一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程序可调用它.假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段.     2) 数据段:存放已初始化的全局变量.静态变量(包括全局和局部的).常量.static全局变量和static函数只能在当前文件中被调用.     3) 未初始化数据区(uninitializeddata s

Block内存管理实例分析

在ios开发中,相信说道block大家都不陌生,内存管理问题也是开发者最头疼的问题,网上很多讲block的博客,但大都是理论性多点,今天结合一些实例来讲解下. 存储域 首先和大家聊聊block的存储域,根据block在内存中的位置,block被分为三种类型: NSGlobalBlock NSStackBlock NSMallocBlock 从字面意思上大家也可以看出来 NSGlobalBlock是位于全局区的block,它是设置在程序的数据区域(.data区)中. NSStackBlock是位于

Obstack是C标准库里面对内存管理的GNU扩展

Obstack介绍 Obstack初始化 在Obstack中申请对象 释放对象 申请growing object 获取Obstack状态 数据对齐 以下是来自wiki对obstack的介绍: Obstack是C标准库里面对内存管理的GNU扩展(实际上就是GNU C library了).Obstack===Object stack.没错,Obstack就是一个栈,栈里面的元素是对象object(不是面向对象的对象哦,这里的对象单指数据元素).这些数据是动态的,也就是使用的是动态内存.这种内存管理技

OC内存管理

OC内存管理 一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等. 管理范围:任何继承NSObject的对象,对其他的基本数据类型无效. 本质原因是因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也

39-oc集合中对象的内存管理

集合中对象的内存管理 集合的内存管理原则是什么 当把一个对象添加到集合中时,这个对象会做了一次retain操作,计数器会+1 当一个集合被销毁时,会对集合里面的所有对象做一次release操作,计数器会-1 当一个对象从集合中移除时,会对这个对象做一次release操作,计数器会-1 集合方法的普遍规律是什么 如果方法名是add\insert开头,那么被添加的对象,计数器会+1 如果方法名是remove\delete开头,那么被移除的对象,计数器-1