热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

slub释放过程do_slab_free

do_slab_free一、快速路径if(likely(pagec-page)){void**freelistREAD_ONCE(c-freelist);set_freep

do_slab_free


一、快速路径

if (likely(page == c->page)) {void **freelist = READ_ONCE(c->freelist);set_freepointer(s, tail_obj, freelist);if (unlikely(!this_cpu_cmpxchg_double(s->cpu_slab->freelist, s->cpu_slab->tid,freelist, tid,head, next_tid(tid)))) {note_cmpxchg_failure("slab_free", s, tid);goto redo;}stat(s, FREE_FASTPATH);
} else__slab_free(s, page, head, tail_obj, cnt, addr);
1、要释放的对象正好在cpu本地缓存中;
2、set_freepointer函数:将要释放的object加入到空闲的object链表中,并且为链表中代替freelist为第一个空闲的object,即相当于object->next = c->freelist;
3、重新分配freelist,这里是将c->freelist = head(head即目标object);

在这里插入图片描述


二、慢速路径

进入__slab_free函数,大致框架如下:

do {if (unlikely(n)) {spin_unlock_irqrestore(&n->list_lock, flags);n = NULL;}prior = page->freelist;counters = page->counters;set_freepointer(s, tail, prior);new.counters = counters;/** 1、frozen=0,说明该slab在node中;frozen=1,则说明该slab在slab_cpu缓存中;* 2、inuse=0,说明该slab中没有正在使用的object;inuse=objects,则说明该slab为full* 3、prior=0,说明目标object在c->page中或者在s->slab_cpu->partital、s->node->partital中且无可分配的object*/was_frozen = new.frozen;new.inuse -= cnt;/** 下面需要对目标object释放的情况进行划分:* (1)inuse=0 && was_frozen=0:目标object在node节点中,且释放后该slab中的object 全部未分配,此时该slab可以释放到伙伴系统或者不处理;* (2)prior=0 && was_frozen=0:释放前在full的slab链表中,释放后为半满状态;* (3)was_frozen=1:该slab在s->slab_cpu->partital缓存中;*/if ((!new.inuse || !prior) && !was_frozen) { //(1)(2)if (kmem_cache_has_cpu_partial(s) && !prior) { //(2)new.frozen = 1;} else { //(1)n = get_node(s, page_to_nid(page));spin_lock_irqsave(&n->list_lock, flags);}
} while (!cmpxchg_double_slab(s, page,prior, counters,head, new.counters,"__slab_free"));
/* * 前面的while循环中对目标object释放进行了分类和简单的预处理,下面针对这几种情况进行后续的处理。* 包括是否将空的slab释放回伙伴系统以及维护slab_cpu->patital和node->partital链表;*/if (likely(!n)) {if (new.frozen && !was_frozen) { //(2)node节点,半满put_cpu_partial(s, page, 1);//将slab释放到slab_cpu->partital链表中stat(s, CPU_PARTIAL_FREE);}if (was_frozen) //slab_cpu->partital中,则不处理直接返回stat(s, FREE_FROZEN);return;
}
//释放object后该slab变为free,此时需要对比node->partital中slab的数量和内核定义的最小min大小
//如果n->nr_partial >= s->min_partial,则将slab释放到伙伴系统;
//如果n->nr_partial min_partial, 则不处理;
if (unlikely(!new.inuse && n->nr_partial >= s->min_partial))goto slab_empty;//未定义CONFIG_SLUB_CPU_PARTITAL时走这个流程;
if (!kmem_cache_has_cpu_partial(s) && unlikely(!prior)) {remove_full(s, n, page);//从full链表中移除add_partial(n, page, DEACTIVATE_TO_TAIL);//加入到node->partital链表中stat(s, FREE_ADD_PARTIAL);
}
spin_unlock_irqrestore(&n->list_lock, flags);
return;
slab_empty:if (prior) {/** Slab on the partial list.*/remove_partial(n, page);//将该slab从链表中删除,并将nr_partital减一stat(s, FREE_REMOVE_PARTIAL);} else {/* Slab must be on the full list */remove_full(s, n, page);}spin_unlock_irqrestore(&n->list_lock, flags);stat(s, FREE_SLAB);discard_slab(s, page);
}

所以从代码来看,主要分成以下几种情况:

1、目标object在s->slab_cpu->partital中,直接释放即可,无需后续的处理;

在这里插入图片描述

2、目标object在s->node中,释放完object后slab中的object全为free;此时需要考虑空的slab如何处理

(1)s->node->partital中slab的个数大于等于min_partital时,将该slab释放到伙伴系统;

(2)s->node->partital中slab的个数小于min_partital时,该slab依然保留在s->node->partital链表中;

3、目标object在s->node中,释放object前slab为full,没有可分配object,释放完后为半满状态;此时需要将半满的slab从full链表中删除并加入到s->slab_cpu的链表中,需要注意s->slab_cpu->partital中也需要判断下所有的free的object的数量是否超过了规定的水位,判断后在决定是否加入;

lab从full链表中删除并加入到s->slab_cpu的链表中,需要注意s->slab_cpu->partital中也需要判断下所有的free的object的数量是否超过了规定的水位,判断后在决定是否加入;


推荐阅读
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
author-avatar
永远在等一个人--嘉儿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有