intel dpdk api rte_eal_hugepage_init() 函数介绍

声明:此文档只做学习交流使用,请勿用作其他商业用途

author:朝阳_tony
E-mail : [email protected]
Create Date:2013-7-8 16:28:28 Monday
Last Change: 2013-7-8 17:31:40 Monday

转载请注明出处:http://blog.csdn.net/linzhaolove


此文中源码可以去http://dpdk.org/dev 网页中下载;更多官方文档请访问http://dpdk.org


1、函数用途

/*
 * 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 , 根据物理地址的大小排序;重新进行映射,获取连续的物理地址的空间;取消第一次的映射;将相关信息填充进去;

2、函数详解

    /* 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~

你可能感兴趣的:(intel,dpdk)