linux内核内存管理学习之三(slab分配器) |
您所在的位置:网站首页 › linux内核中的内存管理器是什么 › linux内核内存管理学习之三(slab分配器) |
一、内核内存分配 在linux内核中伙伴系统用来管理物理内存,其分配的单位是页,但是向用户程序一样,内核也需要动态分配内存,而伙伴系统分配的粒度又太大。由于内核无法借助标准的C库,因而需要别的手段来实现内核中动态内存的分配管理,linux采用的是slab分配器。slab分配器不仅可以提供动态内存的管理功能,而且可以作为经常分配并释放的内存的缓存。通过slab缓存,内核能够储备一些对象,供后续使用。需要注意的是slab分配器只管理内核的常规地址空间(准确的说是直接被映射到内核地址空间的那部分内存包括
ZONE_NORMAL和ZONE_DMA)。
采用了slab分配器后,在释放内存时,slab分配器将释放的内存块保存在一个列表中,而不是返回给伙伴系统。在下一次内核申请同样类型的对象时,会使用该列表中的内存开。slab分配器分配的优点:
可以提供小块内存的分配支持不必每次申请释放都和伙伴系统打交道,提供了分配释放效率如果在slab缓存的话,其在CPU高速缓存的概率也会较高。伙伴系统的操作队系统的数据和指令高速缓存有影响,slab分配器降低了这种副作用伙伴系统分配的页地址都页的倍数,这对CPU的高速缓存的利用有负面影响,页首地址对齐在页面大小上使得如果每次都将数据存放到从伙伴系统分配的页开始的位置会使得高速缓存的有的行被过度使用,而有的行几乎从不被使用。slab分配器通过着色使得slab对象能够均匀的使用高速缓存,提高高速缓存的利用率 在引入了slab分配器后,内核的内存管理方案如图所示:
slab分配器也不是万能的,它也有缺陷: 对于微型嵌入式系统,它显得比较复杂,这是可以使用经过优化的slob分配器,它使用内存块链表,并使用最先适配算法对于具有大量内存的大型系统,仅仅建立slab分配器的数据结构就需要大量内存,这时候可以使用经过优化的slub分配器 无论是slab分配器家族的这三个中的那个一,它们提供的接口都是相同的: kmalloc,__kmalloc和kmalloc_node用于普通内存的分配 kmem_cache_alloc,kmem_cache_alloc_node用于申请特定类型的内存 内核中普通内存的申请使用kmalloc(size,flags),size是申请的大小,flags告诉分配器分配什么样的内存,如何分配等等。 内核中普通内存的释放使用kfree(*ptr);释放ptr所指向的内存区。 可以通过/proc/slabinfo查看活动的缓存列表。 二、slab分配器的原理slab算法是1994年开发出来的并首先用于sun microsystem solaris 2.4操作系统。这种算法的使用基于以下几个前提: 所存放数据的类型可以影响存储器取区的分配方式。内核函数倾向于反复请求同一类型的存储器区。对存储器区的请求可以根据它们发生的频率来分类。所引入的对象大小不是几何分布的。硬件高速缓存的高性能。在这种情况下,伙伴函数的每次调用都增加了对内存的平均访问时间。 slab分配器把对象分组放进高速缓存。每个高速缓存都是同种类型对象的一种“储备”。一个cache管理一组大小固定的内存块(也称为对象实体),每个内存块都可用作一种数据结构。cache中的内存块来自一到多个slab。一个slab来自物理内存管理器的一到多个物理页,该slab被分成一组固定大小的块,被称为slab对象(object),一个slab属于一个cache,其中的对象就是该cache所管理的固定大小的内存块。所以一个cache可以有一到多个slab。下图给出了slab分配器的各个部分及其相互关系:slab缓存的详细结构 如图所示:
每个缓存结构都包括了两个重要的成员: struct kmem_list3 **nodelists:kmem_list3结构中包含了三个链表头,分别对应于完全用尽的slab链表,部分用尽的slab链,空闲的slab链表,其中部分空闲的在最开始struct array_cache *array[NR_CPUS + MAX_NUMNODES]:array是一个数组,系统中的每一个CPU,每一个内存节点都对应该数组中的一个元素。array_cache结构包含了一些特定于该CPU/节点的管理数据以及一个数组,每个数组元素都指向一个该CPU/节点刚释放的内存对象。该数组有助于提高高速缓存的利用率。 当释放内存对象时,首先将内存对象释放到该数组中对应的元素中申请内存时,内核假定刚释放的内存对象仍然处于CPU高速缓存中,因而会先从该数组的对应数组元素中查找,看是否可以申请。当特定于CPU/节点的缓存数组是空时,会用slab缓存中的空闲对象填充它 因此,对象分配的次序为: 特定于CPU/节点的缓存列表中的对象当前已经存在于slab缓存中中的未用对象从伙伴系统获得内存,然后创建的对象 2.slab对象对象在slab中不是连续排列的,其排列如图所示: slab分配器使用kmem_cache_create创建一个新的slab缓存。该函数的基本工作过程为: 参数检查计算对齐分配缓存的管理结构所需的内存计算slab所需的物理内存大小以及每个slab中slab对象的个数计算slab管理部分应该放在哪里,并存储在缓存的flags域中计算slab的颜色,颜色数目存在color中,颜色偏移量存在color_off中建立每CPU的缓存将新创建的缓存添加到全局slab缓存链表slab_caches中 2.分配对象 kmem_cache_alloc用于从指定的slab缓存分配对象。与kmalloc相比,它多了一个缓存指针的参数,用于指向所要从其中分配内存的缓存。 其工作过程如图:在NUMA系统中,如果在本节点分配失败,还会尝试其它节点。 cache_grow用于缓存的增长,它会从伙伴系统获取内存。其流程如图所示:
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |