1 rte_memzone_reserve
rte_memzone_reserve_thread_safe 这个基本的函数上封装了三个对外的函数接口:rte_memzone_reserve/rte_memzone_reserve_aligned/rte_memzone_reserve_bounded。
rte_memzone_reserve_thread_safe加了锁之后调用 memzone_reserve_aligned_thread_unsafe,由下面的代码可以看出,memzone的申请最终调用malloc_heap_alloc。
static const struct rte_memzone *memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,int socket_id, unsigned int flags, unsigned int align,unsigned int bound)
{
mcfg = rte_eal_get_configuration()->mem_config;
arr = &mcfg->memzones; //memzones是一个fbarray。
if (len == 0 && bound == 0) {
requested_len = 0; /* no size constraints were placed, so use malloc elem len */
mz_addr = malloc_heap_alloc_biggest(NULL, socket_id, flags, align, contig);
} else {
if (len == 0)
requested_len = bound;
mz_addr = malloc_heap_alloc(NULL, requested_len, socket_id, flags, align, bound, contig); /* allocate memory on heap */
}
if (mz_addr == NULL) {
rte_errno = ENOMEM;
return NULL;
}
struct malloc_elem *elem = malloc_elem_from_data(mz_addr);
/* fill the zone in config */
mz_idx = rte_fbarray_find_next_free(arr, 0);
if (mz_idx < 0) {
mz = NULL;
} else {
rte_fbarray_set_used(arr, mz_idx);
mz = rte_fbarray_get(arr, mz_idx);
}
snprintf(mz->name, sizeof(mz->name), "%s", name);
mz->iova = rte_malloc_virt2iova(mz_addr);
mz->addr = mz_addr;
mz->len = requested_len == 0 ?
elem->size - elem->pad - MALLOC_ELEM_OVERHEAD :
requested_len;
mz->hugepage_sz = elem->msl->page_sz;
mz->socket_id = elem->msl->socket_id;
mz->flags = 0;
return mz;
}
2 gdb调试
2.1 通过rte_memzone_reserve申请内存
2.2 调用到memzone_reserve_aligned_thread_unsafe
查看rte_config->mem_config->memzones的arr变量可知,当下counter为0,没有申请过memzone。
2.3 通过malloc_heap_alloc申请内存得到mz_addr
2.4 通过mz_addr得到malloc element,然后申请一个free的memzone id且占住这个free的id,第一个free的id值为0,而后可以看到arr中的counter变成了1。
2.5
对mz中的其他字段赋值
3 总结
按我理解,memzone是在heap之上的一层封装,通过fbarray机制管理。fbarray中data区域中,保存了每个memzone结构体的内容,包括name/iova/len/socket id等。用户可以通过memzone name在fbarray中查询已有的memzone结构。