slub分配流程-kmem_cache_alloc函数
slub分配流程-kmem_cache_alloc函数
static __always_inline void *slab_alloc_node(struct kmem_cache *s,gfp_t gfpflags, int node, unsigned long addr)
{void *object;struct kmem_cache_cpu *c;struct page *page;unsigned long tid;s = slab_pre_alloc_hook(s, gfpflags);if (!s)return NULL;
redo:/* * 保证获取到的tid和kmem_cache_cpu是同一个cpu上面的,以避免中间发生cpu切换* 一旦不匹配则在do循环中重新获取直到匹配为止;*/do {tid = this_cpu_read(s->cpu_slab->tid);c = raw_cpu_ptr(s->cpu_slab);} while (IS_ENABLED(CONFIG_PREEMPTION) &&unlikely(tid != READ_ONCE(c->tid)));barrier();object = c->freelist;page = c->page;/** 从这里判断进入slowpath还是fastpath* 进入fastpath的条件:* 1、page与当前节点node匹配* 2、c->freelist != NULL*/if (unlikely(!object || !node_match(page, node))) {object = __slab_alloc(s, gfpflags, node, addr, c);stat(s, ALLOC_SLOWPATH);/* 标记slowpath状态 */} else {void *next_object = get_freepointer_safe(s, object);if (unlikely(!this_cpu_cmpxchg_double(s->cpu_slab->freelist, s->cpu_slab->tid,object, tid,next_object, next_tid(tid)))) {note_cmpxchg_failure("slab_alloc", s, tid);goto redo;}prefetch_freepointer(s, next_object);stat(s, ALLOC_FASTPATH);/* 标记fastpath状态 */}maybe_wipe_obj_freeptr(s, object);if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)memset(object, 0, s->object_size);slab_post_alloc_hook(s, gfpflags, 1, &object);return object;
}
从图中可以大致可以分成4种情况:
1、c->freelist != NULL;
2、c->freelist = NULL,c->partital != NULL;
3、c->partital = NULL,n->partital != NULL;
4、n->partital = NULL的情况;
第一种情况,c->freelist != NULL,即在本地的slab缓存池不为空,这种分配即fastpath操作,精简代码后如下所示:
void *next_object = get_freepointer_safe(s, object); /*(1)*/
if (unlikely(!this_cpu_cmpxchg_double( /*(2)*/s->cpu_slab->freelist, s->cpu_slab->tid,object, tid,next_object, next_tid(tid)))) {note_cmpxchg_failure("slab_alloc", s, tid);goto redo;}
prefetch_freepointer(s, next_object); /*(3)*/
stat(s, ALLOC_FASTPATH);/* 标记fastpath状态 */
/* * (1)获取下一个空闲的object赋值给next_object* (2)原子操作,主要做了三件事:**重定向首指针指向当前CPU空间;**判断tid和freelist未被修改;**用新的tid和freelist覆盖旧的数据:s->cpu_slab->freelist = next_objects->cpu_slab->tid = next_tid(tid)此时c->freelist就指向了新的下一个空闲对象;* (3)刷新数据,主要是下一个空闲object的地址指向;*/
图解如下图所示:
其余的几种情况均属于slowpath,在__slab_alloc中执行,
当kmem_cache_cpu的freelist没有可用的object时,需要去kmem_cache_cpu的partital链表中寻找可用的object,如果c->partial存在,则可找到对应的object,对应的函数主体如下:
if (slub_percpu_partial(c)) {page = c->page = slub_percpu_partial(c);/*(1)*/slub_set_percpu_partial(c, page); /*(2)*/stat(s, CPU_PARTIAL_ALLOC); goto redo; /*(3)*/}/** (1)slub_percpu_partial(c)函数实际上是返回c->partial,赋值给c->page;* (2)更新c->partial的链表,将c->partial指向下一个page链表中的对象;实际上就是:c->partial = page->next;(3)返回redo标签,重新进行freelist的获取和更新;*/
图解如下图所示:
当kmem_cache_cpu的freelist和partital链表都没有可用的object的时候,就需要去kmem_cache_node中去寻找可用的object。主体函数为get_partial_node:
static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,struct kmem_cache_cpu *c, gfp_t flags)
{struct page *page, *page2;void *object = NULL;unsigned int available = 0;int objects;if (!n || !n->nr_partial)return NULL;spin_lock(&n->list_lock);list_for_each_entry_safe(page, page2, &n->partial, slab_list) {void *t;if (!pfmemalloc_match(page, flags))continue;/*(1)*/t = acquire_slab(s, n, page, object == NULL, &objects);if (!t)break;available += objects;if (!object) {c->page = page;stat(s, ALLOC_FROM_PARTIAL);object = t;} else {put_cpu_partial(s, page, 0);stat(s, CPU_PARTIAL_NODE);}/*(2)*/if (!kmem_cache_has_cpu_partial(s)|| available > slub_cpu_partial(s) / 2)break;}spin_unlock(&n->list_lock);return object;
}
/** (1)变量partial,acquire_slab获取partial链表上slab空闲的数量,对于第一个获取到的slab,挂到c->page上;* (2)然后将后续slab挂到c->partial,直到满足其数量大于cpu_partial的一半;*/
如果在kmem_cache_cpu的freelist、partital链表以及kmem_cache_node的partital链表中都没有可用的object时,则需要调用new_slab函数从伙伴系统重新申请一页内存,此时函数主体如下:
page = new_slab(s, flags, node); /*(1)*/if (page) {c = raw_cpu_ptr(s->cpu_slab);/*(2)*/if (c->page) /*(3)*/flush_slab(s, c);freelist = page->freelist; /*(4)*/page->freelist = NULL; /*(5)*/stat(s, ALLOC_SLAB);c->page = page; /*(6)*/*pc = c;
}
/** (1)从伙伴系统以页为单位分配内存,保存在page中;* (2)获取当前cpu的kmem_cache_cpu结构;* (3)如果存在c->page,则说明当前cpu(暂不清楚)* (4)返回page中的freelist;* (5)将page中的freelist指向NULL;* (6)将新申请的page加入cpu本地缓存(c->page = page);其中(4)(5)(6)步主要是将申请的page 加入到该CPU的本地缓存中;*/
当调用new_slab失败,无法从伙伴系统获取内存时,说明系统内存不足,此时就会发生OOM;
slub分配流程-kmem_cache_alloc函数相关推荐
- Slub代码流程分析
Slub代码流程分析: slub的代码晦涩难懂,在看书或者相关资料时看似简单,再去对照代码分析时会发现被打回原形,就像数学老师推导公式和自己去推导公式一样.因此,需要静下来心来仔细研读,看完原理之后分 ...
- 深入理解JVM之对象分配流程
Java对象分配流程 栈上分配 参考: https://www.cnblogs.com/BlueStarWei/p/9358757.html (讲的很好) https://blog.csdn.net/ ...
- 【SemiDrive源码分析】【X9芯片启动流程】30 - AP1 Android Kernel 启动流程 start_kernel 函数详细分析(一)
[SemiDrive源码分析][X9芯片启动流程]30 - AP1 Android Kernel 启动流程 start_kernel 函数详细分析(一) 一.Android Kernel 启动流程分析 ...
- socket编程流程及函数详解
socket编程流程及函数详解-服务器端 一.创建socket 二.命名socket 2.1通用的socket地址结构体 2.2专用socket地址 三.监听socket 四.接受连接 五.总结 一. ...
- JVM-剖析对象内存分配流程
文章目录 Pre 对象分配流程总览 流程分解 栈上分配对象 (逃逸分析) Eden区分配对象 -XX:+UseAdaptiveSizePolicy 默认开启 Eden区域分配对象Demo 大对象直接进 ...
- LTE(4G) GUTI分配流程
目录 MME中的UE上下文 GUTI GUTI的组成 GUTI的主要作用 TA List COUNT SGW TEID eNB S1AP id eNB TEID GUTI重新分配 GUTI分配出现的异 ...
- java对象的内存分配流程
了解对象的内存分配流程对常见内存溢出问题.jvm优化有很大作用. 内存分配原则 对象栈内分配 通常理解new对象都在堆中分配存储空间,但是当(通过逃逸分析 确定)对象仅在方法内使用而未被外部访问的时候 ...
- 编写一个函数,模拟微信发红包的红包分配过程。函数有两个参数:一个参数表示红包总金额,默认值为100,另一个参数表示红包数量,默认为10。程序输入:红包总金额和红包数量;程序输出:每个红包的金额。要求:
题目 编写一个函数,模拟微信发红包的红包分配过程.函数有两个参数:一个参数表示红包总金额,默认值为100,另一个参数表示红包数量,默认为10.程序输入:红包总金额和红包数量:程序输出:每个红包的金 ...
- linux内核网络协议栈--接收流程及函数(九)
本章来看下,数据是如何从网络中接收并最后到达应用程序的. 网络层将数据链路层提供的帧组成数据包,包中封装有网络层包头,其中含有逻辑地址信息. 1.链路层 包到达机器的物理网卡时候触发一个中断,并将通过 ...
- 【Android 逆向】Android 进程代码注入原理 ( 进程注入原理 | 远程调用流程 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 )
文章目录 一.进程注入原理 二.远程调用流程 ( 获取 so 动态库地址 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 ) 一.进程注入原理 调试进程 At ...
最新文章
- 更换用installshield打包生成exe文件的图标
- php生成文字闪烁,如何用jquery实现闪烁文字效果
- 3.2 指数型生成函数
- iphone备忘录突然没了_为什么用过iPhone的人都不再想换回安卓?网友:过于真实,哭了...
- 结合CmakeList来更好地理解windows下的动态库和静态库
- python 选择题 多线程_python多线程练习题
- matlab 模态,用matlab做模态分析
- SOLD2算法详解之1 backbone(CVPR2021 源码解析)
- webview无法播放视频
- 三大 Windows 文件搜索神器 Everything、Listary、AnyTXT Searcher 功能特色与区别详解
- SprintBoot:Post请求的参数多一个逗号的解决方法
- FAT16文件系统简介
- java excel单元格背景色_POI 设置Excel单元格背景色(setFillForegroundColor)
- db4o数据库的基本操作
- Pandas中的pivot操作
- htmlcss全屏视频背景
- 【项目管理】项目选择与项目章程
- [234] 回文链表
- SQL优化的魅力!从 30248s 到 0.001s
- python爬取笔趣阁小说的代码微小调整修改