目录

1.1 内存堆的作用

1.2 分析函数

1.2.1 rte_eal_malloc_heap_init

1.2.2  rte_memseg_contig_walk

1.2.3 malloc_add_seg

2.3 总结


1.1 内存堆的作用

内存堆的主要作用就是将大页分段信息保存到堆中,用堆对这块内存进行管理。

1.2 分析函数

1.2.1 rte_eal_malloc_heap_init

int
rte_eal_malloc_heap_init(void)
{struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;unsigned int i;//参数没有设置if (internal_config.match_allocations) {RTE_LOG(DEBUG, EAL, "Hugepages will be freed exactly as allocated.\n");}if (rte_eal_process_type() == RTE_PROC_PRIMARY) {/* assign min socket ID to external heaps */mcfg->next_socket_id = EXTERNAL_HEAP_MIN_SOCKET_ID;/* assign names to default DPDK heaps *///设置默认堆的sock id,使堆的信息和head关联for (i = 0; i < rte_socket_count(); i++) {struct malloc_heap *heap = &mcfg->malloc_heaps[i];char heap_name[RTE_HEAP_NAME_MAX_LEN];int socket_id = rte_socket_id_by_idx(i);snprintf(heap_name, sizeof(heap_name),"socket_%i", socket_id);strlcpy(heap->name, heap_name, RTE_HEAP_NAME_MAX_LEN);heap->socket_id = socket_id;}}//注册了一个mp请求if (register_mp_requests()) {RTE_LOG(ERR, EAL, "Couldn't register malloc multiprocess actions\n");rte_mcfg_mem_read_unlock();return -1;}/* unlock mem hotplug here. it's safe for primary as no requests can* even come before primary itself is fully initialized, and secondaries* do not need to initialize the heap.*/rte_mcfg_mem_read_unlock();/* secondary process does not need to initialize anything */if (rte_eal_process_type() != RTE_PROC_PRIMARY)return 0;/* add all IOVA-contiguous areas to the heap *///将所有虚拟rte_msg segment添加到heap中return rte_memseg_contig_walk(malloc_add_seg, NULL);
}

1.2.2  rte_memseg_contig_walk

//加锁调用,主要功能是在这个函数中rte_memseg_contig_walk_thread_unsafe
int
rte_memseg_contig_walk(rte_memseg_contig_walk_t func, void *arg)
{int ret = 0;/* do not allow allocations/frees/init while we iterate */rte_mcfg_mem_read_lock();ret = rte_memseg_contig_walk_thread_unsafe(func, arg);rte_mcfg_mem_read_unlock();return ret;
}int
rte_memseg_contig_walk_thread_unsafe(rte_memseg_contig_walk_t func, void *arg)
{struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;int i, ms_idx, ret = 0;//遍历所有mem_seg,在上一篇中有分析,根据当前系统,实际能够产生4个内存段for (i = 0; i < RTE_MAX_MEMSEG_LISTS; i++) {struct rte_memseg_list *msl = &mcfg->memsegs[i];const struct rte_memseg *ms;struct rte_fbarray *arr;if (msl->memseg_arr.count == 0)continue;//根据rte_meseg的页的个数,以及掩码申请的一块虚拟内存,将内存地址放到nenseg_arrarr = &msl->memseg_arr;ms_idx = rte_fbarray_find_next_used(arr, 0);while (ms_idx >= 0) {int n_segs;size_t len;//根据id找到rte_memsegms = rte_fbarray_get(arr, ms_idx);/* find how many more segments there are, starting with* this one.*///查找有多少个页能用n_segs = rte_fbarray_find_contig_used(arr, ms_idx);//算出整个内存的大小len = n_segs * msl->page_sz;//调用函数malloc_add_segret = func(msl, ms, len, arg);if (ret)return ret;ms_idx = rte_fbarray_find_next_used(arr,ms_idx + n_segs);}}return 0;
}

