DPDK 内存管理---malloc_heap和malloc_elem

博文是基于dpdk20.5代码阅读所写,如理解有错误或不当之处,烦请指正,不甚感激。也可以私信我一起探讨。

两种数据结构体介绍

Malloc 库内部使用了两种数据结构类型(可以参考dpdk官方文档3.4.4章节介绍):

  • struct malloc_heap:用于在每个 CPU Socket 上跟踪和管理可用内存空间。
    在这里插入图片描述
  • struct malloc_elem:Malloc 库内部用于追踪分配和释放空间的基本要素。
    在这里插入图片描述

基本内存分布结构说明

malloc_elem介绍

elem是heap管理内存的基本单元,内存的添加和删除都是基于elem结构来操作的,内存块有三种状态,具体如下:

enum elem_state {
	ELEM_FREE = 0, /*表示当前elem块是空闲的*/ 
	ELEM_BUSY,     /*表示当前elem块已经被使用的*/
	ELEM_PAD       /*表示当前elem块已经使用并且是pad形势*/
};

一个elem被分为三个段,elem header(管理头)、data(存放数据部分)、Trailer cookie(debug打开时有效,主要用户检测内存是否存在越界) 三部分。具体分布如下:
在这里插入图片描述
当申请elem1块剩余空间小于elem最小内存时,会创建一个ELEM_PAD 类型的elem2块。ELEM_PAD 数据块内存状态如下,主要原因是rte_malloc 是返回data区域的首地址,通过数据首地址-malloc elem结构大小可以找到elem2块的地址,根据elem2的类型是ELEM_PAD,使用elem2地址-elem2->pad可以直接找到elem1的首地址,管理起来很方便,但是会造成内存的浪费,在频繁申请小内存时,空间浪费比较多。
在这里插入图片描述
malloc_elm结构还有两个比较关注的数据prev和next
这两个指针用于指向紧跟这当前 memseg 的头元素。当释放一个内存块时,该指针用于引用上一个内存块,检查上一个块是否也是空闲。如果空闲,则将两个空闲块合并成一个大块。双向链表的关系必须是前后内存连续的并且参数中msl和orig_elem,这样才能进行合并。

static int
next_elem_is_adjacent(struct malloc_elem *elem)
{
	return elem->next == RTE_PTR_ADD(elem, elem->size) &&
			elem->next->msl == elem->msl &&
			(!internal_config.match_allocations ||
			 elem->orig_elem == elem->next->orig_elem);
}

在这里插入图片描述

malloc_heap介绍

在EAL初始化时,所有预先分配的内存段都被设置成malloc heap的一部分,这种设置包括在每个几乎连续的内存段的开头放置一个带有free的elem内存块。然后将free 的elem内存块添加到malloc heap的free_head 链表中。
这种设置也会在运行时候发生如果支持的话(leacy mem是不支持的),在这种情况下,还会将新分配的页面添加到堆中,如果有空闲段,则与相邻的空闲段合并。
当应用程序调用类malloc函数时,malloc函数将首先索引调用线程的lcore_config结构,并确定该线程的NUMA节点。NUMA节点用于索引malloc_heap结构的数组,该数组作为参数传递给heap_alloc()函数,以及请求的大小、类型、对齐方式和边界参数。
heap_alloc()函数将扫描堆的free_list,并尝试找到适合存储所请求大小的数据的空闲块,该块具有所请求的对齐方式和边界约束。

heap堆是dpdk内存管理socket对应空间内存块,结构体中free_head[13],根据data数据部分的大小来划分的,下面也有说明,是通过双向链表来管理的。具体如下:
在这里插入图片描述
下面是debug下对heap结构的打印,存在内存异常的时候,可以通过串联关系来检查elem块是否存在写越界问题。
在这里插入图片描述## Rte_malloc 函数解读

