声明:此文档只做学习交流使用,请勿用作其他商业用途
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~