我正在构建自己的内存池作为Linux内核模块。我修改了页面框架分配功能,以便用户级别的进程从我的内存池中获取页面框架。这很好用。然后我尝试修改页面释放功能,以便在进程释放它们时回收页面框架。但每当我启用页面回收时,我都无法启动任何程序,并在控制台中打印出“分段错误”消息。
我正在使用alloc_page(__GFP_HIGHMEM | __GFP_MOVABLE | __GFP_ZERO)
创建我的内存池,它进入每个cpu页面帧缓存,因此我得到的每个页面都有一个使用计数器(page-> _count)设置为1。
对于页面释放,我在free_pcppages_bulk()
中插入了几行,当每个cpu页面帧缓存想要将一些空闲页面刷回Buddy系统时调用该行:
static void free_pcppages_bulk(struct zone *zone, int count,
struct per_cpu_pages *pcp)
{
int migratetype = 0;
int batch_free = 0;
int to_free = count;
spin_lock(&zone->lock);
zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
zone->pages_scanned = 0;
while (to_free) {
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 {
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);
/* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
/* --ADDED BY ME-- */
if(colored_free != NULL) { /* if my memory pool is created */
if(!colored_free(page, zone)) { /* if it fails, free page to Buddy system */
__free_one_page(page, zone, 0, page_private(page));
}
}
else {
__free_one_page(page, zone, 0, page_private(page));
}
trace_mm_page_pcpu_drain(page, 0, page_private(page));
} while (--to_free && --batch_free && !list_empty(list));
}
__mod_zone_page_state(zone, NR_FREE_PAGES, count);
spin_unlock(&zone->lock);
}
在colored_free()
中,我只是将页面描述符插入页面空闲列表中。由于页面使用计数器在被释放到Buddy系统时被设置为0,因此我将其重置为1以在创建内存池时恢复初始页面状态。
对此有何建议?或者有更好的方法将页面帧释放到我的内存池而不是Buddy系统吗?