Slab Allocator

Slab


understand
是基于2.6的这本书比较有年代了,学习基本思想后看最新代码,应该会好点,记录下备用。

在本章中,将描述通用分配器。它是一个slab分配器,在许多方面与Solaris [MM01]中使用的通用内核分配器非常相似。 Linux的实现很大程度上基于Bonwick [Bon94]的第一份slab分配器文件,其许多改进与他在其后一篇论文[BA01]中所述的非常相似。我们将首先快速了解分配器,然后在深入介绍分配器负责的每个任务之前,先描述所使用的不同结构。

slab分配器的基本思想是使常用对象的缓存保持在初始化状态,以供内核使用。如果没有基于对象的分配器,内核将花费大量时间分配,初始化和释放同一对象。slab分配器旨在缓存释放的对象,以便在使用之间保留基本结构[Bon94]

slab分配器由可变数量的高速缓存组成,这些高速缓存在称为高速缓存链的双向链接循环列表上链接在一起。在slab分配器的上下文中,高速缓存是特定类型的许多对象的管理器,例如mm_structfs_cache高速缓存,并由稍后将详细讨论的struct kmem_cache_s进行管理。缓存通过缓存结构中的下next字段链接。

每个高速缓存在内存中维护称为slab的连续页面块,这些页面被切成小块,用于高速缓存管理的数据结构和对象。这些不同结构之间的关系如图8.1所示。
8.1
slab分配器具有三个主要目标:

  • 分配小内存块,以帮助消除内部的碎片,否则碎片会由伙伴系统引起;
  • 缓存常用对象,以便系统不会浪费时间分配,初始化和销毁​​对象。 Solaris上的基准测试表明,使用中的slab分配器的分配速度显着提高[Bon94];
  • 通过将对象对准L1或L2缓存来更好地利用硬件缓存。

为了帮助消除通常由二进制伙伴分配器引起的内部碎片,维护了两组小型存储器缓冲区的高速缓存,范围从2^5 (32)字节到2^17 (131072)字节。一种高速缓存集适用于DMA设备。这些高速缓存称为size-Nsize-N(DMA),其中N是分配的大小,并提供了kmalloc()函数(请参见第8.4.1节)来分配它们。这样,解决了低级页面分配器的最大问题。

slab分配器的第二个任务是维护常用对象的缓存。对于内核中使用的许多结构,初始化对象所需的时间与为对象分配空间的成本相当或超过。当创建一个新的slab时,许多对象被打包到其中并使用构造函数(如果可用)进行初始化。释放对象后,它会保持其初始化状态,这样可以快速分配对象。

slab分配器的最终任务是硬件高速缓存利用率。如果将对象包装到slab中之后仍有剩余空间,则将剩余空间用于为slab着色。slab着色是一种尝试使不同slab中的对象使用高速缓存中不同行的方案。通过将对象放置在slab中的不同起始偏移处,对象可能会在CPU高速缓存中使用不同的行,从而有助于确保来自同一slab高速缓存的对象不太可能相互刷新。通过这种方案,原本会被浪费的空间将实现一项新功能。下图显示了从伙伴分配器分配的页面如何用于存储对象,这些对象使用着色将对象与L1 CPU缓存对齐。
在这里插入图片描述
图8.2:包含与L1 CPU缓存对齐的对象的Slab页面

Linux不会尝试根据其物理地址(Kes91)或放置对象的顺序(如针对数据[GAV95]或代码段描述的对象[HK97])来为页面分配着色,但是使用的方案确实有助于提高缓存行的使用率。缓存着色将在8.1.5节添加链接描述中进一步讨论。在SMP系统上,采取了进一步的步骤来帮助提高缓存利用率,其中每个缓存都有为每个CPU保留的一小部分对象。这将在8.5节中进一步讨论。

如果在编译时使用CONFIG_SLAB_DEBUG设置了选项,则slab分配器将提供slab调试的附加选项。提供了两个调试功能,称为红色分区和对象中毒。使用红色分区时,将标记放置在对象的任一端。如果此标记受到干扰,分配器将知道发生缓冲区溢出的对象并报告该对象。中毒时,将在创建slab时和释放之后用预定义的位模式(在mm / slab.c中定义为0x5A)填充对象。在分配时,将检查此模式,如果更改了该模式,分配器将在分配对象之前知道该对象已被使用并对其进行标记。

列出分配器导出的小型但功能强大的API

kmem_cache_t * kmem_cache_create(const char *name, size_t size,     size_t offset, unsigned long flags,
    void (*ctor)(void*, kmem_cache_t *, unsigned long),
   void (*dtor)(void*, kmem_cache_t *, unsigned long))

创建一个新的缓存并将其添加到缓存链

int kmem_cache_reap(int gfp_mask)

扫描REAP_SCANLEN高速缓存,并选择其中一个用于从中获取所有每个cpu对象和空闲slab。内存不足时调用

int kmem_cache_shrink(kmem_cache_t *cachep)

此函数将删除与缓存关联的所有按CPU对象,并删除slabs_free列表中的所有slab。它返回已释放的页面数。

void * kmem_cache_alloc(kmem_cache_t *cachep, int flags)

从缓存中分配单个对象,并将其返回给调用方

void kmem_cache_free(kmem_cache_t *cachep, void *objp)

释放对象并将其返回到缓存

void * kmalloc(size_t size, int flags)

从大小缓存之一分配一块内存

void kfree(const void *objp)

释放由kmalloc分配的一块内存

int kmem_cache_destroy(kmem_cache_t * cachep)

在从链中删除缓存之前,销毁所有slab中的所有对象并释放所有关联的内存

以上就是用于缓存的Slab Allocator API

Caches

对于每种要缓存的对象,都存在一个缓存。有关正在运行的系统上可用的高速缓存的完整列表,请运行cat / proc / slabinfo。该文件提供了有关缓存的一些基本信息。该文件的输出摘录如下:

[root@node34 ~]# cat /proc/slabinfo |grep orcafs
slabinfo - version: 1.1 (SMP)
kmem_cache            80     80    248    5    5    1 :  252  126
urb_priv               0      0     64    0    0    1 :  252  126
tcp_bind_bucket       15    226     32    2    2    1 :  252  126
inode_cache         5714   5992    512  856  856    1 :  124   62
dentry_cache        5160   5160    128  172  172    1 :  252  126
mm_struct            240    240    160   10   10    1 :  252  126
vm_area_struct      3911   4480     96  112  112    1 :  252  126
size-64(DMA)           0      0     64    0    0    1 :  252  126
size-64              432   1357     64   23   23    1 :  252  126
size-32(DMA)          17    113     32    1    1    1 :  252  126
size-32              850   2712     32   24   24    1 :  252  126

每个列字段都对应于struct kmem_cache_s结构中的一个字段。上面摘录中列出的列是:

  • name 易读的名称,例如“ tcp_bind_bucket”;
  • num-active-objs 正在使用的对象数;
  • total-objs 总共有多少个对象可用,包括未使用的对象;
  • obj-size 每个对象的大小,通常很小;
  • num-active-slabs包含活动对象的slab数;
  • total-slabs总共有多少块slab;
  • num-pages-per-slab 创建一个slab(通常为1个)所需的页面.

如果像示例摘录中那样启用了SMP,则在冒号之后将显示另外两列。它们引用了第8.5节中描述的每个CPU缓存。这些列是:

  • limit 这是池将其一半分配给全局空闲池之前可以拥有的空闲对象的数量;
  • batchcount没有可用对象时在一个块中分配给处理器的对象数
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值