DPDK内存管理一:结构体

DPDK的内存管理工作主要分布在几个大的部分:大页初始化与管理,内存管理。使用大页可以减少页表开销,是为了尽量减少TBL miss导致的性能损失。基于大页,DPDK又进一步细化管理这部分内存,使得分配,回收更加方便。
大页内存的基本原理在前面已经解释过了,这里就不在继续。

首先熟悉一下DPDK 内存相关的结构体:

  • struct rte_mem_config(rte_eal_memconfig.h)
    这个数据结构mmap 到文件/var/run /.rte_config中,主/从进程通过这个文件访问实现对这个数据结构的共享。
    在每个程序内,使用rte_config .mem_config 访问这个结构。
/**
 * the structure for the memory configuration for the RTE.
 * Used by the rte_config structure. It is separated out, as for multi-process
 * support, the memory details should be shared across instances
 */
struct rte_mem_config {
    volatile uint32_t magic;   /**< Magic number - Sanity check. */

    /* memory topology */
    uint32_t nchannel;    /**< Number of channels (0 if unknown). */
    uint32_t nrank;       /**< Number of ranks (0 if unknown). */

    /**
     * current lock nest order
     *  - qlock->mlock (ring/hash/lpm)
     *  - mplock->qlock->mlock (mempool)
     * Notice:
     *  *ALWAYS* obtain qlock first if having to obtain both qlock and mlock
     */
    rte_rwlock_t mlock;   /**< only used by memzone LIB for thread-safe. */
    rte_rwlock_t qlock;   /**< used for tailq operation for thread safe. */
    rte_rwlock_t mplock;  /**< only used by mempool LIB for thread-safe. */

    uint32_t memzone_cnt; /**< Number of allocated memzones */

    /* memory segments and zones */
    struct rte_memseg memseg[RTE_MAX_MEMSEG];    /**< Physmem descriptors. */
    struct rte_memzone memzone[RTE_MAX_MEMZONE]; /**< Memzone descriptors. */

    struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */

    /* Heaps of Malloc per socket */
    struct malloc_heap malloc_heaps[RTE_MAX_NUMA_NODES];

    /* address of mem_config in primary process. used to map shared config into
     * exact same address the primary process maps it.
     */
    uint64_t mem_cfg_addr;
} __attribute__((__packed__));
  • struct rte_memseg (rte_memory.h)
    rte_mem_config 结构体中的memseg 数组是维护物理地址的,在上面讲到struct hugepage结构对每个hugepage物理页面都存储了它在程序里面的虚存地址。memseg 数组的作用是将物理地址、虚拟地址都连续的hugepage,并且都在同一个socket,pagesize 也相同的hugepage页面集合,把它们都划在一个memseg结构里面,这样做的好处就是优化内存。
    这个结构体的信息都是从hugepage页表数组里面获得的。
/**
 * Physical memory segment descriptor.
 */
struct rte_memseg {
    phys_addr_t phys_addr;      /**< Start physical address. 这个memseg的包含的所有的hugepage页面的起始地址*/
    union {
        void *addr;         /**< Start virtual address.这些hugepage页面的起始的虚存地址,由于物理地址和虚拟地址是相同的,这个值应该等于phys_addr。 */
        uint64_t addr_64;   /**< Makes sure addr is always 64 bits */
    };
#ifdef RTE_LIBRTE_IVSHMEM
    phys_addr_t ioremap_addr; /**< Real physical address inside the VM */
#endif
    size_t len;               /**< Length of the segment. memseg的包含的空间size*/
    uint64_t hugepage_sz;       /**< The pagesize of underlying memory 大页内存的size 2M /1G? */
    int32_t socket_id;          /**< NUMA socket ID. */
    uint32_t nchannel;          /**< Number of channels. */
    uint32_t nrank;             /**< Number of ranks. */
#ifdef RTE_LIBRTE_XEN_DOM0
     /**< store segment MFNs */
    uint64_t mfn[DOM0_NUM_MEMBLOCK];
#endif
} __rte_packed;
  • struct rte_memzone (rte_memzone.h)
    这个结构体是DPDK内存管理最终向客户程序提供的基础接口
    通过rte_memzone_reverse 可以获取基于dpdk hugepage 的属于同一个物理cpu的,物理内存连续同时虚拟内存也连续的一块地址。在里面找满足socket_id的要求,最小的memseg,从中划出来一块内存,然后把这块内存记录到memzone里面。一般情况下,各个功能分配内存都使用这个函数分配一个memzone
    rte_ring/rte_malloc/rte_mempool等组件都是依赖于rte_memzone 组件实现的。
/**
 * A structure describing a memzone, which is a contiguous portion of
 * physical memory identified by a name.
 */
struct rte_memzone {

#define RTE_MEMZONE_NAMESIZE 32       /**< Maximum length of memory zone name.*/
    char name[RTE_MEMZONE_NAMESIZE];  /**< Name of the memory zone. */

    phys_addr_t phys_addr;            /**< Start physical address. */
    union {
        void *addr;                   /**< Start virtual address. */
        uint64_t addr_64;             /**< Makes sure addr is always 64-bits */
    };
#ifdef RTE_LIBRTE_IVSHMEM
    phys_addr_t ioremap_addr;         /**< Real physical address inside the VM */
#endif
    size_t len;                       /**< Length of the memzone. */

    uint64_t hugepage_sz;             /**< The page size of underlying memory */

    int32_t socket_id;                /**< NUMA socket ID. */

    uint32_t flags;                   /**< Characteristics of this memzone. */
    uint32_t memseg_id;               /**< Memseg it belongs. */
} __attribute__((__packed__));
  • rte_memzone_reverse()函数:
    一般情况下,各个功能分配内存都使用这个函数分配一个memzone
    const structrte_memzone *
    rte_memzone_reserve(constchar *name, size_t len, int socket_id,
    unsigned flags)
    {
    1、这里就在free_memseg数组里面找满足socket_id的要求,最小的memseg,从这里面划出来一块内存,当然这时候free_memseg需要更新把这部分内存刨出去。
    2、把这块内存记录到memzone里面。
    }
    上面提到rte_memzone_reserve分配内存后,同时在rte_mem_config.memzone数组里面分配一个元素保存它。对于从memseg中分配内存,以memzone为单位来分配,对于所有的分配情况,都记录在memzone数组里面,当然这个数组是多进程共享,大家都能看到。
    在rte_mem_config结构里面memzone_idx 变量记录当前分配的memzone,每申请一次这个变量+1。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值