Chinaunix首页 | 论坛 | 博客
  • 博客访问: 35847
  • 博文数量: 4
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 43
  • 用 户 组: 普通用户
  • 注册时间: 2015-12-20 22:18
文章分类
文章存档

2016年(4)

我的朋友

分类: LINUX

2016-03-31 21:32:37

在 BiscuitOS / Linux 上使用 kmem_cache_create() 创建缓存时,需要根据分配的对象的大小从 Buddy 分配器中获得空闲页来组成 slab page.
例如:
      struct kmem_cache *file_cachep = kmem_cache_create("File",sizeof(struct file),0,0,NULL);
内核通过 sizeof(struct file) 计算的值将从 Buddy 中获得的空闲页,然后将空闲页分成大小为 sizeof(struct file) 的 object.
储存这些 object 的 page 称为 slab page.本帖用于讨论一个 slab page 的大小.
内核根据 object 的 size 来计算 slab page 的大小,
1. 如果 object 的 size 很小,那么一个 slab page 就由一个 page 组成
2. 如果 object 的 size 很大,那么一个 slab page 可能有两个或多个 page 组成.
Slab page 的大小计算如下:
1. 在 slub 中一个 slab page 中规定最小的 object 数量为 slub_min_objects,其值可以为零,
    当 slub_min_objects 为零的时候,内核根据 cpu 的数量来进行赋值,其计算公式如下:
         slub_min_objects = 4 * (fls(nr_cpu_ids) + 1)
    其中函数 fls() 的作用是求参数的最高位的位数,如
         fls(00001100B) = 4
         fls(00001000B) = 4
         fls(00010000B) = 5
    fls() 的作用类似于向下除的效果.
    nr_cpu_ids 为系统 cpu 的个数.
    于是我们可以得出以下结论:
    (1) 在单 CPU 的体系中 slub_min_objects 为 8
    (2) 在双 CPU 的体系中 slub_min_objects 为 12
    (3) 在四 CPU 的体系中 slub_min_objects 为 16
2. 一个 slab page 最大 objects 数量为 max_objects,其计算如下:
    max_objects = (PAGE_SIZE << slub_max_order) / size;
    max_objects = min(min_objects,max_objects);
    上述表达式中 slub_max_order 为 3,其含义为最大的 slab_page 为 2^3,也就是 一个最大的 slab_page 可由 8 page 构成.
    size 为 object 的 size.
3. 获得上面两个值之后,内核进行 slab order 的计算,其过程如下:
    (1) 对一个 page 构成的 slab page 进行检测,如果在这种情况下, objects 的数量大于 slab page 规定的最大 object 的数量
          那么内核直接从 Buddy 分配器中获得最大 object 时的 page. 代码如下:
         if ((PAGE_SIZE << min_order) / size > MAX_OBJS_PER_PAGE)
                return get_order(size * MAX_OBJS_PER_PAGE) - 1;
     (2) 内核计算 object 的 size 对应的最小 order,其计算如下:
           order =  fls(min_objects * size - 1) - PAGE_SHIFT;
           通过上面对 min_objects 的计算,可以获得 object 的最小 order 如下表:
object_size
min_object = 8
min_object = 12
min_object = 16

8
-6
-5
-5

16
-5
-4
-4

32
-4
-3
-3

64
-3
-2
-2

128
-2
-1
-1

256
-1
0
0

512
0
1
1

1024
1
2
2

2048
2
3
3

4096
3
4
4

8096
4
5
5

          
          通过上面表的计算,我们可以看出不同的 object size 的 slab page 的最小 order 不同,由于 order 最小为 0,所以最最小 order 进行处理
          order = max(min_order,fls(min_objects * size - 1) - PAGE_SHIFT);
     (3) 获得最小 order 之后,就从最小 order 开始遍历,只要满足一个 slab page 中,浪费部分小于 1/16 就可以进行分配.因为 object size 大小不同,
         而 page 则按 PAGE_SIZE 进行对齐,所以无法避免一定的浪费,但内核规定只要浪费不超过 1/16 就可以进行分配.所以代码如下:
          for (order = max(min_order , fls(min_objects * size - 1) - PAGE_SHIFT) ; order <= max_order; order++) {
                   unsigned long slab_size = PAGE_SIZE << order;
         
                  if (slab_size < min_objects * size)
                         continue;
                  rem = slab_size % size;

                  if (rem <= slab_size / fract_leftover)
                          break;
 }
     (4) 通过上面的计算之后获得最小 slab page 的 order,接着就可以从 Buddy 中获得对应的 page 来构成 slab page.         

阅读(2579) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~