内存管理的配置和大页信息是进程间共享的,由主进程创建并共享给其他进程。
1 rte_config_init -> rte_eal_config_create
1.1 mem_config存储内存的配置信息,挂在全局变量rte_config.mem_config下面,其结构体主要成员如下:
包括memzone/memsegs/heap等重要信息。
struct rte_mem_config {
volatile uint32_t magic; /**< Magic number - Sanity check. */
struct rte_fbarray memzones; /**< Memzone descriptors. */
struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS]; /**< list of dynamic arrays holding memsegs */
struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
struct malloc_heap malloc_heaps[RTE_MAX_HEAPS]; /* Heaps of Malloc */
uint64_t mem_cfg_addr; //主进程的mem_config地址。
uint32_t legacy_mem;
uint32_t single_file_segments;
} __attribute__((__packed__));
1.2 主进程把自己的mem_config映射到文件中,主进程的mem_cfg变化之后,所有进程可见。
static void
rte_eal_config_create(void)
{
void *rte_mem_cfg_addr;
int retval;
const char *pathname = eal_runtime_config_path(); // "/var/run/dpdk/rte/config"
if (mem_cfg_fd < 0){
//创建文件,用作进程间共享
mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660);
}
retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config));
rte_mem_cfg_addr = mmap(rte_mem_cfg_addr, sizeof(*rte_config.mem_config),
PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
//初始化共享文件的内容。
memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config)); // early_mem_config应该都是0.
//共享文件的地址,挂到主进程自己的全局变量下。
rte_config.mem_config = rte_mem_cfg_addr;
//把主进程的地址保存到自己结构体下的uint64成员,从进程可见。
rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr;
}
1.3 gdb
1.3.1 创建共享文件
1.3.2 mmap共享文件,初始化之,并挂到全局变量rte_config.mem_config下。
1.3.3 共享文件所在linux目录的变化
1.3.4 rte_config.mem_config最终的结果
primary进程没有unmap掉共享文件,且lock住了该文件。说明primary进程后续还要修改mem_config,且只能由primary进程来修改。secondary进程负责从共享文件中读取mem_config配置。
2 eal_hugepage_info_init
2.1 hugepage_info_init
读取hugepage配置信息。
2.1.1 配置大页信息的文件夹路径
2.1.2 逐条读取文件夹信息,找到以“hugepages-”起始的文件夹
2.1.3 解析文件夹,获取大页的size(即每页有多少字节),大页的mount挂载点,大页在每个socket node中的具体数目,保存到internal_config.hugepage_info 中。
size = 2097152即2MB,hugedir为默认路径“/dev/hugepages”。
2.1.4 internal_config最终结果
2.2 进程间共享hugepage_info
hpi = &internal_config.hugepage_info[0];
tmp_hpi = create_shared_memory(eal_hugepage_info_path(),sizeof(internal_config.hugepage_info));
memcpy(tmp_hpi, hpi, sizeof(internal_config.hugepage_info));
if (munmap(tmp_hpi, sizeof(internal_config.hugepage_info)) < 0) {
RTE_LOG(ERR, EAL, "Failed to unmap shared memory!\n");
return -1;
}
2.2.1 hugepage的共享文件和路径,primary进程把自己的信息copy到共享文件中。
2.2.2 对应的文件夹变化
2.2.3 munmap
Primary进程munmap共享文件,说明primary进程不再更新internal_config.hugepage信息。munmap之后,该文件地址不能再访问。
3 总结
内存管理由Primary进程负责,这一篇章主要讲了两点:1. Primary进程的rte_config.mem_config变量,存放内存管理的信息,Primary后续对rte_config.mem_config的修改,会映射写入到共享文件中。Secondary进程读取内存管理的信息。这里并没有完成内存管理的配置。2. Primary进程完成对linux大页配置信息的读取,然后映射到共享文件中,后续不再更改hugepage info,所以munmap了。