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

返回的即是bitmap的size,下面函数将分配bitmap,
*******************************************************
*  memblock_alloc_base这个东东以前没见过,顺着看看
*  在/mm/memblock.c中,这里的参数max_addr为896M
*******************************************************
phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
{
    phys_addr_t found;

    /* We align the size to limit fragmentation. Without this, a lot of
     * small allocs quickly eat up the whole reserve array on sparc
     */
    size = memblock_align_up(size, align);

    found = memblock_find_base(size, align, 0, max_addr);
    if (found != MEMBLOCK_ERROR &&
        !memblock_add_region(&memblock.reserved, found, size))
        return found;

    return 0;
}


*******************************************************
*  memblock_find_base在可操作内存范围内,找到第一个bitmap
*  size大小的空闲内存
*******************************************************
static phys_addr_t __init_memblock memblock_find_base(phys_addr_t size,
            phys_addr_t align, phys_addr_t start, phys_addr_t end)
{
    long i;

    BUG_ON(0 == size);

    /* Pump up max_addr */
    if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
        end = memblock.current_limit;

    /* We do a top-down search, this tends to limit memory
     * fragmentation by keeping early boot allocs near the
     * top of memory
     */
    for (i = memblock.memory.cnt - 1; i >= 0; i--) {
        phys_addr_t memblockbase = memblock.memory.regions[i].base;
        phys_addr_t memblocksize = memblock.memory.regions[i].size;
        phys_addr_t bottom, top, found;

        if (memblocksize < size)
            continue;
        if ((memblockbase + memblocksize) <= start)
            break;
        bottom = max(memblockbase, start);
        top = min(memblockbase + memblocksize, end);
        if (bottom >= top)
            continue;
        found = memblock_find_region(bottom, top, size, align);
        if (found != MEMBLOCK_ERROR)
            return found;
    }
    return MEMBLOCK_ERROR;
}


memblock应当是收集的内存信息的一个描述,回头再看一下,这里会找到这么个基地之然后将其
返回,以前这个地址应当是在紧挨着内核镜像bss后面,继续回到arm_bootmem_init

函数,下一个是


/**
 * init_bootmem_node - register a node as boot memory
 * @pgdat: node to register
 * @freepfn: pfn where the bitmap for this node is to be placed
 * @startpfn: first pfn on the node
 * @endpfn: first pfn after the node
 *
 * Returns the number of bytes needed to hold the bitmap for this node.
 */
unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn,
                unsigned long startpfn, unsigned long endpfn)
{
    return init_bootmem_core(pgdat->bdata, freepfn, startpfn, endpfn);
}

/*
 * Called once to set up the allocator itself.
 * bootmem 核心初始化
 */
static unsigned long __init init_bootmem_core(bootmem_data_t *bdata,
    unsigned long mapstart, unsigned long start, unsigned long end)
{
    unsigned long mapsize;

    mminit_validate_memmodel_limits(&start, &end);
    bdata->node_bootmem_map = phys_to_virt(PFN_PHYS(mapstart));  //bitmap起始地址
    bdata->node_min_pfn = start;     //节点起始地址
    bdata->node_low_pfn = end;       //结束地址
    link_bootmem(bdata);

    /*
     * Initially all pages are reserved - setup_arch() has to
     * register free RAM areas explicitly.
     */
    mapsize = bootmap_bytes(end - start);
        //又算了一遍????
    memset(bdata->node_bootmem_map, 0xff, mapsize);
        //node_bootmem_map记录bitmap起始地址,清空这里

    bdebug("nid=%td start=%lx map=%lx end=%lx mapsize=%lx\n",
        bdata - bootmem_node_data, start, mapstart, end, mapsize);

    return mapsize;
}


靠,现在的分配器真成分配器了,不带收集的??

总结:总括了bootmem分配器,介绍了其原理,后文准备跟一下memblock这个东东,以及那些分配函数具体实现^.^!.

相关阅读:

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

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