zoukankan      html  css  js  c++  java
  • mem_init()

    原本由bootmem管理的内存在mem_init函数中交由伙伴系统管理。

    1.free_unused_memmap_node

    相邻的membank间可能存在空洞,但在bootmem阶段这些空洞页也分配了page结构体。该函数的作用是找到这些page结构体所占用的内存并且释放掉。

    static void __init free_unused_memmap_node(int node, struct meminfo *mi)
        -->unsigned long bank_start; //前一个membank的结束地址
        -->unsigned long prev_bank_end ;//后一个membank的起始地址
        -->free_memmap(node, prev_bank_end, bank_start);
            -->struct page *start_pg = pfn_to_page(prev_bank_end);
            -->struct page *end_pg = pfn_to_page(bank_start);
            -->unsigned long pg = PAGE_ALIGN(__pa(start_pg));
            -->unsigned long pgend = __pa(end_pg) & PAGE_MASK;
            -->free_bootmem_node(NODE_DATA(node), pg, pgend - pg);

    2.移交bootmem分配剩余的空闲页到伙伴系统

    该函数返回的是返回给伙伴系统的空闲页数。

    unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
    {
        register_page_bootmem_info_node(pgdat);
        return free_all_bootmem_core(pgdat->bdata);
    }

    空闲页保存在全局变量totalram_pages中

    /*mm/page_alloc.c*/
    unsigned long totalram_pages __read_mostly;

    totalram_pages += free_all_bootmem_node(pgdat);

    2.1该函数的核心是free_all_bootmem_core(pgdat->bdata)

    static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
        -->__free_pages_bootmem(pfn_to_page(start), order);
        -->释放掉bdata->node_bootmem_map所占用的内存,彻底废弃bootmem分配器

    释放页到伙伴系统底层调用的两个函数是

    void __free_pages(struct page *page, unsigned int order)
    #define __free_page(page) __free_pages((page), 0)

    可以看到,最终调用的还是__free_pages函数

    void __free_pages(struct page *page, unsigned int order)
    {
        if (put_page_testzero(page)) {
            if (order == 0)
                free_hot_page(page);
            else
                __free_pages_ok(page, order);
        }
    }

    free_hot_page流程如下

    free_hot_page(page);
        -->free_hot_cold_page(page, 0);
            -->struct zone *zone = page_zone(page);
            -->struct per_cpu_pages *pcp = &zone_pcp(zone, get_cpu())->pcp;
            -->if (cold)
                list_add_tail(&page->lru, &pcp->list);/*冷页插入队列末尾*/
               else
                list_add(&page->lru, &pcp->list);/*热页插入队列首*/
            -->pcp->count++;
            -->if (pcp->count >= pcp->high)
                -->free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
                    -->从队列末尾开始删除pcp->batch个页
                    -->__free_one_page(page, zone, order);/*把删除的页释放到伙伴系统*/

    __free_pages_ok流程如下:

    static void __free_pages_ok(struct page *page, unsigned int order)
        -->free_one_page(page_zone(page), page, order);
            -->__free_one_page(page, zone, order);

    可以看出,最终调用相同的底层函数__free_one_page,这个函数的实现可以说是伙伴系统的精髓。

    这里注意空闲页加入伙伴系统后要做如下的设置。

    set_page_order(page, order);
        -->set_page_private(page, order);/*设置page->private*/
        -->__SetPageBuddy(page);/*设置page->flags*/
    list_add(&page->lru,&zone->free_area[order].free_list[migratetype]);
    zone->free_area[order].nr_free++;
  • 相关阅读:
    python 复杂一点的装饰器
    python 装饰器
    python 歌词解析
    ATX 免越狱调试IOS和Android
    OpenCV库文件介绍
    NetEaseGame/ATX 的MD
    带你玩转Visual Studio——带你高效开发
    python 图像识别
    fatal: Authentication failed for又不弹出用户名和密码 解决办法
    lua luna工具库
  • 原文地址:https://www.cnblogs.com/yangjiguang/p/9532124.html
Copyright © 2011-2022 走看看