LINUX内存管理之slab机制

引言

slab是Linux在伙伴系统之上的一种内存管理机制。伙伴系统最小的内存处理大小为4k(即一页的内存大小),然而,实际使用内存过程中,很多都是小内存,为了提高内存申请释放效率防止内存碎片的产生防止内存连续分配导致CPU缓存命中率低,linux在伙伴系统之上设计出slab机制来解决这些问题。slab可以理解为它是linux内核的对象池

1 概述

整个slab机制的数据结构如下图。
在这里插入图片描述
注1 :page描述符中很多字段是以union形式存在,所以最好结合源码查看。

1.1 kmem_cache

kmem_cache缓存对象,每个kmem_cache对应一种object类型。各个字段意义如下:

  • name: 缓存名称;
  • list: 缓存链表,所有的kmem_cache都会连接成一个全局的链表;
  • refcount: 应用计数;
  • object_size:对象大小;
  • align:对象以align个字节对齐;
  • ctor:对象初始化函数指针,可以理解为c++的构造函数;
  • node: 保存kmem_cache_node数组,在NUMA架构中,每个内存节点对应一个缓存节点来分开管理;
  • cpu_cache:为每个cpu变量的对象缓存池,用于加速对象的分配。

1.2 kmem_cache_node

kmem_cache_node是对于不同内存结点的缓存结构体。主要由三个list_head,即三个存储slab描述符的链表。slab是一组连续的页框,这些页框用来分配object所需的内存。
slab描述符结合在page描述符中,也就是page描述符描述slab的时候,就是slab描述符。至少在4.0的源码中看到的是这样。书本所说,slab描述符存储在两个地方:

  • 外部slab描述符 :存放在slab外部,位于cache_sizes指向的一个不适合ISA DMA的普通高速缓存中。
  • 内部slab描述符:存放在slab内部,位于分配给slab的第一个页框的起始位置。

当对象小于512MB时,或者当内部碎片为slab描述符和对象描述符在slab中留下足够的空间时,slab分配器选择第二种方案。如果slab描述符存放在slab外部,那么高速缓存描述符的flags字段中的CFLGS_OFF_SLAB标志置为1;否则它被置为0。
三个存储slab描述符的链表字段意义如下:

  • slabs_free: 空闲slab,即该slab还没有分配一个对象;
  • slabs_partial: 部分slab, 即slab已经分配了对象,但是还有部分可以继续分配;
  • slabs_full: 满slab,即所有可分配的对象都已分配完,无法再继续分配。

三个链表会随着状态迁移。

1.3 page

page为页描述符字段,同时,当嵌套的slab描述字段中的flags为PG_slab时,表明是一个slab描述符。在page描述符结构体中有两个关键字段s_mem和freelist。

  • s_mem: 指向这段连续页框中第一个对象;
  • freelist: 指向空闲对象链表。

整个page所指向的内存结构如下图:
在这里插入图片描述
整个内存前面为freelist指向;后面为object数组,s_mem指向object 1的起始地址;中间为对象描述符数组。
对象申请释放过程如下:

  • 初始状态
    在这里插入图片描述
    假设有五个对象的大小可以分配,才开始都空闲,freelist指向0,page的activie为0。
  • 连续分配三个对象
    在这里插入图片描述
    连续分配三个对象后,freelist指向为3,page的activie为3。
  • 释放对象1
    在这里插入图片描述
    释放对象1的时候,首先将page的activie减1变为2,然后将1和active所在的2交换位置。然后,后面申请对象的时候就直接申请对象1了。

其实关于slab的对象申请和释放远远比这个复杂,这种方式会造成CPU缓存行命中率降低。slab采用着色机制来打乱对象的分配顺序。

2 源码解读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值