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官方文档
DPDK 内存管理---malloc_heap和malloc_elem相关推荐
- dpdk内存管理分析
dpdk内存管理分析 文章目录 dpdk内存管理分析 1.1 简述 1.2 `rte_config_init`分析 1.3 `eal_hugepage_info_init`的分析 1.4 `rte_e ...
- dpdk内存管理——内存初始化
*说明:本系列博文源代码均来自dpdk17.02* 1.1内存初始化 1.1.1 hugepage技术 hugepage(2M/1G..)相对于普通的page(4K)来说有几个特点: (1) huge ...
- dpdk内存管理之rte_eal_hugepage_init()函数分析
dpdk版本:dpdk-stable-16.11.11 今天我们来看一下rte_eal_hugepage_init() 函数都干了哪些事. 1.计算大页总数 在调用rte_eal_hugepage_i ...
- DPDK内存管理总结
1.前言 本文基于DPDK-17.05.2分析总结, DPDK通过使用hugetlbfs,减少CPU TLB表的Miss次数,提高性能. 2.Hugetlbfs初始化 DPDK的内存初始化工作,主要是 ...
- DPDK内存管理二:初始化
DPDK 内存的初始化主要在rte_eal_init()函数中进行: eal_hugepage_info_init() /* 获取系统中hugepage种类以及数量信息到internal_config ...
- dpdk 内存管理 原理剖析
dpdk 的内存管理层次结构 物理巨页的管理 虚拟地址空间的管理 heap管理(变长buffer) mempool管理(定长buffer) 物理巨页的管理 dpdk中通过 数组 hugepg_tbl[ ...
- DPDK内存管理 ----- (四) rte_mbuf
本文主要介绍 rte_mbuf 与 rte_mempool 数据结构之间的组织关系.以及网卡接收到的数据是如何存储在 rte_mbuf 中的. 一. rte_mbuf.rte_mempool及网卡 ...
- 收藏:DPDK内存基本概念
点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 来源:DPDK与SPDK开源社区 作者简介:Anatoly Burakov ...
- DPDK内存篇(三): 标准大页、NUMA、DMA、IOMMU、IOVA、内存池
作者简介:Anatoly Burakov,英特尔软件工程师,目前在维护DPDK中的VFIO和内存子系统. 目录 引言 标准大页 将内存固定到NUMA节点 硬件.物理地址和直接内存存取(DMA) IOM ...
最新文章
- h3c交换机配置文件的导出
- 前端学习(3035):vue+element今日头条管理-关于问题的一个解析
- haskell vscode下的环境搭配(包含各种坑的解决办法)
- 开发者真的喜欢开源吗?
- 关于取反符号的相关问题
- 枚举基类Enum详解
- C语言合法常量123L,C语言综合习(最终版).doc
- Unicode 中文,日文,西欧语言Unicode编码域(区间)
- 【论文阅读】【综述】A survey of deep learning techniques for autonomous driving
- “线上食堂”项目报告
- WSUS 3.0 的部署
- 一键让网页变黑白色调
- 使用Selenium控制已打开的浏览器和网页
- The maximum number of apps for free development profiles has been reached.
- 国内云通讯渗透率不足3% 容联云SaaS业务迈入高速发展期
- 21考研:一研为定,定为研一
- luaPanda 调试
- js JavaScript 计算时间差(两个日期时间相差的时间,包括毫秒,分钟,天数,差几个月,差几个季度)
- xampp php目录,htaccess文件,php,包括目录和Windows XAMPP配置噩梦
- 第十七章 Unity 预制件prefab(下)