Linux内核-内存-分区页框分配器

简介

分区页框分配器处理对连续页框组的内存分配请求,主要组成如下图所示:

这里写图片描述

管理区分配器接受动态内存分配与释放的请求,它首先从每CPU页框高速缓存中请求页框,若无法满足才从伙伴系统中请求分配。


源码分析(Linux2.6/mm/page_alloc.c)

  1. buffered_rmqueue()

    此函数从指定内存管理区中分配页框,对应上图中的分配机制。

     static struct page *buffered_rmqueue(struct zone *zone, int order, int gfp_flags)
        {
            unsigned long flags;
            struct page *page = NULL;
            int cold = !(gfp_flags & __GFP_COLD);
    
            /**
             * 如果order!=0,则每CPU页框高速缓存就不能被使用,因为每CPU页框高速缓存是对单个页框的管理
             */
            if (order == 0) {
                struct per_cpu_pages *pcp;
    
                /**
                 * 检查由__GFP_COLD标志所标识的内存管理区本地CPU高速缓存是否需要被补充。
                 * 其count字段小于或者等于low
                 */
                pcp = &zone->pageset[get_cpu()].pcp[cold];
                local_irq_save(flags);
                /**
                 * 当前缓存中的页框数低于low,需要从伙伴系统中补充页框。
                 * 调用rmqueue_bulk函数从伙伴系统中分配batch个单一页框
                 * rmqueue_bulk反复调用__rmqueue,直到缓存的页框达到low。
                 */
                if (pcp->count <= pcp->low)
                    pcp->count += rmqueue_bulk(zone, 0,
                                pcp->batch, &pcp->list);
                /**
                 * 如果count为正,函数从高速缓存链表中获得一个页框。
                 * count减1
                 */
                if (pcp->count) {
                    page = list_entry(pcp->list.next, struct page, lru);
                    list_del(&page->lru);
                    pcp->count--;
                }
                local_irq_restore(flags);
                /**
                 * 没有和get_cpu配对使用呢?
                 * 这就是内核,外层一定调用了get_cpu。这种代码看起来头疼。
                 */
                put_cpu();
            }
    
            /**
             * 内存请求没有得到满足,或者是因为请求跨越了几个连续页框,或者是因为被选中的页框高速缓存为空。
             * 调用__rmqueue函数(因为已经保护了,直接调用__rmqueue即可)从伙伴系统中分配所请求的页框(见伙伴系统一文)
             */
            if (page == NULL) {
                spin_lock_irqsave(&zone->lock, flags);
                page = __rmqueue(zone, order);
                spin_unlock_irqrestore(&zone->lock, flags);
            }
    
            /**
             * 如果内存请求得到满足,函数就初始化(第一个)页框的页描述符
             */
            if (page != NULL) {
                BUG_ON(bad_range(zone, page));
                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值