歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> Linux教程

Linux內存模型之bootmem分配器<一>

簡介:bootmem分配器是系統啟動初期的內存分配方式,在耳熟能詳的伙伴系統,slab系統建立前內存都是利用bootmem分配器來分配的,伙伴系統框架建立起來後,bootmem會過度到伙伴系統,bootmem大致思想就是收集內存中的可用內存,然後建立bit位圖,然後需要的內存從這些空閒內存中分配,分配了就標記占用,當然這種分配方式很低效,但是由於只占用啟動階段很少一部分,所以也大可接受了,好了,廢話不多說,一起看代碼吧,

相關閱讀:http://www.linuxidc.com/Linux/2012-02/53138.htm

一、初始化部分
init/main.c中
start_kernel函數
{
  ...
  setup_arch(&command_line);
  ...
}
代碼位於arch/arm/kernel/setup.c中,
void __init setup_arch(char **cmdline_p)
{
 ...
 paging_init(mdesc);
 ...
}


*******************************************************
*  繼續跟進paging_init函數在arch/arm/mm/mmu.c中

*******************************************************

/*
 * paging_init() sets up the page tables, initialises the zone memory
 * maps, and sets up the zero page, bad page and bad page tables.
 */
void __init paging_init(struct machine_desc *mdesc)
{
    void *zero_page;

    memblock_set_current_limit(lowmem_limit);

    build_mem_type_table();
    prepare_page_table();
    map_lowmem();
    devicemaps_init(mdesc);
    kmap_init();

    top_pmd = pmd_off_k(0xffff0000);

    /* allocate the zero page. */
    zero_page = early_alloc(PAGE_SIZE);

    bootmem_init();

    empty_zero_page = virt_to_page(zero_page);
    __flush_dcache_page(NULL, empty_zero_page);

}


***************************************************************
*  其中的bootmem_init()就是我們要找的,對應arm的定義在
*  arch/arm/mm/init.c
***************************************************************
void __init bootmem_init(void)
{
    unsigned long min, max_low, max_high;

    max_low = max_high = 0;

        /*
         *找到內存區域大小,max_low低端內存上界限
         *max_high 總內存上界
         */
    find_limits(&min, &max_low, &max_high);


        //arm bootmem初始化
    arm_bootmem_init(min, max_low);

    /*
     * Sparsemem tries to allocate bootmem in memory_present(),
     * so must be done after the fixed reservations
     */
    arm_memory_present();

    /*
     * sparse_init() needs the bootmem allocator up and running.
     */
    sparse_init();

    /*
     * Now free the memory - free_area_init_node needs
     * the sparse mem_map arrays initialized by sparse_init()
     * for memmap_init_zone(), otherwise all PFNs are invalid.
     */
    arm_bootmem_free(min, max_low, max_high);

    high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) - 1) + 1;

    /*
     * This doesn't seem to be used by the Linux memory manager any
     * more, but is used by ll_rw_block.  If we can get rid of it, we
     * also get rid of some of the stuff above as well.
     *
     * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
     * the system, not the maximum PFN.
     */
    max_low_pfn = max_low - PHYS_PFN_OFFSET;
    max_pfn = max_high - PHYS_PFN_OFFSET;
}

*******************************************************
*  這裡的函數需要一個一個的過一下,先看這個
*  find_limits(&min, &max_low, &max_high)函數
*  同文件夾下
*******************************************************
static void __init find_limits(unsigned long *min, unsigned long *max_low,
    unsigned long *max_high)
{
    struct meminfo *mi = &meminfo;  //內存bank的表述結構
    int i;

    *min = -1UL;
    *max_low = *max_high = 0;

    for_each_bank (i, mi) {
        struct membank *bank = &mi->bank[i];
        unsigned long start, end;

        start = bank_pfn_start(bank);
        end = bank_pfn_end(bank);

        if (*min > start)
            *min = start;             //保證min最後是最小值
        if (*max_high < end)    //保證最後的max_high是最大值
            *max_high = end;
        if (bank->highmem)      //如果bank是高端內存那麼不再標記max_low
            continue;
        if (*max_low < end)     //如果是普通內存,那麼max_low繼續跟著增大
            *max_low = end;
    }
}
Copyright © Linux教程網 All Rights Reserved