分类: LINUX
2008-12-09 16:20:49
内核中,分别对于不同的应用层面,对kmalloc有不同的定义,分别位于
slab.c
Mark Hemment捣鼓的,从从Sun OS引进
slob.c
针对嵌入式系统,主要是针对内存非常有限的设备
slub.c
可以说是对slab的重新设计,代码量更下,并且能够更好的适应 large NUMA系统,被认为时slab和slob的取代者
Slob中的kmalloc只有一个语句,return __kmalloc_node(size, flags,
-1);跟踪相应的__kmalloc_node()函数,该函数首先会获得ARCH_KMALLOC_MINALIGN和 ARCH_SLAB_MINALIGN 中的max值,当需要分配的页面大小小于PAGE_SIZE减去max的差时:
1、 当size为0时,返回ZERO_SIZE_PTR错误
2、 采用slob_alloc分配内存,不成功时返回错误
3、 返回size+max的地址
否则,调用slob_new_page重新分配一个新的内存空间,并且将分配的虚地址转化成的物理地址交给一个page->private的值为所分配的大小的页面。
在看Slub和slab中的kmalloc的时候先要了解__builtin_constant_p 是一个gcc的内建函数用于判断一个值是否为编译时常数,如果参数EXP 的值是常数,函数返回 1,否则返回 0。
Slub中,首先判断kmalloc函数中的size的类型,如果是在编译时不确定,那么直接调用__kmalloc(size, flags)并且取值返回,否则,将在返回之前进行一些判断:
1、 当需分配的的大小大于页面大小时,使用__kmalloc(size, flagkmalloc_larges)进行分配
2、 当分配时带有SLUB_DMA标记时,首先采用kmalloc_slab(size)分配内存,分配失败时,返回ZERO_SIZE_PTR
3、 返回kmem_cache_alloc(s,
flags)
__kmalloc(size, flags)
1、 当size不大于PAGE_SIZE时,调用kmalloc_large(size,
flags)分配空间并返回
2、 当get_slab(size,
flags)返回值不为0或者空时,返回其返回值
3、 调用slab_alloc(s,
flags, -1, __builtin_return_address(0))分配空间
kmalloc_large(size,
flags)调用__get_free_pages(flags | __GFP_COMP,
get_order(size));返回指定大小的空闲页面
kmalloc_slab()当kmalloc_index(size)返回的索引不为0时,调用kmalloc_cache(index)分配页面
kmem_cache_alloc()返回slab_alloc()给分配的空间。
Slab中的kmalloc()分配策略类似于sulb中,都需要对size的类型进行判断,如果是在编译时不确定,那么直接调用__kmalloc(size, flags)并且取值返回,否则,将在返回之前进行一些判断:
1、 错误处理,当size为0时,返回ZERO_SIZE_PTR
2、 当cache的值小于size时,i+=1,否则跳到found处执行
如果在编译选项中设置了CONFIG_ZONE_DMA,并且标明了GFP_DMA,调用kmem_cache_alloc(malloc_sizes[i].cs_dmacachep,
flags)分配内存并返回。否则调用kmem_cache_alloc(malloc_sizes[i].cs_cachep, flags);分配内存并返回
__kmalloc(size, flags)
返回__do_kmalloc(size, flags, NULL);的值
kmem_cache_alloc
返回__cache_alloc(cachep, flags, __builtin_return_address(0))的值
__do_kmalloc()
得到一个cache的指针,如果指针不为空或者0的时候,返回指针,否则调用__cache_alloc(cachep, flags, caller)分配一个缓存并返回
__cache_alloc()
该函数主要功能是分配一个
1、
得到一个CPU的对应的cache数组,设置为变量ac
2、
当ac可用时,cache指针加1并且状态设置成命中,返回ac的入口指针
3、
或者将cache指针加1,返回重新分配并填充的cache指针