[linux kernel]slub内存管理分析(0) 导读

文章详细分析了Linux内核5.13版本中的slub内存管理算法,包括slub的结构体关系、kmalloc的申请逻辑和kfree的释放逻辑,以及slab页面的状态转换。slub作为管理小块内存的算法,其kmalloc操作涉及cpu_slab、partial列表和node的交互,而kfree则根据对象状态进行不同方式的释放。
摘要由CSDN通过智能技术生成

简介

linux 内核内存管理算法有管理页面分配的伙伴算法,和对于小块内存的slab、slob、slub算法。其中slab是slob和slub的基础,slob多用于嵌入式设备中,目前linux内核中用到的内存管理算法是slub。本次分为下面几个章节从源码出发分析slub算法。我用的源码不是最新的是linux-5.13版本,主要是最开始看的时候用的这个版本,注释都写在这里,写博客的时候懒得换最新的了,可能有一些错误,欢迎指正。

整体目录

本系列文章从slub算法的结构体分析起,包括初始化、kmalloc申请操作、kfree释放操作和最后的销毁操作以及一些其他相关知识。

[linux kernel]slub内存管理分析(0) 导读

[linux kernel]slub内存管理分析(1) 结构体

[linux kernel]slub内存管理分析(2) 初始化

[linux kernel]slub内存管理分析(2.5) slab重用

[linux kernel]slub内存管理分析(3) kmalloc

[linux kernel]slub内存管理分析(4) 细节操作以及安全加固

[linux kernel]slub内存管理分析(5) kfree

[linux kernel]slub内存管理分析(6) 销毁slab

[linux kernel]slub内存管理分析(7) MEMCG的影响与绕过

SLUB中的结构体关系图

slub 算法中涉及的结构体不多,总共只有:

  • struct kmem_cache
  • struct kmem_cache_cpu
  • struct kmem_cache_node
  • struct page

他们之间的关系如下图:

在这里插入图片描述

kmalloc 申请逻辑

逻辑图

在这里插入图片描述

逻辑简述

其实slab 就是几级缓存机制,从cpu_slab 分配最快,能从cpu_slab当前freelist 分配就从cpu_slab当前freelist 分配,不能则从partial 列表中把一个slab page拿出来放到freelist,如果还没有就从node 里找slab page,都没有再新申请slab page。

  • 首先判断请求kmalloc分配内存的大小,大于slab可以分配的上限(通常8k)则调用kmalloc_large进行分配。
    • kmalloc_large 则直接根据大小调用伙伴系统分配适当的页数。
  • 其他大小可以使用slab申请,则根据申请flag 和申请大小计算出kmalloc_caches的类型和index,获取对应的slab管理结构体。
    • 如果flag 存在ACCOUNT相关可能要切换到计数后slab,即kmalloc-cg相关slab(slab_pre_alloc_hook)
    • 获得slab 之后获取当前cpu 的cpu_slab,如果当前cpu_slabfreelist 不为空,则直接将freelist 的第一个分配返回,然后freelist向后移动,更新tid等。
    • 如果cpu_slabfreelist 为空,则看cpu_slabpartial 链表是否为空,不为空则将partial 链表第一个slab page 切换给cpu_slab freelist,然后分配,partial指向下一个slab page。
    • 如果以上都失败,说明cpu_slab无法完成分配,需要新slab,则会找到合适当前运行cpu 的内存node所属kmem_cache_node结构,查询partial 链表是否有可用slab page有的话将这个slab page给cpu_slab ,然后也从这个node取出一些slab page补充到cpu_slab->partial,然后从freelist 分配一个,跟上面一样。
    • 如果还是没有,则调用new_slab申请一个全新slab page,从新slab page的freelist 分配。

kfree 释放逻辑

逻辑图

在这里插入图片描述

逻辑简述

内存对象释放主要思路就是,如果是页面对象,则直接伙伴系统释放,如果是slab 对象,如果在cpu_slab中,在cpu_slab中释放,如果不是,则根据释放之前之后的状态(为空、为满、半满),进行不同的操作。

  • 首先找到释放的内存对象所在的page 的page结构体。如果该page不是slab,也就是说内存对象不是通过slab分配的,而是直接分配的页(大块内存),那么直接释放页。

    • 大块内存分配的时候就是从伙伴系统直接分配的页,释放的时候页通过伙伴系统释放页面(__free_pages)
  • 其他内存是通过slab分配,则通过slab释放(slab_free)

    • memcg相关处理(memcg_slab_free_hook)

    • 获取当前cpu_slab,如果要释放的内存对象正好属于当前cpu_slab(可以理解为是否是从当前cpu_slab分配的),则快速释放

      • 获取cpu_slabfreelist,将该内存对象插入freelist头部,刷新cpu_slab相关信息(do_slab_free)
    • 如果要释放的内存对象不属于当前cpu_slab,(当前slab page在cpu_slab->partial、别的cpu_slab->page、别的cpu_slab->partial、游离状态、node->partialnode->full6种情况),需要慢速释放(__slab_free)

      • 先把内存对象释放到slab page的freelist头部,更新slab page相关统计信息
      • 如果该slab page为冻结状态(说明是在cpu_slab中的三种情况)
        • 则直接结束(已经将object 放到page->freelist了,剩下的就不用管了)
      • 如果释放前该slab page是满的(freelist为空),则说明page目前是游离状态(不在任何列表中)或node->full
        • 如果开启cpu->partial,则将该slab page放到cpu_slab->partial中(从node->full中移除)
          • 如果cpu_slab->partial满了,则要将当前cpu_slab->partial中的所有slab page放到node->partial中,然后再将新的slab page放到cpu_slab->partial
        • 否则放入node->partial中(从node->full中移除)
      • 如果释放后为空,则说明目前该slab page一定处在node->partial列表中,因为如果在cpu_slab或者游离状态或node->full中不管释放完是否为空,都会在上面的步骤中处理完毕
        • 如果当前slab 管理的partial页面数量满足最小要求,则将该释放后为空的slab page释放掉(__free_pages)
        • 否则不变,继续呆在node->partial
      • 否则说明该page是本来就呆在node->partial中的半满page,并且释放后还是半满,则什么也不操作。

slab page状态转换关系图

结合kmallockfree的逻辑,可以画出slab page的状态转换关系图:

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值