DPDK学习记录13 - 内存申请1之malloc_heap_alloc

1 malloc_heap_alloc

内存初始化经过前面几步已经结束,后续就是如何去申请和管理内存。值得一提的是,由于采用了动态内存的默认配置,所以malloc heaps中的链表是空的,且memsegs list中的memseg也是按照最大limit个数初始化的,后续内存申请的过程,会动态从hugepage中申请memseg到malloc heaps中。

malloc_heap_alloc是dpdk申请内存最基本的入口,rte_malloc / rte_calloc / rte_memzone_reserve等申请内存的接口,都会调用到它。
在这里插入图片描述

我们来看看malloc_heap_alloc申请内存的过程。

2 malloc_heap_alloc_on_heap_id

malloc_heap_alloc调用到了malloc_heap_alloc_on_heap_id,然后再调用heap_alloc,由于malloc heaps第一次调用的时候,链表为空,所以返回值为0。尝试用alloc_more_mem_on_socket向hugepage申请更多的内存导入到malloc heaps中,然后再继续heap_alloc。
在这里插入图片描述

3 alloc_more_mem_on_socket

alloc_more_mem_on_socket 根据不同的page sz去调用 try_expand_heap,如果是primary进程,try_expand_heap调用try_expand_heap_primary。

3.1 try_expand_heap_primary

try_expand_heap_primary则主要调用alloc_pages_on_heap。

static int
try_expand_heap_primary(struct malloc_heap *heap, uint64_t pg_sz,
		size_t elt_size, int socket, unsigned int flags, size_t align,
		size_t bound, bool contig)
{

	alloc_sz = RTE_ALIGN_CEIL(align + elt_size +
			MALLOC_ELEM_TRAILER_LEN, pg_sz);
	n_segs = alloc_sz / pg_sz;
	ms = malloc(sizeof(*ms) * n_segs);
	memset(ms, 0, sizeof(*ms) * n_segs);
	elem = alloc_pages_on_heap(heap, pg_sz, elt_size, socket, flags, align,
			bound, contig, ms, n_segs);

	map_addr = ms[0]->addr;
	/* notify user about changes in memory map */
	eal_memalloc_mem_event_notify(RTE_MEM_EVENT_ALLOC, map_addr, alloc_sz);
	/* notify other processes that this has happened */
	if (request_sync()) {
		callback_triggered = true;
		goto free_elem;
	}
	heap->total_size += alloc_sz;
	free(ms);
	return 0;

}

3.2 alloc_pages_on_heap

alloc_pages_on_heap通过eal_memalloc_alloc_seg_bulk申请memseg,然后通过malloc_heap_add_memory加入到malloc heaps中。

struct malloc_elem *
alloc_pages_on_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,
		int socket, unsigned int flags, size_t align, size_t bound,
		bool contig, struct rte_memseg **ms, int n_segs)
{
	alloc_sz = (size_t)pg_sz * n_segs;
	allocd_pages = eal_memalloc_alloc_seg_bulk(ms, n_segs, pg_sz, socket, true);
	/* make sure we've allocated our pages... */
	if (allocd_pages < 0)
		return NULL;
	map_addr = ms[0]->addr;
	msl = rte_mem_virt2memseg_list(map_addr);

	/* add newly minted memsegs to malloc heap */
	elem = malloc_heap_add_memory(heap, msl, map_addr, alloc_sz);

	/* try once more, as now we have allocated new memory */
	ret = find_suitable_element(heap, elt_size, flags, align, bound,
			contig);

	if (ret == NULL)
		goto fail;

	return elem;

在这里插入图片描述
3.3 eal_memalloc_alloc_seg_bulk -> alloc_seg_walk -> alloc_seg

在这里插入图片描述

在这里插入图片描述

在hugepage的mount文件夹下多了一个rtemap_0的文件。
在这里插入图片描述
把rte_config->mem_config->memsegs[0]中的fbarray 对应的element设置成used,同时count置成1。
在这里插入图片描述

3.4 malloc_heap_add_memory

static struct malloc_elem *
malloc_heap_add_memory(struct malloc_heap *heap, struct rte_memseg_list *msl,
		void *start, size_t len)
{
	struct malloc_elem *elem = start;
	malloc_elem_init(elem, heap, msl, len);
	malloc_elem_insert(elem);
	elem = malloc_elem_join_adjacent_free(elem);
	malloc_elem_free_list_insert(elem);
	return elem;
}

此时,malloc heaps里还是空的。

在这里插入图片描述
malloc_heap_add_memory运行之后,heaps被写入,如下:
在这里插入图片描述

4 heap_alloc

在这里插入图片描述

struct malloc_elem *
malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,
		size_t bound, bool contig)
{
	struct malloc_elem *new_elem = elem_start_pt(elem, size, align, bound,
			contig);
	const size_t old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
	const size_t trailer_size = elem->size - old_elem_size - size -
		MALLOC_ELEM_OVERHEAD;

	malloc_elem_free_list_remove(elem);

	split_elem(elem, new_elem);
	new_elem->state = ELEM_BUSY;
	malloc_elem_free_list_insert(elem);

	return new_elem;
}

5 总结

malloc_heap_alloc是从malloc heaps中申请内存,如果当前heaps中没有找到,会尝试从hugepage中获取more memseg,然后add到heap memory中。当heaps中有足够的空间时,调用heap_alloc可以找到适当的malloc element,从该malloc element中得到一定大小的内存,剩余部分重新插入heaps中的free 链。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值