内核版本:linux-2.6.11


  • 内存区和内存对象

伙伴系统是linux用于满足对不同大小块内存分配和释放请求的解决方案,它为slab分配器提供页框分配请求的实现。

如果我们需要请求具有连续物理地址和任意长度的内存单元序列时,即不定大小的内存区时,则需要在伙伴系统之上提供一层更细粒度的管理方案。

Linux在分配内存的时候,会将这部分内存初始化成一定的类型,即内存对象,例如信号、进程描述符、文件描述符等等,在释放的时候,会进行析构。

然而进行初始化和析构占用的时间已然超出了分配这部分内存的时间,于是,需要一个机制能够省略内存初始化和内存析构的时间,这对提升内存从分配到使用再到释放这一系列处理过程的性能有着莫大帮助。

  • slab分配器

出于这两种需求,slab出现了。

slab分配器最早是由Jeff Bonwick引进Solaris 5.4内核中的,如今各主流Unix-like系统都在使用。

它充当了伙伴系统和内存区分配接口之间的中间件。

举一个完整的例子,假设之前没有任何可用高速缓存的情况下,slab分配器接收到第一个内存分配请求时,首先会调用伙伴系统来分配足够大小的页框,然后按照一定规则初始化这部分内存,返回。内存释放时,slab分配器不会马上析构这部分内存,而是标记为可用,下一次的内存分配请求如果类型相同,那么直接使用可用的未析构的那块内存区,这样一来,高速缓存中会留有相同类型内存区的可用链表,只要链表不为空,那么该类型的内存区分配请求将会跳过初始化这一步直接得到满足。

所以说整个slab分配器的核心就是缓存(硬件高速缓存),是一种用空间换时间的聪明机制。

  • 高速缓存

讲到这里,不得不补充一下高速缓存这个东西。

由于多级高速缓存之间的一致性是由硬件实现的,因此对于Linux而言,CPU片内只有一个逻辑的高速缓存,单位为行,一般由几十个连续的字节组成,同时,片内存在一个高速缓存控制器,里面保存了从高速缓存行到主存单元的映射表,由此判断访问内存时是否命中高速缓存。

Linux在系统初始化的时候调用函数kmem_cache_init()和函数kmem_cache_sizes_init()初始化了一系列高速缓存,并创建描述符以供slab分配器使用。

slab本身是存在于高速缓存以及对应的页框里的,由高速缓存控制器控制这里的高速缓存跟主存保持一致。

  • 核心处理流程

    • 为新的slab分配页框

      kmem_getpages() 调用伙伴系统的alloc_pages()函数接口,返回首个页描述符指针。
    • 给高速缓存分配slab

      cache_grow 给高速缓存分配一个新的slab,同时调用cache_init_objs(),该函数主要代码如下
    static void cache_init_objs(struct kmem_cache *cachep, struct page *page)
    {
     for (i = 0; i < cachep->num; i++) {
      void *objp = index_to_obj(cachep, page, i);
      if (cachep->ctor)
     cachep->ctor(objp);
      set_obj_status(page, i, OBJECT_FREE);
      set_free_obj(page, i, i);
      }
    }

    第一个参数为指定高速缓存的描述符指针,第二个参数为上一步调用伙伴系统分配的首个页框的描述符指针。

    用途是将这个新的slab中的所有对象的构造函数设为该高速缓存中注册的构造函数,且将他们全部设为空闲。

    由这里也可以看出,对象类型是跟高速缓存绑定的,即一个高速缓存描述符对应的这一块硬件高速缓存中的所有slab中的所有对象都是同一种类型的。

    • 分配slab对象

      假设上一步初始化了一个服务于A类型对象的slab,此时,我们就拥有了一组A类型的空闲对象虚位以待。

      当接到内存区分配请求时,通过指定拥有不同构造函数的高速缓存描述符来调用kmem_cache_alloc(cachep, flags)就可以获得相应的空闲内存对象指针。

总结一下

首先,系统初始化了两组高速缓存,第一组包括各个指定类型(task_struct、mm_struct、singal等等)的高速缓存,第二组则是一系列2的幂字节大小的通用对象(范围从32-131072)的高速缓存,内核其他模块进行内存区分配请求时,指定好自己需要的内存类型所对应的高速缓存,例如,新建进程时就需要指定第一组中的task_struct对应高速缓存,kmalloc函数则是指定第二组中的高速缓存,slab分配器会取得指定高速缓存中的一个空闲内存对象返回给请求模块。

slab分配器在做分配和释放内存对象的工作时,会尽量减少构造新对象和析构旧对象以实现这个空间换时间的算法。


