内核内存分配API

5790阅读 0评论2014-07-01 wangbaolin719
分类:LINUX


  1. 内核提供了众多分配内存空间的API,介绍如下:

  2. 1. __get_free_pages()/__free_pages()
  3. __get_free_pages()函数用于以gfp_mask分配方式分配2的order次方个连续的物理页,主要调用alloc_pages()。它返回所分配的连续物理页面中第一个页的逻辑地址。

  4. 2. __krealloc()和krealloc()
  5. krealloc和__krealloc都是重新分配内存,且不改变原地址空间中的内容。但是区别在P参数。
  6. void *krealloc(const void *p, size_t new_size, gfp_t flags)
  7. {
  8.     void *ret;
  9.     
  10.     if (unlikely(!new_size)) {
  11.         kfree(p);
  12.         return ZERO_SIZE_PTR;
  13.     }
  14.     
  15.     ret = __do_krealloc(p, new_size, flags);
  16.     if (ret && p != ret)
  17.         kfree(p);
  18.     
  19.     return ret;
  20. }

  21. void *__krealloc(const void *p, size_t new_size, gfp_t flags)
  22. {
  23.     if (unlikely(!new_size))
  24.         return ZERO_SIZE_PTR;
  25.     
  26.     return __do_krealloc(p, new_size, flags);
  27. }

  28. 3. alloc_pages()
  29. 以gfp_mask分配方式分配2的order次方个连续的物理页.
  30. alloc_pages(gfp_t gfp_mask, unsigned int order)
  31. {
  32.     return alloc_pages_current(gfp_mask, order);
  33. }

  34. 4. get_zeroed_page()
  35. 用于获取一个物理页,它保证该页不属于高端内存,并将该页的内容清零。
  36. unsigned long get_zeroed_page(gfp_t gfp_mask);

  37. 5. kcalloc()
  38. kcalloc和kzalloc函数功能类似,都是基于slab分配在物理上连续的实际的内存,并且在分配了内存之后,又将内存中的内容清0.但是kcalloc是为一个数组分配空间,数组中的一个元素对应一个内存对象。
  39. static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
  40. {
  41.     return kmalloc_array(n, size, flags | __GFP_ZERO);
  42. }

  43. static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
  44. {
  45.     if (size != 0 && n > SIZE_MAX / size)
  46.         return NULL;
  47.     return __kmalloc(n * size, flags);
  48. }

  49. 6. kmalloc()/kfree()
  50. kmalloc用于分配在物理上连续的内存,虚拟地址自然也是连续的,它是基于slab分配实际上存在的连续的内存。
  51. static __always_inline void *kmalloc(size_t size, gfp_t flags)
  52. {
  53.     if (__builtin_constant_p(size)) {
  54.         if (size > KMALLOC_MAX_CACHE_SIZE)
  55.             return kmalloc_large(size, flags);
  56. #ifndef CONFIG_SLOB
  57.         if (!(flags & GFP_DMA)) {
  58.             int index = kmalloc_index(size);
  59.         
  60.             if (!index)
  61.                 return ZERO_SIZE_PTR;
  62.             return kmem_cache_alloc_trace(kmalloc_caches[index],flags, size);
  63.         }
  64. #endif
  65.     }
  66.     return __kmalloc(size, flags);
  67. }

  68. 7. kmem_cache_alloc()/kmem_cache_free()
  69. kmem_cache_alloc函数用于从一个给定的缓存分配一个对象,如果缓存目前为空,则会调用cache_alloc_refill()向缓冲中增加内存。
  70. void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
  71. {
  72.     void *ret = slab_alloc(cachep, flags, _RET_IP_);
  73.     
  74.     trace_kmem_cache_alloc(_RET_IP_, ret,cachep->object_size, cachep->size, flags);
  75.     
  76.     return ret;
  77. }

  78. 8.kmem_cache_zalloc()
  79. 与kmem_cache_alloc函数类似,都是从一个给定的缓存分配一个对象,但是它还把对象所代表的内存空间初始化为0.
  80. static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags)
  81. {
  82.     return kmem_cache_alloc(k, flags | __GFP_ZERO);
  83. }

  84. 9.kmemdup
  85. 该函数是根据给定的一段地址区间,再分配一个内存空间,将原地址空间的内容拷贝到新分配的内存空间中。
  86. void *kmemdup(const void *src, size_t len, gfp_t gfp)
  87. {
  88.     void *p;
  89.     
  90.     p = kmalloc_track_caller(len, gfp);
  91.     if (p)
  92.         memcpy(p, src, len);
  93.     return p;
  94. }

  95. 10. ksize()
  96. 该函数用于通过函数kmalloc/kmem_cache_alloc所分配的对象的实际内存的大小。
  97. size_t ksize(const void *objp)
  98. {
  99.     BUG_ON(!objp);
  100.     if (unlikely(objp == ZERO_SIZE_PTR))
  101.         return 0;
  102.     
  103.     return virt_to_cache(objp)->object_size;
  104. }

  105. 11. kstrdup函数
  106. 该函数的功能是为常量字符串s分配内存空间,并将该字符串拷贝到所分配的地址空间中。
  107. char *kstrdup(const char *s, gfp_t gfp)
  108. {
  109.     size_t len;
  110.     char *buf;
  111.     
  112.     if (!s)
  113.         return NULL;
  114.     
  115.     len = strlen(s) + 1;
  116.     buf = kmalloc_track_caller(len, gfp);
  117.     if (buf)
  118.         memcpy(buf, s, len);
  119.     return buf;
  120. }

  121. #define kmalloc_track_caller(size, flags) __kmalloc(size, flags)

  122. 12. kstrndup()
  123. 跟kstrdup函数类似,只是拷贝的字节个数可以设定。
  124. char *kstrndup(const char *s, size_t max, gfp_t gfp)
  125. {
  126.     size_t len;
  127.     char *buf;
  128.          
  129.     if (!s)
  130.         return NULL;
  131.     
  132.     len = strnlen(s, max);
  133.     buf = kmalloc_track_caller(len+1, gfp);
  134.     if (buf) {
  135.         memcpy(buf, s, len);
  136.         buf[len] = '\0';
  137.     }
  138.     return buf;
  139. }

  140. 13. kzalloc()
  141. 与kmalloc类似,都是基于slab分配在物理上连续的实际的内存。但是kzalloc在分配了内存之后,将内存中的内容都初始化为0.
  142. static inline void *kzalloc(size_t size, gfp_t flags)
  143. {
  144.     return kmalloc(size, flags | __GFP_ZERO);
  145. }

  146. 14. vmalloc()
  147. 该函数用于分配一块非连续地址空间,它分配的物理地址一般不连续的,但是虚拟地址是连续的。
  148. void *vmalloc(unsigned long size)
  149. {
  150.     return __vmalloc_node_flags(size, NUMA_NO_NODE,GFP_KERNEL | __GFP_HIGHMEM);
  151. }


上一篇:Linux双核SMP系统启动流程(Zynq-ARM-CortexA9)
下一篇:scatterlist分析