日志标签 ‘页框释放’

伙伴算法的实现-释放页框

2012年3月12日

与页框分配函数的整个实现过程相比,页框释放函数的实现要简单的多。常用的页框分配函数接口有 __free_pages()和__free_page(),很明显后者是前者的特殊情况。

#define __free_page(page) __free_pages((page), 0)

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

释放页框函数在一开始也兵分两路:如果分配阶为0,那么直接通过per-CPU机制来释放单一页框;否则通过__free_pages_ok()释放所申请的页框块。

1.__free_pages_ok()

该函数内部经过一些检查,这些检查是确保稍候对页框的释放是安全的,最终会调用free_one_page(),而它内部又封装了__free_one_page()。内核中函数之间的这种多次封装是很常见的,上层函数通过这种封装可以屏蔽某些参数,而底层的被封装的函数也可以被多种情况所引用。

static void __free_pages_ok(struct page *page, unsigned int order)
{
        …………
        free_one_page(page_zone(page), page, order, get_pageblock_migratetype(page));
        …………
}

static void free_one_page(struct zone *zone, struct page *page, int order,int migratetype)
{
        spin_lock(&zone->lock);
        zone->all_unreclaimable = 0;
        zone->pages_scanned = 0;

        __mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order);
        __free_one_page(page, zone, order, migratetype);
        spin_unlock(&zone->lock);
}

在调用核心函数__free_one_page()之前,还需更新当前内存管理区的空闲页面数,其实就是将(1<vm_stat[NR_FREE_PAGES]上,其中vm_stat是一个对内存区进行信息统计的数组。

2.__free_one_page()

该函数按照伙伴算法的回收原理实现,从所请求的分配阶order开始,为当前页框块尽可能的寻找伙伴,进而合并成更大的页框块。在进入循环之前,先得到释放页框块的索引page_idx。

static inline void __free_one_page(struct page *page,
                struct zone *zone, unsigned int order,
                int migratetype)
{
        unsigned long page_idx;

        if (unlikely(PageCompound(page)))
                if (unlikely(destroy_compound_page(page, order)))
                        return;

        VM_BUG_ON(migratetype == -1);

        page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1);

        VM_BUG_ON(page_idx & ((1 << order) - 1));
        VM_BUG_ON(bad_range(zone, page));

        while (order < MAX_ORDER-1) {
                unsigned long combined_idx;
                struct page *buddy;

                buddy = __page_find_buddy(page, page_idx, order);
                if (!page_is_buddy(page, buddy, order))
                        break;

                list_del(&buddy->lru);
                zone->free_area[order].nr_free--;
                rmv_page_order(buddy);
                combined_idx = __find_combined_index(page_idx, order);
                page = page + (combined_idx - page_idx);
                page_idx = combined_idx;
                order++;
        }
        set_page_order(page, order);
        list_add(&page->lru,
                &zone->free_area[order].free_list[migratetype]);
        zone->free_area[order].nr_free++;
}

在每次的遍历过程中,通过__page_find_buddy()为当前页框块找一个伙伴buddy,这个伙伴可能在当前页框块之前,也可能在其之后。通过page_is_buddy()判断刚才找到的buddy是否能和欲释放的页框块进行合并。如果可以合并,则将这个buddy从它所处的页框块链表中删除,并更新nr_free的值,然后再通过rmv_page_order()更新buddy页框块首页框的相关标志。

接下来,通过__find_combined_index()寻找合并后页框块的索引combined_idx。由于page永远都指向要释放页框块的首页框描述符,因此根据combined_idx更新page和page_idx。同时,由于成功进行了伙伴合并,因此最后再将分配阶order加一。一旦没有可合并的伙伴(通过page_is_buddy()而break),整个合并过程也将结束,即退出循环。

接下来就要将页框块进行释放,其实就是将合并后的页框块(也许并没有合并,还是合并之前的那个页框块)插入到具体的分配阶链表中,并设置首页框的相关标志,将nr_free加一。要释放的页框块由page指定,order则指明了应该将这个页框块插入到哪一个页框块链表中,而migratetype则更具体的指明了要将该页框块插入哪一个迁移列表中。这些操作和之前伙伴算法中页框分配的过程是相反的。

3.__page_find_buddy()

前文已经说过,这个函数用于寻找当前要释放页框块的伙伴。具体的办法是先通过异或求出伙伴的索引,再根据此索引求出伙伴页框块的首页框描述符。

static inline struct page *
__page_find_buddy(struct page *page, unsigned long page_idx, unsigned int order)
{
        unsigned long buddy_idx = page_idx ^ (1 << order);

        return page + (buddy_idx - page_idx);
}

由于buddy_idx-page_idx的值可能为正也可能为负,因此伙伴页框块可能在当前页框块之前,也可能在其之后。

4.__find_combined_index()

该函数可以获得合并后页框块的索引。如果伙伴页框在当前页框块之后,那么这个函数返回的索引还是原来的值page_idx。如果伙伴页框在当前页框之前,那么合并后页框的索引其实是伙伴页框的索引。

static inline unsigned long
__find_combined_index(unsigned long page_idx, unsigned int order)
{
        return (page_idx & ~(1 << order));
}

至此基于伙伴算法的页框分配过程完毕。

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key