Linux内存管理之SLAB原理浅析。

原创 2018年04月17日 16:38:14

前言

1.以下这篇文章是2015年我所在的via-telecom小组学习内存知识时整理的笔记。最近复习内存管理又拿出来看了一遍,庆幸当时阅读时留了这份笔记,不然重头看又要花费很多时间。当时画了很多visio图片且加上了via-telecom的copyright。虽然目前via-telecom被intel收购了,为了纪念在via-telecom的岁月暂且保留这些copyright。如果涉及了版权问题,请联系我。
2。虽然最新的内核默认支持的是SLUB,但理解SLAB的原理依然对我们有帮助。所以先把SLAB的原理贴出来,下一篇分析SLUB,然后对比两者的优缺点。
3.当时分析的内核版本是基于3.x,现在已经到4.x了。源码中很多变量名/接口函数已经改变了。但是最最基本的管理方法 分配逻辑都没变,阅读时注意辨别。

为什么有了Buddy还需要SLAB?

Buddy提供了以page为单位的内存分配接口,这对内核来说颗粒度还太大了,所以需要一种新的机制,将page拆分为更小的单位来管理。
Linux中支持的主要有:slab、slub、slob。其中slob分配器的总代码量比较少,但分配速度不是最高效的,所以不是为大型系统设计,适合内存紧张的嵌入式系统。(ARM架构新内核的menucofnig中居然找不到slob的配置了,神奇。。。by 2018)
这里写图片描述
伙伴系统,通用分配器和一般内核代码之间的关系如上图所示。
slab分配器的管理数据主要划分为两大结构,管理数据结构kmem_cache(称之为缓存)和保存obj对象的各个slab,如下图片所示:
这里写图片描述
内核中所有的kmem_cache通过cache_chain连接起来。
内核初始化的时候首先创建了一个cache_cache的静态kmem_cache结构,内核后续创建新的kmem时候直接从这个cache_cache管理slab的obj中取出。

CACHE SIZE

内核在初始化的时候根据kmalloc_sizes.h文件中定义的obj大小,初始化了管理这些obj的slab,以及相关kmem_cache。
这里写图片描述
在初始化之后,系统中kmem_cache的链表大致如下。cache_chain上挂着系统中所有的kmem_cache。前面我们提到初始化的时候会根据kmalloc_sizes.h中的定义初始化好固定大小obj的slab以及对应的kmem_cache,这些kmem_cache称之为通用缓存,提供给kmalloc来使用的。kmalloc根据传入size大小来选择合适的kmem_cache,然后从他的array_cache中取出obj。所以我们可以发现kmalloc并没有malloc那么强大,kmalloc分配的时候只是去找和自己size最接近的obj,所以kmalloc分配有可能会造成内存浪费,甚至在某些情况下浪费的还不低!
这里写图片描述

两个重要数据结构(per node和per cpu)

slab分配器的两大数据结构slab和kmem_cache的连接关系如下图所示。
这里写图片描述
我们主要关心数据结构之间的连接关系,所以先看kmem_cache中的kmem_list3和array_cache这两个成员。
struct kmem_list3
kmem_list3是per node类型数据,一个node对应一个kmem_list3结构,我们的系统是UMA,所以只有一个kmem_list3结构。
kmem_list3中有三个链表slabs_partial、slabs_full、slabs_free,每个链表中挂着都是slab结构。其中,已经有部分obj被分配出去的slab均挂在slabs_partial下;全部obj都被分配出去的slab挂在slabs_full下;全部obj都未分配出去的slab挂在slabs_free下。
struct array_cache
array_cache是per cpu类型数据,每个core对应一个array_cache结构。
当array_cache中的obj为空时,系统会以batchcount值为准,一次性从kmem_list3中搬运batchcount个obj到arry_cache中,存放在entry里。
slab
slab主要包含两大部分,管理性数据和obj对象,其中管理性数据包括struct slab和kmem_bufctl_t。
slab有两种形式的结构,管理数据外挂式或内嵌式。如果obj比较小,那么struct slab和kmem_bufctl_t可以和obj分配在同一个物理page中,可称为内嵌式;如果obj比较大,那么管理性数据需要单独分配一块内存来存放,称之为外挂式。我们在上图中所画的slab结构为内嵌式。

kmem_bufctl_t

管理性数据kmem_bufctl_t的类型是unsigned int,本质上是一个空闲obj链表,用于描述下一个可用obj序号。初始化时,当前slab中的obj均可用,所以图中kmem_bufctl_t中的值依次就是下一个可用的obj序。
kmem_bufctl_t中使用方法可参考下图场景。
这里写图片描述
系统初始化时slab->free执行0#slab,某时刻系统已将0#—3# obj分配出去,此时slab->free指向4# slab,而4#slab对应的kmem_bufctl_t中存放的值是5。表明slab中current可用obj是4#,next可用obj是5#。
系统运行一段时间后,1# obj需回收。此时,1#obj对应的kmem_bufctl_t中填入slab->free值4,并将slab->free修正为1。这表明slab中current可用obj是1#,next可用的obj为4#。