1.2.3 malloc_add_seg

static int
malloc_add_seg(const struct rte_memseg_list *msl,const struct rte_memseg *ms, size_t len, void *arg __rte_unused)
{struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;struct rte_memseg_list *found_msl;struct malloc_heap *heap;int msl_idx, heap_idx;if (msl->external)return 0;heap_idx = malloc_socket_to_heap_id(msl->socket_id);if (heap_idx < 0) {RTE_LOG(ERR, EAL, "Memseg list has invalid socket id\n");return -1;}heap = &mcfg->malloc_heaps[heap_idx];/* msl is const, so find it */msl_idx = msl - mcfg->memsegs;if (msl_idx < 0 || msl_idx >= RTE_MAX_MEMSEG_LISTS)return -1;found_msl = &mcfg->memsegs[msl_idx];//ms->addr这块地址是每一个rte_segmem的首地址//在hugepage_init中ms->addr是遍历每一段内存中每一页,根据页的偏移计算出ms->addr,//在本函数中ms->addr根据每一段的页的个数和大小还有首页的地址算出来的malloc_heap_add_memory(heap, found_msl, ms->addr, len);heap->total_size += len;RTE_LOG(DEBUG, EAL, "Added %zuM to heap on socket %i\n", len >> 20,msl->socket_id);return 0;
}//初始化元素信息
void
malloc_elem_init(struct malloc_elem *elem, struct malloc_heap *heap,struct rte_memseg_list *msl, size_t size,struct malloc_elem *orig_elem, size_t orig_size)
{elem->heap = heap;elem->msl = msl;elem->prev = NULL;elem->next = NULL;memset(&elem->free_list, 0, sizeof(elem->free_list));elem->state = ELEM_FREE;elem->size = size;elem->pad = 0;elem->orig_elem = orig_elem;elem->orig_size = orig_size;set_header(elem);set_trailer(elem);
}//把元素插入到free list的链表中
static struct malloc_elem *
malloc_heap_add_memory(struct malloc_heap *heap, struct rte_memseg_list *msl,void *start, size_t len)
{//elem的地址是rte_seg的首地址struct malloc_elem *elem = start;//初始化元素malloc_elem_init(elem, heap, msl, len, elem, len);//将elem这个元素插入到堆中malloc_elem_insert(elem);//如果元素是相邻的元素就会把钱一个元素后一个元素合并成一个元素,变成一块内存elem = malloc_elem_join_adjacent_free(elem);//把这一类地址空间加到free_list里边malloc_elem_free_list_insert(elem);return elem;
}

2.3 总结

1、rte_eal_memory_init是为rte_eal_malloc_heap_init做了一个铺垫,通过一系列的内存分配,分页,分段的初始化,最终的目的是把这些内存放到堆中,所有内存的调用,缓冲池,rte_alloc的调用最终申请的是堆的内存,而堆用到的内存是虚拟内存。

2、分析到目前还有以下疑问:

(1)大页的产生是因为TLB大小有限,但是大页在TLB的应用是怎么体现的,这个还未开始研究

(2)内存申请,缓存池内存申请,mbuf的内存申请这块还没有研究,接下来花一定的时间去探究这些问题

