内核基础层提供的服务---内核中使用内存

来源:互联网 发布:女生漂亮知乎 编辑:程序博客网 时间:2024/05/16 15:05

Linux内存关系参考:http://blog.csdn.net/column/details/linux--mm.html?&page=2 

很详细很清晰


        Linux采用伙伴系统解决外部碎片的问题,采用slab解决内部碎片的问题。

避免外部碎片的方法有两种:

        一种是之前介绍过的利用非连续内存的分配;

        一种是用一种有效的方法来监视内存,保证在内核只要申请一小块内存的情况下,不会从大块的连续空闲内存中截取一段过来,从而保证了大块内存的连续性和完整性。

显然,前者不能成为解决问题的普遍方法,一来用来映射非连续内存线性地址空间有限,二来每次映射都要改写内核的页表,进而就要刷新TLB,这使得分配的速度大打折扣,这对于要频繁申请内存的内核显然是无法忍受的。因此Linux采用后者来解决外部碎片的问题,也就是著名的伙伴系统。


伙伴系统:

        伙伴系统的宗旨就是用最小的内存块来满足内核的对于内存的请求。在最初,只有一个块,也就是整个内存,假如为1M大小,而允许的最小块为64K,那么当我们申请一块200K大小的内存时,就要先将1M的块分裂成两等分,各为512K,这两分之间的关系就称为伙伴,然后再将第一个512K的内存块分裂成两等分,各位256K,将第一个256K的内存块分配给内存,这样就是一个分配的过程。

        

slab系统:

        slab分配器是Linux内存管理中非常重要和复杂的一部分,其工作是针对一些经常分配并释放的对象,如进程描述符等,这些对象的大小一般比较小,如果直接采用伙伴系统来进行分配和释放,不仅会造成大量的内碎片,而且处理速度也太慢。而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统。slab分配对象时,会使用最近释放的对象内存块,因此其驻留在CPU高速缓存的概率较高。


slub系统:

         Slab分配器一直处于内核内存管理的核心地位,尽管如此,它还是拥有自身的缺点,最明显的两点就是复杂性和过多的管理数据造成的内存上的开销。针对这些问题,linux引入了slub分配器,slub分配器保留了slab分配器的所有接口,实际上slub分配器的模型和slab分配的模型是基本一致的,只不过在一些地方进行了精简,这也使得slub分配器工作起来更为游刃有余。两者主要的区别如下:

  • slab分配器为了增加分配速度,引入了一些管理数组,如slab管理区中的kmem_bufctl数组和紧随本地CPU结构后面的用来跟踪最热空闲对象的数组,这些结构虽然加快了分配对象的速度,但也增加了一定的复杂性,而且随着系统变得庞大,其对内存的开销也越明显。而slub分配器则完全摒弃了这些管理数据,个人觉得这也是slub分配器最精髓的地方,至于slub分配器的具体做法是怎样的,后面再做分析;
  • slab分配器针对每个缓存,根据slab的状态划分了3个链表--full,partial和free. slub分配器做了简化,去掉了free链表,对于空闲的slab,slub分配器选择直接将其释放;
  • slub分配器摒弃了slab分配器中的着色概念,在slab分配器中,由于颜色的个数有限,因此着色也无法完全解决slab之间的缓存行冲突问题,考虑到着色造成了内存上的浪费,slub分配器没有引入着色;
  • 在NUMA架构的支持上,slub分配器也较slab分配器做了简化。



原创粉丝点击