Linux内存模型之bootmem分配器一(2)

这样会遍历所有的bank,start和end分别表示每个bank的开始和结束地址,max_low标记成低端最大值,例如:896M,平时耳熟能详的x86上面,这个值不是个固定值,是根据总内存大小来的,896M比较常见.

**************************************************************
*  回过头来继续看arm_bootmem_init(min, max_low)
*  将刚才得到的值传入,可见bootmem是操作的低端内存
**************************************************************
static void __init arm_bootmem_init(unsigned long start_pfn,
    unsigned long end_pfn)
{
    struct memblock_region *reg;
    unsigned int boot_pages;
    phys_addr_t bitmap;
    pg_data_t *pgdat;

  
 /*
     * Allocate the bootmem bitmap page.  This must be in a region
     * of memory which has already been mapped.
         *
        
* 分配bitmap所需的内存,bitmap是一个内存单元分配与否的标志,
         * 用一个bit来表示,当然它自身也要占用一定内存,参数是低端起始
         * 内存到低端上界内存,这里假设拿x86的896M来说,那么就是
         * 0---896M,哦,忘了说一点,这里应当是以4k(一页)为单位,
         * 所以应当是0---896M/4k
     */


    boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);

        //分配bitmap
    bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES,
                __pfn_to_phys(end_pfn));

  
 /*
     * Initialise the bootmem allocator, handing the
     * memory banks over to bootmem.
         * 初始化分配器核心,包括bitmap内容清空
     */

    node_set_online(0);
    pgdat = NODE_DATA(0);
    init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);

      
/* Free the lowmem regions from memblock into bootmem.
        * 把memblock收集的那些内存标志到bootmem中,也就是把这些
        * 内存在bootmem中标记成可用在bitmap中
        *
        */

    for_each_memblock(memory, reg) {
        unsigned long start = memblock_region_memory_base_pfn(reg);
        unsigned long end = memblock_region_memory_end_pfn(reg);

        if (end >= end_pfn)
            end = end_pfn;
        if (start >= end)
            break;

        free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT);
    }

    /* Reserve the lowmem memblock reserved regions in bootmem.
        *  再过滤一遍,把memblock已用的内存在bitmap中标记成已使用
        *
        */
    for_each_memblock(reserved, reg) {
        unsigned long start = memblock_region_reserved_base_pfn(reg);
        unsigned long end = memblock_region_reserved_end_pfn(reg);

        if (end >= end_pfn)
            end = end_pfn;
        if (start >= end)
            break;

        reserve_bootmem(__pfn_to_phys(start),
                    (end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT);
    }
}


*******************************************************
*  bootmem_bootmap_pages是个体系结构无关函数在
*  mm/bootmem.c中定义
*******************************************************
/**
 * bootmem_bootmap_pages - calculate bitmap size in pages
 * @pages: number of pages the bitmap has to represent
 */
unsigned long __init bootmem_bootmap_pages(unsigned long pages)
{
    unsigned long bytes = bootmap_bytes(pages);

    return PAGE_ALIGN(bytes) >> PAGE_SHIFT;
}


static unsigned long __init bootmap_bytes(unsigned long pages)
{
        //页数/8得到需要用多少个字节表示这些页
    unsigned long bytes = (pages + 7) / 8;

    return ALIGN(bytes, sizeof(long));
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/22651.html