您的位置:首页 > 其它

kmalloc VS kmem_cache_alloc

2014-05-07 18:14 337 查看
Linux内核为需要动态分配内存的内核程序提供了kmalloc/kfree/kcalloc/krealloc函数接口,它们分别对应于C标准库的malloc/free/calloc/krealloc。除此之外,Linux还提供了kmem_cache_xxx系列系统调用,以提供比上述接口更低的时间复杂度和空间复杂度,那么两者的效率究竟能差多少,它们又各自适合于何种场合呢?


Linux内存系统的层次结构

为了保证灵活性,Linux内存分配系统是分层设计的,这种层次设计使得整个设计更加明晰,每个层次都能简单而有效地进行局部优化,所以一般也能提供更好的性能,当然扩展性也更好了,不然SLUB[1]的出现就不可能那么轻松自然了。Linux内存系统自上而下分成以下几部分:

单位接口算法
动态大小kmalloc/kfree/krealloc/kcalloc 按大小组织的缓存数组
固定大小kmem_cache_create/kmem_cache_destroy

kmem_cache_alloc/kmem_cache_free
Slab[2]
2^n页alloc_pages/free_pages

__get_free_pages/__free_pages
伙伴算法


kmalloc相对于kmem_cache_alloc的时间复杂度

因为kmalloc是基于kmem_cache_create实现的,那么时间效率上kmalloc肯定是占不到任何便宜了,那么究竟能差多少呢?让我们先来看看相关代码:

    79  static inline void *kmalloc(size_t size, gfp_t flags)

    80  {

    81      if (__builtin_constant_p(size)) {

    82          int i = 0;

    83  #define CACHE(x) \

    84          if (size <= x) \

    85              goto found; \

    86          else \

    87              i++;

    88  #include "kmalloc_sizes.h"

    89  #undef CACHE

    90          {

    91              extern void __you_cannot_kmalloc_that_much(void);

    92              __you_cannot_kmalloc_that_much();

    93          }

    94  found:

    95          return kmem_cache_alloc((flags & GFP_DMA) ?

    96              malloc_sizes[i].cs_dmacachep :

    97              malloc_sizes[i].cs_cachep, flags);

    98      }

    99      return __kmalloc(size, flags);

   100  }
出于效率上的考虑,上述函数为被声明为内联编译,81行的__builtin_constant_p是gcc的内建函数[3],它能够在编译时判定它的参数是否是编译时常量,如果是它将返回真,因为此函数为内联函数,并且__builtin_constant_p的参数为整型变量,所以判定仍有效。这也就意味着,如果你用如下方式调用kmalloc:

ptr = kmalloc(128, GTP_KERNEL);
实际执行的将是82-79行的代码。为了能将这部分代码展开,我们不得不参考文件kmalloc_sizes.h的内容:

     1  #if (PAGE_SIZE == 4096)

     2          CACHE(32)

     3  #endif

     4          CACHE(64)

     5  #if L1_CACHE_BYTES < 64

     6          CACHE(96)

     7  #endif

     8          CACHE(128)

     9  #if L1_CACHE_BYTES < 128

    10          CACHE(192)

    11  #endif

    12          CACHE(256)

    13          CACHE(512)

    14          CACHE(1024)

    15          CACHE(2048)

    16          CACHE(4096)

    17          CACHE(8192)

    18          CACHE(16384)

    19          CACHE(32768)

    20          CACHE(65536)

    21          CACHE(131072)

    22  #ifndef CONFIG_MMU

    23          CACHE(262144)

    24          CACHE(524288)

    25       
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: