news 2026/10/24 0:51:06

slub get_node

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
slub get_node

SLUB 里访问per-NUMA-node 结构的最基础辅助函数,一行代码,但背后涉及 SLUB 的节点组织和编译配置。

一、函数本身

static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node) { return s->node[node]; }

功能

给定缓存s和 NUMA 节点号node,返回该缓存在这个节点上的struct kmem_cache_node。

调用形式:

struct kmem_cache_node *n = get_node(s, node);

get_partial()、__slab_free()、add_partial()、discard_slab()等慢路径函数,第一步几乎都是拿n,然后在n->list_lock保护下操作n->partial等。

二、s->node是什么

在struct kmem_cache里有:

struct kmem_cache_node *node[MAX_NUMNODES];
  • 这是一个按节点号索引的指针数组,每个元素指向该缓存的对应节点的kmem_cache_node。

  • MAX_NUMNODES由CONFIG_NODES_SHIFT决定:非 NUMA 系统通常为 1,NUMA 系统可达 64、1024 等。

所以get_node(s, node)本质就是数组下标访问,O(1)、无锁、无分支。

三、为什么用static inline

  • 极高频调用:慢路径每一步都要用,而且常作为参数传递。

  • 极简单:只有一次数组访问,函数调用开销相对过大。

  • 内联后编译器可把它折叠进调用点,甚至把s->node[node]直接编进后续代码,消除中间变量。

这是内核里“简单访问器一律内联”的典型做法。

四、与 NUMA 配置的关系

SLUB 的node数组组织随 NUMA 配置变化:

配置MAX_NUMNODESs->node[]
非 NUMA(CONFIG_NUMA关)1只有一个元素,node恒为 0
NUMA(CONFIG_NUMA开)多每个节点一项

因此get_node(s, node)在非 NUMA 下等价于s->node[0],编译器可能把整个节点参数优化掉。SLUB 代码不需要为此写两套,靠这个访问器屏蔽差异。

五、与strict_numa的呼应

#ifdef CONFIG_NUMA static DEFINE_STATIC_KEY_FALSE(strict_numa); #endif
  • 默认(strict_numa关):get_node()拿到的节点可能与请求节点不同,SLUB 允许跨节点取 slab,优先保证分配成功。

  • 开启strict_numa:分配时严格要求从请求节点的kmem_cache_node取,get_node(s, node)里的node必须是目标节点,不匹配就可能失败或走特殊路径。

ALLOC_NODE_MISMATCH统计的就是“实际 slab 所在节点 ≠ 请求节点”的情况,判断依据正是通过get_node()拿到的 node 信息。

六、对比this_cpu_ptr

SLUB 的两类后端访问方式形成对称:

访问粒度方式路径
this_cpu_ptr(s->cpu_slab)per-CPU隐式(当前 CPU)快速路径
get_node(s, node)per-node显式传node慢路径
  • per-CPU 用this_cpu_ptr,因为“当前 CPU”是隐式的,且要配合preempt_disable()/migrate_disable()。

  • per-node 用get_node(s, node),因为节点号是显式参数(可能来自numa_node_id()、请求参数、对象所在页等)。

七、使用示例(慢路径骨架)

static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, ...) { struct kmem_cache_node *n; ... n = get_node(s, node); // 拿到目标节点的 node 结构 spin_lock(&n->list_lock); slab = get_partial(s, n, ...); // 从 n->partial 找 spin_unlock(&n->list_lock); ... }
static void __slab_free(struct kmem_cache *s, struct slab *slab, void *object, ...) { struct kmem_cache_node *n; ... n = get_node(s, slab_nid(slab)); // 用 slab 实际所在节点 spin_lock(&n->list_lock); ... spin_unlock(&n->list_lock); }

注意两者传的node来源不同:

  • 分配:node是请求节点(可能来自kmalloc_node参数或numa_node_id())。

  • 释放:node是对象所在 slab 的实际节点(slab_nid(slab)),因为释放必须回到对象真正的归属节点。

八、一句话总结

get_node(s, node)是 SLUB 访问per-NUMA-node 结构的访问器:s->node[node]一次数组下标,static inline保证零开销。它屏蔽了 NUMA 与非 NUMA 的差异,是慢路径拿到list_lock和partial列表的入口。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 0:42:24

JAVA_HOME配置失效的五大原因与精准排查指南

1. 这个报错不是Java没装好,而是环境在“装睡”刚看到这条报错:“The supplied javaHome seems to be invalid. I cannot find the java executable”,很多人的第一反应是——赶紧重装JDK!我试过三次,删了装、装了删&a…

作者头像 李华
网站建设 2026/10/24 0:42:18

.env与.gitignore:现代Web开发的配置安全双基石

1. 项目概述:为什么两个小文件能决定一个项目的生死存亡你有没有遇到过这样的情况:刚把代码推到远程仓库,第二天就收到安全团队的紧急通知——数据库密码、API密钥、测试用的支付密钥全被提交上去了;或者新同事克隆完项目&#xf…

作者头像 李华
网站建设 2026/10/24 0:39:58

C++学生成绩管理系统源码实战:从结构体到文件持久化与避坑指南

简介:这是一套面向高校计算机相关专业学生的C学生成绩管理系统完整源码,适合用作毕业设计、课程设计参考,也便于想研究C项目开发与数据库应用的开发者学习。系统实现了教师与学生双角色登录,学生可查看个人全部信息,教…

作者头像 李华
网站建设 2026/10/24 0:21:12

Java超市管理系统源码实战:SQL Server后端配置与JDBC连接避坑指南

简介:这份资源是面向Java初学者与课程设计开发者的超市管理系统项目源码,基于Java语言结合SQL Server数据库实现,适合作为毕业设计、课程实训或自学练手参考。系统涵盖商品管理、库存控制、销售记录、会员管理与报表生成等模块,技…

作者头像 李华
网站建设 2026/10/24 0:21:04

llcbench实战:缓存、浮点与MPI基准测试及调优避坑

简介:LLCbench(Low-Level Characterization Benchmarks)是一套面向 Linux 平台的底层性能表征测试工具集,集成了 MPBench、CacheBench 与 BLASBench 三种测试方法,本包聚焦其中的 CacheBench,用于测量处理器…

作者头像 李华