rte_eal_init之内存堆相关推荐

  1. LwIP 之五 详解动态内存管理 内存堆(mem.c/h)

    写在前面   目前网上有很多介绍LwIP内存的文章,但是绝大多数都不够详细,甚至很多介绍都是错误的!无论是代码的说明还是给出的图例,都欠佳!下面就从源代码,到图例详细进行说明.   目前,网络上多数文 ...

  2. JVM【带着问题去学习 01】什么是JVM+内存结构+堆内存+堆内存参数(逃逸分析)

    1.是什么 (1) 基本概念:可运行 Java 代码的非真实计算机 ,包括一套字节码指令集.一组寄存器.一个栈.一个垃圾回器,堆和一个存储方法域.它运行在操作系统之上,与硬件没有直接的交互. (2) ...

  3. 4g内存 堆内存分配多少_我需要多少内存

    4g内存 堆内存分配多少 什么是保留堆? 我需要多少内存? 在构建解决方案,创建数据结构或选择算法时,您可能会问自己(或其他人)这个问题. 如果此图包含1,000,000条边并且我使用HashMap进 ...

  4. 堆(概念,数据结构中堆与内存堆区的区别 ,堆的基本操作)

    堆的特性: 必须是完全二叉树 用数组实现 任一结点的值是其子树所有结点的最大值或最小值 最大值时,称为"最大堆",也称大根堆: 在完全二叉树中,任何一个子树的最大值都在这个子树的根 ...

  5. LwIP之动态内存堆

    内存堆其实就是一个数组.为了方便管理需要将内存堆首尾组织成内存块,因此多分配的2 * SIZEOF_STRUCT_MEM大小的空间 /* 内存堆空间 */ static u8_t ram_heap[M ...

  6. 小内存堆管理算法详细解析

    1.小内存堆管理算法介绍 本文所介绍的内存堆管理是RT Thread操作系统中的小内存管理算法,参考mem.c源文件.这个程序适用于小内存的CPU,比如像STM32F这样的只有几十-几百KB内存的处理 ...

  7. LwIP源码分析(3):内存堆和内存池代码详解

    文章目录 1 内存堆 1.1 mem_init 1.2 mem_malloc 1.3 mem_free 2 内存池 2.1 memp_init 2.2 memp_malloc 2.3 memp_fre ...

  8. mysql8 堆应该给多大_深入进阶:图解分析JVM内存堆布局

    JAVA能够实现跨平台的一个根本原因,是定义了class文件的格式标准,凡是实现该标准的JVM都能够加载并解释该class文件,据此也可以知道,为啥Java语言的执行速度比C/C++语言执行的速度要慢 ...

  9. JVM内存堆布局图解分析

    转载原文出处:http://www.codeceo.com/article/jvm-memory-stack.html JAVA能够实现跨平台的一个根本原因,是定义了class文件的格式标准,凡是实现 ...

最新文章

  1. sql serve 数据库游标的使用
  2. 前端学习(804):替换字符串和转换为数组
  3. 获取win7时区所有信息
  4. 【学习生活杂谈】学习记录
  5. 【转】syslog服务和syslogd守护进程
  6. 放弃治疗式宣传?Kindle官方自我调侃:盖Kindle 面更香
  7. mysql投票网站_PHP+Mysql实现网站顶和踩投票功能实例
  8. Web前端前景、最新技术、学习路线?
  9. 平安银行股票数据涨跌预测
  10. 如何用VsCode进行Debug
  11. 过去分词和动词过去式区别
  12. vba字典重复key_VBA字典数据重复次数
  13. 10246 - Asterix and Obelix
  14. 初步了解PS“时间轴”
  15. 激光雷达还是摄影测量?两者数据融合如何提高点云质量
  16. s:iterator各种遍历用法
  17. Linux小白的大师之路
  18. 树 —— 线索二叉树
  19. 7-1 统计字符串中不同种类的字符个数 (10 分)
  20. 音频相关基础知识(采样率、位深度、通道数、PCM、AAC)

热门文章

  1. PyTorch碎片:PyToch和Torchvision对应版本
  2. 虚假IP地址攻击溯源
  3. MFC 打开外部文件 WinExec,ShellExecute ,CreateProcess
  4. Linux 部署 .NET 6(宝塔面板)
  5. FPGA四种基本的设计思想
  6. 金蝶K3案例教程生产任务管理后台配置
  7. 几何用计算机,平面几何
  8. IOS7 界面布局,导航条透明
  9. vue3+ts+pinia大气政府门户pc端
  10. USB 网卡驱动数据流