[Linux内存]slab分配器学习笔记(一)--概念

http://blog.csdn.net/vanbreaker/article/details/7664296
1,为什么需要slab分配器:
 利用伙伴系统进行分配内存只能按照页的单位进行分配,这样会造成很多的内存浪费,多了很多内存碎片,比如只需要申请10字节的,结果分配了一个页。
 
2,slab分配器和伙伴系统分配的差别
 slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统。slab分配对象时,会使用最近释放的对象内存块,因此其驻留在CPU高速缓存的概率较高
 Slab分配器由很多缓存(动态链表)组成,不同的缓存大小不同(如名为kmalloc-128的缓存所管理对象的长度为128字节)。Linux的Slab缓存分为专用和通用两种,通用缓存通过函数kmem_cache_init() 进行初始化,适用于特定对象,比如各种描述符,存放进程描述符的缓存大小就是sizeof(task_struct);而专用缓存则通过函数 kmem_cache_create()创建。通用Slab的对象大小预先定义好的,一般是2的次幂(cache对齐的需要),Linux使用13级, 如下:32、64、128、256、512、1024、2048、4096、8192、16384、32768、65536、131072。这样可以保证内存碎片小于百分之50

3,slab的概念

slab分配器把内存区看作对象(object),这些对象由一组数据结构和几个构造函数或者析构函数组成,分别用于初始化和回收内存。slab分配器把对象分组放进告诉缓存,包含高速缓存的主内存区被划分为多个slab,每个slab由一个或者多个连续的页组成,这些页框包含已分配对象和空闲对象。

