mem_init()

在mem_init函数中,系统将bootmem管理的内存转交给伙伴系统。free_unused_memmap_node释放了占用内存的page结构体,然后通过free_all_bootmem_node将剩余的空闲页移交给伙伴系统,此过程涉及__free_pages和__free_one_page等关键函数,实现了内存的有效管理。

原本由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++;

 

转载于:https://www.cnblogs.com/yangjiguang/p/9532124.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值