欢迎光临
我们一直在努力

slub alloc_slab_page

alloc_slab_page() 是 SLUB 中负责向伙伴系统申请物理页的底层函数,是 slab 页的“进货渠道”。它把 kmem_cache_order_objects 里编码的 order 解出来,调用伙伴系统分配 2^order 个连续页。

一、函数签名

static inline struct slab *alloc_slab_page(gfp_t flags, int node,
struct kmem_cache_order_objects oo)

参数含义
flags 分配标志(GFP_KERNEL、GFP_ATOMIC、__GFP_ZERO 等)
node 目标 NUMA 节点
oo 打包的 order + objects

返回:新分配的 struct slab *,失败返回 NULL。

二、典型实现

static inline struct slab *alloc_slab_page(gfp_t flags, int node,
struct kmem_cache_order_objects oo)
{
struct folio *folio;
struct slab *slab;
unsigned int order = oo_order(oo);

if (node == NUMA_NO_NODE)
folio = (struct folio *)alloc_pages(flags, order);
else
folio = (struct folio *)__alloc_pages_node(node, flags, order);

if (!folio)
return NULL;

slab = folio_slab(folio);
__folio_set_slab(folio);
…
return slab;
}

逻辑:

  • 解出 order:oo_order(oo)(前面讲过,x.x >> OO_SHIFT)。

  • 按节点分配:

    • NUMA_NO_NODE:用 alloc_pages(),由伙伴系统选节点。

    • 指定节点:用 __alloc_pages_node(),优先从该节点分配。

  • 失败返回 NULL:调用者(allocate_slab)据此走 ORDER_FALLBACK 或报错。

  • 转换为 slab:folio_slab(folio) 取得对应的 struct slab(较新内核里 folio/page/slab 关系紧密)。

  • 设置页标志:__folio_set_slab(folio) 标记该页为 slab 页,供后续 PageSlab() 判断。

  • 三、oo 参数的来源

    oo 来自 struct kmem_cache 的 s->oo:

    s->oo = oo_make(order, size); // calculate_order() 里算好

    alloc_slab_page() 只是消费这个打包值,取出 order 去分配。对象数由 oo_objects(oo) 在别处使用。

    四、与伙伴系统的接口

    接口场景
    alloc_pages(flags, order) 未指定节点,伙伴系统自选
    __alloc_pages_node(node, flags, order) 指定节点,优先本地
    alloc_pages_node(node, flags, order) 封装,node == NUMA_NO_NODE 时退化为 alloc_pages

    SLUB 用 __alloc_pages_node() 而非普通 alloc_pages(),是为了NUMA 亲和性:尽量从对象归属的节点分配,减少跨节点访问。

    五、node 参数的意义

    • 分配时:node 可能来自 kmalloc_node() 参数、numa_node_id(),或 NUMA_NO_NODE。

    • 释放时:不用这个函数,走 __free_pages()。

    • NUMA 严格模式(strict_numa):若开启,分配严格要求从 node 取,不匹配可能失败;默认允许回退到其他节点。

    六、分配失败与 ORDER_FALLBACK

    如果 alloc_pages() 返回 NULL:

    • 调用者 allocate_slab() 可能尝试更大的 order 或不同的对象数方案。

    • 相关统计 ORDER_FALLBACK 递增。

    • 最终仍失败则返回 NULL,kmem_cache_alloc 走错误路径。

    七、返回的是 struct slab * 而非 struct page *

    较新内核里:

    • struct slab 是独立类型,与 struct page 通过 folio 关联。

    • folio_slab(folio) 把 folio 转成 struct slab。

    • 早期版本直接用 struct page,SLUB 复用其字段;现在独立出来,更清晰。

    这也是 print_slab_info()、slab->objects、slab->inuse 等字段能直接访问的原因。

    八、与前面的呼应

    前面这里体现
    oo_order() 解出 order
    oo_objects() 在别处用对象数
    struct kmem_cache_order_objects oo 参数类型
    calculate_order() 生成 s->oo
    allocate_slab() 调用者
    ORDER_FALLBACK 分配失败的统计
    NUMA / strict_numa node 参数的作用
    __folio_set_slab() 标记页为 slab

    九、总结

    alloc_slab_page(flags, node, oo) 从打包的 oo 中解出 order,按 node 用 alloc_pages() / __alloc_pages_node() 向伙伴系统申请 2^order 个连续页,取得对应的 struct slab,设置 PageSlab 标志后返回;失败返回 NULL,由 allocate_slab() 决定回退或报错。它是 SLUB 的页级进货入口,负责 NUMA 亲和性和与伙伴系统的对接。

    赞(0)
    未经允许不得转载:171主机测评 » slub alloc_slab_page
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址