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. */ /*从PCP中释放count个页面到伙伴系统中*/ static void free_pcppages_bulk(struct zone *zone, int count, struct per_cpu_pages *pcp) { int migratetype = 0; int batch_free = 0; /* * 虽然管理区可以按照CPU节点分类,但是也可以跨CPU节点进行内存分配, * 因此这里需要用自旋锁保护管理区 * 使用每CPU缓存的目的,也是为了减少使用这把锁。 */ spin_lock(&zone->lock); /* all_unreclaimable代表了内存紧张程度,释放内存后,将此标志清除 */ zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE); zone->pages_scanned = 0;/* pages_scanned代表最后一次内存紧张以来,页面回收过程已经扫描的页数。 目前正在释放内存,将此清0,待回收过程随后回收时重新计数 */ /*增加管理区空闲页数*/ __mod_zone_page_state(zone, NR_FREE_PAGES, count); while (count) { struct page *page; struct list_head *list; /* * Remove pages from lists in a round-robin fashion. A * batch_free count is maintained that is incremented when an * empty list is encountered. This is so more pages are freed * off fuller lists instead of spinning excessively around empty * lists */ do {/*从pcp的三类链表中找出不空的一个,释放*/ batch_free++;/*参看英文注释*/ if (++migratetype == MIGRATE_PCPTYPES) migratetype = 0; list = &pcp->lists[migratetype]; } while (list_empty(list)); do { page = list_entry(list->prev, struct page, lru); /* must delete as __free_one_page list manipulates */ list_del(&page->lru); /*释放单个页面到伙伴系统,注意这里的分类回收*/ __free_one_page(page, zone, 0, migratetype); trace_mm_page_pcpu_drain(page, 0, migratetype); } while (--count && --batch_free && !list_empty(list)); } spin_unlock(&zone->lock); }
Linux内存管理之伙伴系统(内存释放)
内容版权声明:除非注明,否则皆为本站原创文章。