SLAB分配流程以及管理逻辑

分配过程
分配的流程如下图所示:
这里写图片描述
obj分配优先考虑从array_cache的entry中取,取的规则遵循LIFO原则,先从enry的末尾取出obj,因为这个obj很有可能还在硬件cache中,是热的。如果entry为空,则说明是第一次从array_cache中分配obj或者是array_cache中的所有obj都已分配,所以需要先从kmem_cache的kmem_list3中取出batchcount个obj,把这些obj全部填充到enty中,然后再分配。
obj释放也是优先考虑释放到array_cache中,而不是直接释放到kmem_list3中。只有array_cache中的obj超过了limit上限,系统才会将enty中的头batchcount个obj搬到kmem_cache所在的kmem_list3中,然后将entry中剩余obj向前移动,然后再将准备释放的obj放到entry的末尾。

linux内存管理之slab机制

一、内核内存分配 在linux内核中伙伴系统用来管理物理内存,其分配的单位是页,但是向用户程序一样,内核也需要动态分配内存,而伙伴系统分配的粒度又太大。由于内核无法借助标准的C库,因而需要别的手段来...
  • qq_26626709
  • qq_26626709
  • 2016-10-06 10:17:05
  • 1610

Linux内存管理之slab机制(概述)

通过前面所有代码的分析和总结,已经把各个部分熟悉了一遍,在此对Linux内核中slab机制做最后的总结。 伙伴系统算法采用页作为基本内存区,这适合于大块内存的请求。对于小内存区的申请,比如说几十或几...
  • bullbat
  • bullbat
  • 2012-01-11 21:01:49
  • 17957

linux内存管理算法 :伙伴算法和slab

伙伴分配器的一个极简实现 原文地址:http://coolshell.cn/articles/10427.html 提起buddy system相信很多人不会陌生,它是一种经典的内存分配算法,...
  • yang_chen_shi_wo
  • yang_chen_shi_wo
  • 2015-07-23 16:26:46
  • 2369

Linux内存管理之slab机制(释放对象)

Linux内核中将对象释放到slab中上层所用函数为kfree()或kmem_cache_free()。两个函数都会调用__cache_free()函数。 代码执行流程: 1,当本地CPU cac...
  • bullbat
  • bullbat
  • 2012-01-10 17:23:15
  • 3123

linux内存管理--slab

struct kmem_cache * kmem_cache_create(const char *name, size_t size, size_t align, unsigne...
  • YuZhiHui_No1
  • YuZhiHui_No1
  • 2016-04-27 22:38:26
  • 3634

linux slab内存管理小析

最近把slab机制看了一下,网上分析内容丰富全面,不再过多赘述,只是自己做了个简单的小结   1. 几大重要数据结构 (1)Kmem_cache数据结构: struct kmem_cache ...
  • hsly_support
  • hsly_support
  • 2013-01-22 20:26:10
  • 1174

linux内核内存管理学习之三(slab分配器)

一、概述 在linux内核中伙伴系统用来管理物理内存,其分配的单位是页,但是向用户程序一样,内核也需要动态分配内存,而伙伴系统分配的粒度又太大。由于内核无法借助标准的C库,因而需要别的手段来实现内核中...
  • goodluckwhh
  • goodluckwhh
  • 2013-08-17 20:20:58
  • 6388

内存的slab算法

•Slab分配模式把对象分组放进缓冲区(尽管英文中使用了Cache这个词,但实际上指的是内存中的区域,而不是指硬件高速缓存)。因为缓冲区的组织和管理与硬件高速缓存的命中率密切相关,因此,Slab缓冲区...
  • kyo34080800
  • kyo34080800
  • 2012-05-14 16:27:29
  • 1503

linux 内存管理分析之-----SLAB层

SLAB层:               想必大多数人一提起linux内存管理,第一反应是"啊,特么的怎么这么复杂",哈哈,其实就是看书时蒙蔽了,别急,兄弟我陪你捋捋. 正经的来吧:  (1)    ...
  • liuchen_csdn
  • liuchen_csdn
  • 2016-03-29 20:58:07
  • 2326

Linux内存管理浅析(一)

1.Linux内存管理的主要内容 a.      虚拟内存管理 b.      内核空间内存管理 c.      用户空间内存管理 2.虚拟内存和物理内存映射 ZONE_HIGH...
  • u012398362
  • u012398362
  • 2016-11-27 19:40:18
  • 2116
收藏助手
不良信息举报
您举报文章:Linux内存管理之SLAB原理浅析。
举报原因:
原因补充:

(最多只允许输入30个字)