我正在构建自己的内存池作为 Linux 内核模块。我修改了页框分配函数,以便用户级进程从我的内存池中获取页框。这工作正常。然后我尝试修改页面释放功能,以便在进程释放页面框架时回收它们。但是每当我启用页面回收时,我都无法启动任何程序,并在控制台中打印“分段错误”消息。
我alloc_page(__GFP_HIGHMEM | __GFP_MOVABLE | __GFP_ZERO)
用来创建我的内存池,它进入每 cpu 页面帧缓存,所以我得到的每个页面都有一个使用计数器(page->_count)设置为 1。
对于页面释放,我在 中插入了几行free_pcppages_bulk()
,当 per-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 以在创建内存池时恢复初始页面状态。
对此有何建议?或者有没有更好的方法将页框释放到我的内存池而不是好友系统?