热门标签 | 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的数量是否超过了规定的水位,判断后在决定是否加入;


推荐阅读
  • 本文详细介绍了如何利用 Bootstrap Table 实现数据展示与操作,包括数据加载、表格配置及前后端交互等关键步骤。 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文详细介绍了在 CentOS 7 系统上安装中文宋体字体的方法,包括操作系统的环境配置、字体管理工具的安装、字体文件的传输与缓存重建等步骤。 ... [详细]
  • 本文详细介绍了Socket在Linux内核中的实现机制,包括基本的Socket结构、协议操作集以及不同协议下的具体实现。通过这些内容,读者可以更好地理解Socket的工作原理。 ... [详细]
  • 解决Expo XDE 2.22.1版本启动错误
    根据问题描述,用户在将Expo升级至2.22.1版本后,在尝试打开项目时遇到了错误。本文提供了详细的错误分析及解决方案。 ... [详细]
  • 本文详细介绍了如何在PHP中使用Memcached进行数据缓存,包括服务器连接、数据操作、高级功能等。 ... [详细]
  • 在CentOS 7中部署Nginx并配置SSL证书
    本文详细介绍了如何在CentOS 7操作系统上安装Nginx服务器,并配置SSL证书以增强网站的安全性。适合初学者和中级用户参考。 ... [详细]
  • 本文详细介绍了如何在 Ubuntu 14.04 系统上搭建仅使用 CPU 的 Caffe 深度学习框架,包括环境准备、依赖安装及编译过程。 ... [详细]
  • Hibernate全自动全映射ORM框架,旨在消除sql,是一个持久层的ORM框架1)、基础概念DAO(DataAccessorOb ... [详细]
  • 本文探讨了如何在PHP与MySQL环境中实现高效的分页查询,包括基本的分页实现、性能优化技巧以及高级的分页策略。 ... [详细]
  • 函子(Functor)是函数式编程中的一个重要概念,它不仅是一个特殊的容器,还提供了一种优雅的方式来处理值和函数。本文将详细介绍函子的基本概念及其在函数式编程中的应用,包括如何通过函子控制副作用、处理异常以及进行异步操作。 ... [详细]
  • 本文详细介绍了在 CentOS 系统中如何创建和管理 SWAP 分区,包括临时创建交换文件、永久性增加交换空间的方法,以及如何手动释放内存缓存。 ... [详细]
  • Beetl是一款先进的Java模板引擎,以其丰富的功能、直观的语法、卓越的性能和易于维护的特点著称。它不仅适用于高响应需求的大型网站,也适合功能复杂的CMS管理系统,提供了一种全新的模板开发体验。 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • Flutter 核心技术与混合开发模式深入解析
    本文深入探讨了 Flutter 的核心技术,特别是其混合开发模式,包括统一管理模式和三端分离模式,以及混合栈原理。通过对比不同模式的优缺点,帮助开发者选择最适合项目的混合开发策略。 ... [详细]
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社区 版权所有