每一个slab对象都有一个kmem_bufctl_t描述符,每个slab的对象描述符都存放在slab描述符的后面。因此((kmem_bufctl_t*)(slab + 1)就指向slab的kmem_bufctl_t描述符地址,语句((kmem_bufctl_t*)(slab + 1)[i]就是访问第i个对象的索引。

4,slab分配器用的相关数据结构
用于描述和管理cache的数据结构是struct kmem_cache

[cpp] view plaincopy

  1. struct kmem_cache {
  2. /* 1) per-cpu data, touched during every alloc/free */
  3. /*per-CPU数据,记录了本地高速缓存的信息,也用于跟踪最近释放的对象,每次分配和释放都要直接访问它*/
  4. struct array_cache *array[NR_CPUS];
  5. /* 2) Cache tunables. Protected by cache_chain_mutex */
  6. unsigned int batchcount;  /*本地高速缓存转入或转出的大批对象数量*/
  7. unsigned int limit;       /*本地高速缓存中空闲对象的最大数目*/
  8. unsigned int shared;
  9. unsigned int buffer_size;/*管理对象的大小*/
  10. u32 reciprocal_buffer_size;/*buffer_size的倒数值*/
  11. /* 3) touched by every alloc & free from the backend */
  12. unsigned int flags;          /* 高速缓存的永久标识*/
  13. unsigned int num;         /* 一个slab所包含的对象数目 */
  14. /* 4) cache_grow/shrink */
  15. /* order of pgs per slab (2^n) */
  16. unsigned int gfporder;   /*一个slab包含的连续页框数的对数*/
  17. /* force GFP flags, e.g. GFP_DMA */
  18. gfp_t gfpflags;          /*与伙伴系统交互时所提供的分配标识*/
  19. size_t colour;         /* 颜色的个数*/
  20. unsigned int colour_off; /* 着色的偏移量 */
  21. /*如果将slab描述符存储在外部,该指针指向存储slab描述符的cache,
  22. 否则为NULL*/
  23. struct kmem_cache *slabp_cache;
  24. unsigned int slab_size;  /*slab管理区的大小*/
  25. unsigned int dflags;     /*动态标识*/
  26. void (*ctor)(void *obj); /*创建高速缓存时的构造函数指针*/
  27. /* 5) cache creation/removal */
  28. const char *name;         /*高速缓存名*/
  29. struct list_head next;    /*用于将高速缓存链入cache chain*/
  30. /* 6) statistics */
  31. /*struct kmem_list3用于组织该高速缓存中的slab*/
  32. struct kmem_list3 *nodelists[MAX_NUMNODES];
  33. /*
  34. * Do not add fields after nodelists[]
  35. */
  36. };
  37. struct kmem_list3 {
  38. struct list_head slabs_partial;/*slab链表,包含空闲对象和已分配对象的slab描述符*/
  39. struct list_head slabs_full;   /*slab链表,只包含非空闲的slab描述符*/
  40. struct list_head slabs_free;   /*slab链表,只包含空闲的slab描述符*/
  41. unsigned long free_objects;    /*高速缓存中空闲对象的个数*/
  42. unsigned int free_limit;       /*空闲对象的上限*/
  43. unsigned int colour_next;       /*下一个slab使用的颜色*/
  44. spinlock_t list_lock;
  45. struct array_cache *shared; /* shared per node */
  46. struct array_cache **alien; /* on other nodes */
  47. unsigned long next_reap;    /* updated without locking */
  48. int free_touched;       /* updated without locking */
  49. };
  50. 描述和管理单个slab的结构是struct slab
  51. struct slab {
  52. struct list_head list;  /*用于将slab链入kmem_list3的链表*/
  53. unsigned long colouroff;/*该slab的着色偏移*/
  54. void *s_mem;            /*指向slab中的第一个对象*/
  55. unsigned int inuse;     /*已分配出去的对象*/
  56. kmem_bufctl_t free;     /*下一个空闲对象的下标*/
  57. unsigned short nodeid;  /*节点标识号*/
  58. };

slab描述符可以放在以下两个地方
1,外部slab描述符,存在普通的高速缓存
2,内部slab描述符,位于分配给slab的第一个页框的起始位置

struct kmem_cache中定义了一个struct array_cache指针数组,数组的元素个数对应了系统的CPU数,和伙伴系统中的每CPU页框高速缓存类似,该结构用来描述每个CPU的本地高速缓存,在每个array_cache的末端都用一个指针数组记录了slab中的空闲对象,分配对象时,采用LIFO方式,也就是将该数组中的最后一个索引对应的对象分配出去,以保证该对象还驻留在高速缓存中的可能性。实际上,每次分配内存都是直接与本地CPU高速缓存进行交互,只有当其空闲内存不足时,才会从kmem_list中的slab中引入一部分对象到本地高速缓存中,而kmem_list中的空闲对象也不足了,那么就要从伙伴系统中引入新的页来建立新的slab了,这一点也和伙伴系统的
每CPU页框高速缓存很类似。

[cpp] view plaincopy

    1. struct array_cache {
    2. unsigned int avail;/*本地高速缓存中可用的空闲对象数*/
    3. unsigned int limit;/*空闲对象的上限*/
    4. unsigned int batchcount;/*一次转入和转出的对象数量*/
    5. unsigned int touched;   /*标识本地CPU最近是否被使用*/
    6. spinlock_t lock;
    7. void *entry[];  /*这是一个伪数组,便于对后面用于跟踪空闲对象的指针数组的访问
    8. */
    9. };
时间: 2024-09-30 04:43:58

[Linux内存]slab分配器学习笔记(一)--概念的相关文章

[Linux内存]slab分配器学习笔记(二)--slab着色

slab着色原理 slab着的原理,cpu cache 一,slab着色原理 slab分配器中用到很多的缓存,每个缓存中又包含了很多slab,每个slab中有很多对象,每个slab的头部用于管理该slab中的对象(比如哪些对象已经使用,哪些对象还没有使用等),在slab的每个对象的开始和结束处都有一个特定分区填充特定的数据,这样后面如果这些数据和预先填充的不符合那么就可以证明该内存区被错误修改过,缓存的各个slab成员会指定不同的偏移量,以便将其定位到不同的缓存行中.在分配和释放slab时候,将

Introduction the naive“scull” 《linux设备驱动》 学习笔记

Introduction the naive "scull" 首先,什么是scull? scull (Simple Character Utility for Loading Localities). scull is a char driver that acts on a memory area as though it were a device. 和第一个C程序Hello world一样,他什么都不能干,却能很好的阐释怎么一步步进阶的去写驱动 blog的最后,我会给出这对于sc

linux应用编程基础学习笔记

********************************************************            --文件I/O-- 文件:文本文件:存储量大,速度慢,便于字符操作二进制文件:存储量小,速度快,便于存放中间结果 普通文件:设备文件: ---C标准函数---:Buffered I/O,高级文件系统,在用户空间开辟缓冲区,流操作(stream)#include<stdio.h> typedef struct{ int _fd;      //文件号 int _

Java IO学习笔记:概念与原理

Java IO学习笔记:概念与原理 一.概念 Java中对文件的操作是以流的方式进行的.流是Java内存中的一组有序数据序列.Java将数据从源(文件.内存.键盘.网络)读入到内存 中,形成了流,然后将这些流还可以写到另外的目的地(文件.内存.控制台.网络),之所以称为流,是因为这个数据序列在不同时刻所操作的是源的不同部分. 二.分类 流的分类,Java的流分类比较丰富,刚接触的人看了后会感觉很晕.流分类的方式很多: 1.按照输入的方向分,输入流和输出流,输入输出的参照对象是Java程序. 2.

linux系统构建基础学习笔记——操作

linux系统构建 ********************************************************                  ---交叉编译环境构建--- 安装arm-linux-gcc-4.3.2 (交叉编译器) tar xzvf arm-linux-gcc-4.3.2.tgz -C /cd /usr/local/arm/4.3.2/bin./arm-linux-gcc -v在/etc/bashrc文件的最后添加如下一行:   export PATH=

1、Websphere学习笔记之一概念篇

1.Websphere学习笔记之一概念篇 最近因为工作需要使用Websphere,下班后就适当学习下这中间件吧.今天就看下一些概念和Websphere本身的架构. l Websphere 概念摘自百度百科: WebSphere 是IBM 的软件平台.它包含了编写.运行和监视全天候的工业强度的随需应变 Web 应用程序和跨平台.跨产品解决方案所需要的整个中间件基础设施,如服务器.服务和工具.WebSphere 提供了可靠.灵活和健壮的软件. WebSphere ApplicationServer

Linux Shell脚本编程学习笔记和实战

http://www.1987.name/141.html shell基础 终端打印.算术运算.常用变量 Linux下搜索指定目录下特定字符串并高亮显示匹配关键词 从键盘或文件中获取标准输入 [read命令] 文件的描述符和重定向 数组.关联数组和别名使用 函数的定义.执行.传参和递归函数 条件测试操作与流程控制语句 获取时间日期格式和延时 [date.sleep命令] 内部字段分隔符IFS和脚本的调试DEBUG 显示.读取或拼接文件内容 [cat命令] 文件查找与打印文件列表 [find命令]

JavaScript高级程序设计学习笔记--基本概念

1.语句 ECMAScript中的语句以一个分号结尾:如果省略分号,则由解析器确定语句的结尾,如下例所示: var sum=a+b //即使没有分号也是有效的语句--推荐 var diff=a-b; //有效的语句--推荐 虽然语句结尾的分号不是必需的,但我们建议任何时候都不要省略它.两个原因:1.加上分号可以避免很多错误 2.加上分号也会在某些情况下增进代码的性能,因为这样解析器就不必再花时间 推测应该在哪里插入分号了. 2.变量 var message="hi"; 像这样初始化变量

《鸟哥的Linux私房菜》学习笔记(0)

听说Linux已经有很长一段时间了,但是从未系统的学习过Linux.这次把在博客园的处女秀给了Linux,希望能够给自己学习Linux一种坚持的动力,坚持就是胜利,fighting! 在我看来,成为技术大牛之前,写博客主要是对自己所学的东西作以总结,涉及的东西也稍显浅薄,但是却能够为更深一步的学习打下基础,于是我选择了写博客!以前从未写过博客,博客给人第一印象——高大上,现在要写了,顿感压力山大,还好本人的初衷是为了知识的整理,暂时这样安慰一下我自己吧.初期的博客,我想肯定会是非常糟糕的,但是我