// 重新填充缓存中的对象
static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
{
int batchcount; // 批量分配的数量
struct kmem_cache_node *n; // 内存缓存节点
struct array_cache *ac, *shared; // CPU缓存、共享缓存
int node; // 节点索引
void *list = NULL; // 空闲对象链表
struct page *page; // 内存页
ac = cpu_cache_get(cachep); // 获取当前CPU缓存
batchcount = ac->batchcount; // 获取批量分配数量
// 如果CPU缓存没有被访问过且批量分配数量超过阈值,则将批量分配数量限制为阈值
if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
batchcount = BATCHREFILL_LIMIT;
}
// 根据节点索引获取内存缓存节点
n = get_node(cachep, node);
BUG_ON(ac->avail > 0 || !n); // 检查CPU缓存是否有可用对象,以及内存缓存节点是否存在
shared = READ_ONCE(n->shared); // 获取共享缓存
// 如果没有空闲对象,并且没有共享空闲对象可分配,则跳转到direct_grow标签处执行直接增长逻辑
if (!n->free_objects && (!shared || !shared->avail))
goto direct_grow;
spin_lock(&n->list_lock);
shared = READ_ONCE(n->shared); // 再次获取共享缓存
// 尝试从共享缓存中重新填充CPU缓存
if (shared && transfer_objects(ac, shared, batchcount)) {
shared->touched = 1;
goto alloc_done;
}
while (batchcount > 0) {
page = get_first_slab(n, false); // 获取第一个内存页
// 如果没有可用的内存页,则跳转到must_grow标签处执行增长逻辑
if (!page)
goto must_grow;
check_spinlock_acquired(cachep); // 检查自旋锁是否被占用
// 分配一块连续的对象,并将其加入空闲对象链表
batchcount = alloc_block(cachep, ac, page, batchcount);
fixup_slab_list(cachep, n, page, &list);
}
must_grow:
n->free_objects -= ac->avail; // 更新空闲对象数量
alloc_done:
spin_unlock(&n->list_lock); // 解锁内存缓存节点链表
fixup_objfreelist_debug(cachep, &list); // 调整空闲对象链表的调试信息
direct_grow:
if (unlikely(!ac->avail)) {
// 检查是否可以使用pfmemalloc分配器中的对象
if (sk_memalloc_socks()) {
void *obj = cache_alloc_pfmemalloc(cachep, n, flags);
if (obj)
return obj;
}
// 开始进行直接增长操作
page = cache_grow_begin(cachep, gfp_exact_node(flags), node);
ac = cpu_cache_get(cachep); // 再次获取CPU缓存
if (!ac->avail && page)
alloc_block(cachep, ac, page, batchcount);
cache_grow_end(cachep, page);
// 如果CPU缓存仍然没有可用对象,则返回NULL
if (!ac->avail)
return NULL;
}
ac->touched = 1; // 标记CPU缓存已使用过
return ac->entry[--ac->avail]; // 返回分配到的内存对象
}
这段代码是Linux内核中与slab分配器相关的函数片段,用于重新填充缓存中的对象。在此函数中,根据当前CPU缓存和节点信息,尝试从共享缓存或者内存页中重新填充CPU缓存的对象。如果无法找到可用对象,则会执行直接增长逻辑来扩大内存资源,并最终返回分配到的内存对象。
内容由零声教学AI助手提供,问题来源于学员提问