PS: 有什么问题,请各位一定指出,万分感谢。

Linux内核笔记——内存管理之slab分配器的更多相关文章

  1. Linux内核笔记--内存管理之用户态进程内存分配

    内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...

  2. Linux内核笔记——内存管理之块内存分配

    内核版本:linux-2.6.11 伙伴系统 伙伴系统是linux用于满足对不同大小块物理内存分配和释放请求的解决方案. 内存管理区 linux将物理内存分成三个内存管理区,分别为ZONE_DMA Z ...

  3. 24小时学通Linux内核之内存管理方式

    昨天分析的进程的代码让自己还在头昏目眩,脑子中这几天都是关于Linux内核的,对于自己出现的一些问题我会继续改正,希望和大家好好分享,共同进步.今天将会讲诉Linux如何追踪和管理用户空间进程的可用内 ...

  4. Linux内核之内存管理

    Linux内核之内存管理 Linux利用的是分段+分页单元把逻辑地址转换为物理地址; RAM的某些部分永久地分配给内核, 并用来存放内核代码以及静态内核数据结构; RAM的其余部分称动态内存(dyna ...

  5. Linux内存管理 (5)slab分配器

    专题:Linux内存管理专题 关键词:slab/slub/slob.slab描述符.kmalloc.本地/共享对象缓冲池.slabs_partial/slabs_full/slabs_free.ava ...

  6. 把握linux内核设计思想(十二):内存管理之slab分配器

    [版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流.请勿用于商业用途] 上一节最后说到对于小内存区的请求,假设採用伙伴系统来进行分配,则会在页内产生非 ...

  7. Linux内存管理之slab分配器

    slab分配器是什么? 参考:http://blog.csdn.net/vanbreaker/article/details/7664296 slab分配器是Linux内存管理中非常重要和复杂的一部分 ...

  8. 内存管理之slab分配器

    基本思想 与传统的内存管理模式相比, slab 缓存分配器提供了很多优点.首先,内核通常依赖于对小对象的分配,它们会在系统生命周期内进行无数次分配.slab 缓存分配器通过对类似大小的对象进行缓存而提 ...

  9. 深入理解Linux内核-内存管理

    内核如果给自己分配动态内存 动态内存:RAM的某些部分被永久打分配给内核,用来存放内核代码以及静态内核数据结构:剩余的部分被称为动态内存 连续物理内存区管理: 页框管理:1.页大小的选择,通常情况下主 ...

随机推荐

  1. Android开发 default activity not found

    新建的项目,今天打开的时候,发现无法编译了.编译按钮无法点击,必须edit configuration.并且报错 default activity not found. 解决: 少写了一个" ...

  2. 6 VC维

    1 VC维的定义 VC维其实就是第一个break point的之前的样本容量.标准定义是:对一个假设空间,如果存在N个样本能够被假设空间中的h按所有可能的2的N次方种形式分开,则称该假设空间能够把N个 ...

  3. 面向对象Part4

    ---------------------------------------------------------------------------------------------------- ...

  4. Java关于IO流的介绍

    JDK提供的流继承了四大类:InputStream(字节输入流).OutputStream(字节输出流).Reader(字符输入流).Writer(字符输出流). 字符流和字节流的主要区别:     ...

  5. hibernate id 策略

    @Id@GeneratedValue(generator = "paymentableGenerator")@GenericGenerator(name = "payme ...

  6. 【java回调】java两个类之间的回调函数传递

    背景交代:熟悉用js开发的cordovaAPP:对java一窍不通的我,老师让做一个监测用户拍照事件的功能,无奈没有找到现成的库,无奈自己动手开发java插件~~0基础java GreenHand,祝 ...

  7. javaee 导航

    tomcate端口设定和服务器虚拟目录设定 静态web 应用和动态web应用 tomcat相关问题 web应用 http 响应 url uri 动态页面 servlet 一个简单的servlet的de ...

  8. iOS Salesforce SDK 小知识

    Salesforce SDK 能做许多任务,因此也比较繁杂,又分了原生,js等多个调用方法. 关键点总结: SFSmartStore 中的 - (id) initWithName:(NSString* ...

  9. 将jetty嵌入到应用中的简单案例

    前面说过jetty最广泛的应用是可以方便的嵌入到应用程序中,而不是作为应用服务器,下面就用最简单的demo来演示一个最简单的应用 1.下载并导入依赖 首先应该建立一个普通的java项目,然后把依赖包导 ...

  10. [转]Android静态变量的生命周期

    原文地址:https://my.oschina.net/jerikc/blog/137207 Android是用Java开发,其静态变量的生命周期遵守Java的设计.我们知道静态变量是在类被load的 ...