-
内核提供了众多分配内存空间的API,介绍如下:
-
-
1. __get_free_pages()/__free_pages()
-
__get_free_pages()函数用于以gfp_mask分配方式分配2的order次方个连续的物理页,主要调用alloc_pages()。它返回所分配的连续物理页面中第一个页的逻辑地址。
-
-
2. __krealloc()和krealloc()
-
krealloc和__krealloc都是重新分配内存,且不改变原地址空间中的内容。但是区别在P参数。
-
void *krealloc(const void *p, size_t new_size, gfp_t flags)
-
{
-
void *ret;
-
-
if (unlikely(!new_size)) {
-
kfree(p);
-
return ZERO_SIZE_PTR;
-
}
-
-
ret = __do_krealloc(p, new_size, flags);
-
if (ret && p != ret)
-
kfree(p);
-
-
return ret;
-
}
-
-
void *__krealloc(const void *p, size_t new_size, gfp_t flags)
-
{
-
if (unlikely(!new_size))
-
return ZERO_SIZE_PTR;
-
-
return __do_krealloc(p, new_size, flags);
-
}
-
-
3. alloc_pages()
-
以gfp_mask分配方式分配2的order次方个连续的物理页.
-
alloc_pages(gfp_t gfp_mask, unsigned int order)
-
{
-
return alloc_pages_current(gfp_mask, order);
-
}
-
-
4. get_zeroed_page()
-
用于获取一个物理页,它保证该页不属于高端内存,并将该页的内容清零。
-
unsigned long get_zeroed_page(gfp_t gfp_mask);
-
-
5. kcalloc()
-
kcalloc和kzalloc函数功能类似,都是基于slab分配在物理上连续的实际的内存,并且在分配了内存之后,又将内存中的内容清0.但是kcalloc是为一个数组分配空间,数组中的一个元素对应一个内存对象。
-
static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
-
{
-
return kmalloc_array(n, size, flags | __GFP_ZERO);
-
}
-
-
static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
-
{
-
if (size != 0 && n > SIZE_MAX / size)
-
return NULL;
-
return __kmalloc(n * size, flags);
-
}
-
-
6. kmalloc()/kfree()
-
kmalloc用于分配在物理上连续的内存,虚拟地址自然也是连续的,它是基于slab分配实际上存在的连续的内存。
-
static __always_inline void *kmalloc(size_t size, gfp_t flags)
-
{
-
if (__builtin_constant_p(size)) {
-
if (size > KMALLOC_MAX_CACHE_SIZE)
-
return kmalloc_large(size, flags);
-
#ifndef CONFIG_SLOB
-
if (!(flags & GFP_DMA)) {
-
int index = kmalloc_index(size);
-
-
if (!index)
-
return ZERO_SIZE_PTR;
-
return kmem_cache_alloc_trace(kmalloc_caches[index],flags, size);
-
}
-
#endif
-
}
-
return __kmalloc(size, flags);
-
}
-
-
7. kmem_cache_alloc()/kmem_cache_free()
-
kmem_cache_alloc函数用于从一个给定的缓存分配一个对象,如果缓存目前为空,则会调用cache_alloc_refill()向缓冲中增加内存。
-
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
-
{
-
void *ret = slab_alloc(cachep, flags, _RET_IP_);
-
-
trace_kmem_cache_alloc(_RET_IP_, ret,cachep->object_size, cachep->size, flags);
-
-
return ret;
-
}
-
-
8.kmem_cache_zalloc()
-
与kmem_cache_alloc函数类似,都是从一个给定的缓存分配一个对象,但是它还把对象所代表的内存空间初始化为0.
-
static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags)
-
{
-
return kmem_cache_alloc(k, flags | __GFP_ZERO);
-
}
-
-
9.kmemdup
-
该函数是根据给定的一段地址区间,再分配一个内存空间,将原地址空间的内容拷贝到新分配的内存空间中。
-
void *kmemdup(const void *src, size_t len, gfp_t gfp)
-
{
-
void *p;
-
-
p = kmalloc_track_caller(len, gfp);
-
if (p)
-
memcpy(p, src, len);
-
return p;
-
}
-
-
10. ksize()
-
该函数用于通过函数kmalloc/kmem_cache_alloc所分配的对象的实际内存的大小。
-
size_t ksize(const void *objp)
-
{
-
BUG_ON(!objp);
-
if (unlikely(objp == ZERO_SIZE_PTR))
-
return 0;
-
-
return virt_to_cache(objp)->object_size;
-
}
-
-
11. kstrdup函数
-
该函数的功能是为常量字符串s分配内存空间,并将该字符串拷贝到所分配的地址空间中。
-
char *kstrdup(const char *s, gfp_t gfp)
-
{
-
size_t len;
-
char *buf;
-
-
if (!s)
-
return NULL;
-
-
len = strlen(s) + 1;
-
buf = kmalloc_track_caller(len, gfp);
-
if (buf)
-
memcpy(buf, s, len);
-
return buf;
-
}
-
-
#define kmalloc_track_caller(size, flags) __kmalloc(size, flags)
-
-
12. kstrndup()
-
跟kstrdup函数类似,只是拷贝的字节个数可以设定。
-
char *kstrndup(const char *s, size_t max, gfp_t gfp)
-
{
-
size_t len;
-
char *buf;
-
-
if (!s)
-
return NULL;
-
-
len = strnlen(s, max);
-
buf = kmalloc_track_caller(len+1, gfp);
-
if (buf) {
-
memcpy(buf, s, len);
-
buf[len] = '\0';
-
}
-
return buf;
-
}
-
-
13. kzalloc()
-
与kmalloc类似,都是基于slab分配在物理上连续的实际的内存。但是kzalloc在分配了内存之后,将内存中的内容都初始化为0.
-
static inline void *kzalloc(size_t size, gfp_t flags)
-
{
-
return kmalloc(size, flags | __GFP_ZERO);
-
}
-
-
14. vmalloc()
-
该函数用于分配一块非连续地址空间,它分配的物理地址一般不连续的,但是虚拟地址是连续的。
-
void *vmalloc(unsigned long size)
-
{
-
return __vmalloc_node_flags(size, NUMA_NO_NODE,GFP_KERNEL | __GFP_HIGHMEM);
- }