在每个zone中,free_area都有一个结构用来保存这个区域的空闲页面。
zone->free_area[MAX_ORDER]
其中MAX_ORDER为11,即有11空闲页面列表,free_area结构如下:
struct free_area {
struct list_head free_list[MIGRATE_TYPES];
unsigned long nr_free;
};
其中MIGRATE_TYPES为5。
分配页面时__rmqueue_smallest从zone的free_area摘下2^order页面,代码如下:
struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
int migratetype)
{
unsigned int current_order;
struct free_area * area;
struct page *page;
/* Find a page of the appropriate size in the preferred list */
for (current_order = order; current_order < MAX_ORDER; ++current_order) {
area = &(zone->free_area[current_order]);
if (list_empty(&area->free_list[migratetype]))
continue;
page = list_entry(area->free_list[migratetype].next,
struct page, lru);
list_del(&page->lru);
rmv_page_order(page);
area->nr_free--;
expand(zone, page, order, current_order, area, migratetype);
return page;
}
return NULL;
}
__rmqueue_smallest遍历zone区域的free_area,找到一个有空闲页面的free_area链表,并且order值大于要分配页面order。
expand()则是当free_area的页面数比2^order大时,则需要把剩余的页面归还给伙伴系统,不至于丢失页面,代码如下:
static inline void expand(struct zone *zone, struct page *page,
int low, int high, struct free_area *area,
int migratetype)
{
unsigned long size = 1 << high;
while (high > low) {
area--;
high--;
size >>= 1;
VM_BUG_ON(bad_range(zone, &page[size]));
list_add(&page[size].lru, &area->free_list[migratetype]);
area->nr_free++;
set_page_order(&page[size], high);
}
}
阅读(1854) | 评论(0) | 转发(0) |