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

    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;

    bjsz.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的私有数据结构。

    bjsz.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的私有数据结构。
  • 相关阅读:
    [编程] 正则表达式
    [游戏] PhysX物理引擎(编程入门)
    [PHP] visitFile()遍历指定文件夹
    [D3D] 用PerfHUD来调试商业游戏
    [C,C++] 妙用0元素数组实现大小可变结构体
    [D3D] DirectX SDK 2006学习笔记1——框架
    [JS] 图片浏览器(兼容IE,火狐)
    [C#(WinForm)] 窗体间传值方法
    [ASP.NET] 提示错误:The server has encountered an error while loading an application during the processing your request
    [JS] 火狐得到文件的绝对路径(暂时的方法)
  • 原文地址:https://www.cnblogs.com/kb342/p/5054290.html
Copyright © 2020-2023  润新知