这个函数用于计算batchsize。staticint __devinit zone_batchsize(struct zone *zone){int batch;/** The per-cpu-pages pools are set to around 1000th of the* size of the zone.But no more than 1/2 of a meg.** OK, so we don't know how big the cache is.So guess.*/batch = zone->present_pages / 1024;if (batch * PAGE_SIZE > 512 * 1024)batch = (512 * 1024) / PAGE_SIZE;batch /= 4;/* We effectively *= 4 below */if (batch < 1)batch = 1;/** Clamp the batch to a 2^n - 1 value. Having a power* of 2 value was found to be more likely to have* suboptimal cache aliasing properties in some cases.** For example if 2 tasks are alternately allocating* batches of pages, one task can end up with a lot* of pages of one half of the possible page colors* and the other with pages of the other colors.*/batch = (1 << (fls(batch + batch/2)-1)) - 1;return batch;}对于64M内存,batch计算的结果为3。
内核中当高速缓存的页面较多时,会将部分页面切换到可用内存的链表中,这个操作由free_pages_bulk函数完成:/** Frees a list of pages. * Assumes all pages on list are in same zone, and of same order.* count is the number of pages to free.** If the zone was previously in an "all pages pinned" state then look to* see if this freeing clears that state.** And clear the zone's pages_scanned counter, to hold off the "all pages are* pinned" detection logic.*/staticvoid free_pages_bulk(struct zone *zone, int count,struct list_head *list, int order){spin_lock(&zone->lock);zone->all_unreclaimable = 0;zone->pages_scanned = 0;while (count--) {struct page *page;VM_BUG_ON(list_empty(list));page = list_entry(list->prev, struct page, lru);/* have to delete it as __free_one_page list manipulates */list_del(&page->lru);__free_one_page(page, zone, order);}spin_unlock(&zone->lock);}因为在页面回收时是将要回收的页面插入到双链表的表头,而从上述函数中可以看出,在将页面切换出高速缓存的时候,也是从链表头按顺序进行的,因此整个切换策略就是后进先出,即最后进入高速缓存的先切换出去。
1.1.5缓存填充
当向内核请求一个页时,如果其order为0,即单页,那么内核将从缓存中进行分配,如果缓存中没有可用的页,那么内核将调用rmqueue_bulk函数取一些页填充到缓存中。/* * Obtain a specified number of elements from the buddy allocator, all under* a single hold of the lock, for efficiency.Add them to the supplied list.* Returns the number of new pages which were placed at *list.*/staticint rmqueue_bulk(struct zone *zone, unsignedint order, unsignedlong count, struct list_head *list){int i;spin_lock(&zone->lock);for (i = 0; i < count; ++i) {struct page *page = __rmqueue(zone, order);if (unlikely(page == NULL))break;list_add_tail(&page->lru, list);}spin_unlock(&zone->lock);return i;}就是调用__rmqueue函数取得指定数量的可用内存页。需要注意的是内核调用此函数时使用的参数:pcp->count = rmqueue_bulk(zone, 0,pcp->batch, &pcp->list);order为0,而要求的count为缓存指定的batch,对于64M内存,此值为3。