/*这个函数从内存的大页区域分配内存。内存没有清0。在NUMA系统中,分配的内存驻留在与调用该函数的core相同的NUMA套接字上。
 * type:标识已分配对象类型的字符串(对于调试目的很有用,例如标识内存泄漏的原因)。可以为空。
 *size :申请内存的大小,单位字节
 *align:如果为0,则返回的指针对任何类型的变量都进行了适当对齐(与malloc()相同)。否则,返回的指针是align的倍数。
 *在这种情况下,它一定是2的幂。(最小对齐是cacheline大小,即64字节)
 */
void *rte_malloc(const char *type, size_t size, unsigned align)
---void *rte_malloc_socket(const char *type, size_t size, unsigned int align,int socket_arg)
  ---void *malloc_socket(const char *type, size_t size, unsigned int align,int socket_arg, 
             const bool trace_ena)
             最终调用malloc_heap_alloc()函数

在这里插入图片描述

参考资料

1、dpdk官方文档

除了 rte_malloc_heap_dump() 函数之外,DPDK 还提供了其他一些 API 来统计内存使用情况,包括: 1. rte_malloc_stats():该函数可以获取 DPDK 内存池的统计信息,包括内存池中的对象数量、空闲对象数量、已分配对象数量等等,可以用于监视内存池的使用情况。 2. rte_malloc_validate():该函数可以验证指定地址是否在 DPDK 内存堆中,如果地址无效,函数返回值为负数。 3. rte_malloc_dump_heaps():该函数可以打印所有非空 DPDK 内存堆的使用情况,包括内存堆的名称、总大小、已分配大小、剩余大小等等。 下面是一个简单的例子,展示了如何使用这些函数来统计 DPDK 内存使用情况: ```c #include <stdio.h> #include <rte_malloc.h> int main(int argc, char **argv) { // 初始化 DPDK 环境 rte_eal_init(argc, argv); // 分配一块内存 void *mem = rte_malloc(NULL, 1024, 0); if (mem == NULL) { printf("Failed to allocate memory!\n"); return -1; } // 输出内存使用情况 struct rte_malloc_stats stats; rte_malloc_stats(&stats); printf("DPDK memory stats:\n"); printf("Total heap size: %lu bytes\n", stats.total_heap_size); printf("Free heap size: %lu bytes\n", stats.free_heap_size); printf("Allocated heap size: %lu bytes\n", stats.allocd_heap_size); printf("Total allocated objects: %lu\n", stats.alloc_count); printf("Total freed objects: %lu\n", stats.free_count); // 验证指定地址是否在内存堆中 if (rte_malloc_validate(mem) < 0) { printf("Invalid memory address!\n"); } // 输出所有内存堆的使用情况 rte_malloc_dump_heaps(stdout); // 释放内存 rte_free(mem); return 0; } ``` 在上述代码中,我们首先使用 rte_eal_init() 函数初始化 DPDK 环境,然后使用 rte_malloc() 函数分配了一块 1024 字节的内存。接着,我们使用 rte_malloc_stats() 函数获取 DPDK 内存池的统计信息,并将其打印到标准输出中。然后,我们使用 rte_malloc_validate() 函数验证分配的内存地址是否有效。最后,我们使用 rte_malloc_dump_heaps() 函数打印所有非空 DPDK 内存堆的使用情况,将结果输出到标准输出中。最后,我们使用 rte_free() 函数释放了分配的内存。 当运行该程序时,屏幕上将输出类似以下的信息: ``` DPDK memory stats: Total heap size: 268435456 bytes Free heap size: 267435392 bytes Allocated heap size: 1021064 bytes Total allocated objects: 1 Total freed objects: 0 DPDK memory heap Heap name: rte_malloc_heap Total size: 268435456 bytes Free size: 267435392 bytes Free blocks: 2 Allocated blocks: 3 Minimum alloc size: 64 bytes Maximum alloc size: 268435392 bytes Total allocations: 1024 bytes Total frees: 0 bytes ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值