内核可以用kmalloc分配一段连续的内存空间,kmalloc的具体实现为:
static __always_inline void *kmalloc(size_t size, gfp_t flags)
{
struct kmem_cache *cachep;
void *ret;
if (__builtin_constant_p(size)) {
int i;
if (!size)
return ZERO_SIZE_PTR;
if (WARN_ON_ONCE(size > KMALLOC_MAX_SIZE))
return NULL;
i = kmalloc_index(size);
#ifdef CONFIG_ZONE_DMA
if (flags & GFP_DMA)
cachep = kmalloc_dma_caches[i];
else
#endif
cachep = kmalloc_caches[i];
ret = kmem_cache_alloc_trace(cachep, flags, size);
return ret;
}
return __kmalloc(size, flags);
}
从上面代码可以发现,kmalloc后面跟了两个形参,第一个是预分配的内存空间大小,第二个是分配标志,可以控制kmalloc的行为(能否睡眠等)。
kmalloc分配的内存属于xkphys地址空间,其特点是虚实地址映射方法为直接映射,不用进行页表转换。而且该段内存是连续的,可以进行随机访问。
kmalloc分配内存大小限制:
观察kmalloc的函数实现会发现,分配内存大小不能超过KMALLOC_MAX_SIZE,在启用slab情况下相关代码:
#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
(MAX_ORDER + PAGE_SHIFT - 1) : 25)
#define KMALLOC_SHIFT_MAX KMALLOC_SHIFT_HIGH
#define KMALLOC_MAX_SIZE (1UL << KMALLOC_SHIFT_MAX)
MAX_ORDER和PAGE_SHIFT在不同的情况下值不一样,建议大家自己去看内核源码计算即可。