https://www.cnblogs.com/MerlinJ/p/4074391.html
DPDK的内存初始化工作,主要是将hugetlbfs的配置的大内存页,根据其映射的物理地址是否连续、属于哪个Socket等,有效的组织起来,为后续管理提供便利。
eal_hugepage_info_init()
主要是获取配置好的Hugetlbfs的相关信息,并将其保存在struct internal_config数据结构中。
读取/sys/kernel/mm/hugepages目录下的各个子目录,通过判断目录名称中包含"hugepages-"字符串,获取hugetlbfs的相关子目录,并获取hugetlbfs配置的内存页大小。
通过读取/proc/mounts信息,找到hugetlbfs的挂载点
以打开文件的方式,打开挂载点目录,为其FD设置互斥锁
hpi->hugepage_sz = 2M;
hpi->hugedir = /mnt/huge;
hpi->num_pages[0] = 64; // 由于此时还不知道哪些内存页分处在哪个socket上,故,都先放在socket-0上。
hpi->lock_descriptor = open(hpi->hugedir, O_RONLY); // 在读取hugetlbfs配置的时候,需要锁住整个目录。当所有hugepage都mmap完成后,会解锁。
rte_eal_config_create()
rte_eal_config_create()主要是初始化rte_config.mem_config。如果是以root用户运行dpdk程序的话,rte_config.mem_config指向/var/run/.rte_config文件mmap的一段sizeof(struct rte_mem_config)大小的内存。用于管理整个内存。
rte_eal_hugepage_init()
rte_eal_hugepage_init()主要是在/mnt/huge目录下创建hugetlbfs配置的内存页数的rtemap_xx文件,并为每个rtemap_xx文件做mmap映射,保证mmap后的虚拟地址与实际的物理地址 一致性。
有多少个内存页,在挂载点目录下创建多少个rtemap_xx文件,如下所示,并为每一个文件mmap一个hugepage_sz大小的内存区域。
通过读取/proc/self/pagemap页表文件,得到本进程中虚拟地址与物理地址的映射关系。使用上一步中,每个rtemap_xx文件mmap得到的虚拟地址,除以操作系统内存页的大小4k,得到一个偏移量。根据这个偏移量,在/prox/self/pagemap中,得到物理地址的页框,假设为page,那么,物理页框page乘以操作系统内存页的大小4K,再加上虚拟地址的页偏移,就是物理地址。每个rtemap_xx映射的物理地址保存在对应的hugepage_file->physaddr中。
读取/proc/self/numa_maps,得到每个rtemap_xx文件mmap得到的虚拟地址在哪个Socket上,即,哪个CPU上。其socketid保存在对应的hugepage_file->socket_id中
在hugepage_file数组中,根据物理地址,按从小到大的顺序,将hugepage_file排序。
根据按物理地址排序后的结果,判断物理地址是否连续,重新mmap /mnt/huge/retmap_xx文件,第二次mmap得到的虚拟地址保存在对应的hugepage_file->final_va中。
munmap释放第一步中各个rtemap_xx文件首次mmap得到的内存地址。
计算每个socket上包含多少个hugepage,信息保存在internal_config.hugepage_info[0].num_pages[socket]中。
rte_config.mem_config->memseg[]数组记录hugepage_file映射后物理地址连续的块数,hugepage_file->memseg_id为该huepage_file的物理地址在哪个rte_config.mem_config->memseg[]数组中。
rte_config.mem_config->memseg[j].phys_addr = 各物理地址是连续的内存块的首地址。
rte_config.mem_config->memseg[j].addr = 各个物理地址是连续的内存块对应的虚拟地址的首地址。由于物理地址和虚拟地址是相同的,这个值应该等于phys_addr。
rte_config.mem_config->memseg[j].len = 各个物理地址是连续的内存块的大小。
rte_config.mem_config->memseg[j].socket_id = 内存块在哪个socket上。。
rte_config.mem_config->memseg[j].hugepage_sz = hugepage内存页的大小。本文中是2M。
rte_eal_memzone_init()
rte_eal_memzone_init()主要负责初始化rte_config.mem_config->free_memseg[]及rte_config.mem_config->memzone[]。其中,rte_config.mem_config->free_memseg[]记录空闲的rte_config.mem_config->memseg[]。