声明:此文档只做学习交流使用,请勿用作其他商业用途
author:朝阳_tony 转载请注明出处:http://blog.csdn.net/linzhaolove
此文中源码可以去http://dpdk.org/dev 网页中下载;更多官方文档请访问http://dpdk.org
/* * Prepare physical memory mapping: fill configuration structure with * these infos, return 0 on success. * 1. map N huge pages in separate files in hugetlbfs * 2. find associated physical addr * 3. find associated NUMA socket ID * 4. sort all huge pages by physical address * 5. remap these N huge pages in the correct order * 6. unmap the first mapping * 7. fill memsegs in configuration with contiguous zones */ static int rte_eal_hugepage_init(void)
函数在dpdk/lib/librte_eal/linuxapp/eal/eal_memory.c文件中
首先对hugepage 进行内存映射,相当于先占领内存,根据虚拟内存,查找物理内存;还有对应的socket id , 根据物理地址的大小排序;重新进行映射,获取连续的物理地址的空间;取消第一次的映射;将相关信息填充进去;/* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config;用首先获取rte_config这个全局的配置结构体,将结构体内的mem_config地址给了mcfg,后期会往这个地址中存储一些重要信息;
nrpages = calc_num_pages(internal_config.memory, &internal_config.hugepage_info[0], &used_hp[0], internal_config.num_hugepage_sizes);calc_num_pages() 计算时候填充的每个映射块中的适合大小;
hugepage = create_shared_memory(eal_hugepage_info_path(), nrpages * sizeof(struct hugepage));
去创建共享问 /var/run/.rte_hugepage_info 方便以后其他的程序共享获取hugepage相关的数据;
其中的nrpages * sizeof(struct hugepage) 是指中共要在.rte_hugepage_info映射nrpages个结构体,存储每个huagepage相关信息,而这个文文件只是在 primary时创建和引用其内容,在secondary时,不创建,只引用里面的内容;
查看一下当前配置的num_pages数;
# grep Huge /proc/meminfo HugePages_Total: 1024 HugePages_Free: 1024 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB
if (map_all_hugepages(&hugepage[hp_offset], hpi, 1) < 0)第一次创建所有的hugepage映射文件,默认是在 /mnt/huge目录下;其数量按你设置的num_pages数,我之前设置的为1024个;
map_all_hugepages函数最后一个参数int orig 被设置被1,也就是在第一次映射时,将映射得到的虚拟地址放在orig_va中;二次映射时,将orig设置为0,根据之后按物理地址排序后,获取连续的的映射地址;这个地方有点绕,需要多加注意;
if (find_physaddr(&hugepage[hp_offset], hpi) < 0)遍历/proc/self/pagemap文件,根据第一映射的虚拟地址,获取其相应的物理地址;
if (find_numasocket(&hugepage[hp_offset], hpi) < 0)遍历/proc/self/numa_maps 获取每个hugepage对应的 socket ID
if (sort_by_physaddr(&hugepage[hp_offset], hpi) < 0)对物理地址按照由小到大排序;在排序后,hugepage文件的号,和hugepg_tbl[i]中的index索引值就不在一一对应;但此时文件映射的物理地址是连续的;
if (map_all_hugepages(&hugepage[hp_offset], hpi, 0) < 0)第二次映射;映射的虚拟地址也是连续的;如果不明白可以在map_all_hugepages函数中加两行打印试试;函数在 dpdk/lib/librte_eal/linuxapp/eal/eal_memory.c 文件中;
if (orig) { hugepg_tbl[i].orig_va = virtaddr; memset(virtaddr, 0, hugepage_sz); /* add linzh */ fprintf(stdout,"orig virtaddr = %p\n",virtaddr); } else { hugepg_tbl[i].final_va = virtaddr; /* add linzh */ fprintf(stdout,"orig virtaddr = %p\n",virtaddr); }
if (unmap_all_hugepages_orig(&hugepage[hp_offset], hpi) < 0)
mcfg->memseg[j].phys_addr = hugepage[i].physaddr; mcfg->memseg[j].addr = hugepage[i].final_va; mcfg->memseg[j].len = hugepage[i].size; mcfg->memseg[j].socket_id = hugepage[i].socket_id; mcfg->memseg[j].hugepage_sz = hugepage[i].size;最后将信息保存大rte_config->mem_config中;
技术水平有待提高,如果文章有错误的地方希望读者指正,相互交流,互相学习;O(∩_∩)O~