Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1058795
  • 博文数量: 573
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 66
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-28 16:21
文章分类

全部博文(573)

文章存档

2018年(3)

2016年(48)

2015年(522)

分类: LINUX

2016-03-02 20:17:48

内核内存分配API 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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