kmalloc/vmalloc获取memory的对齐方式

来源:互联网 发布:淘宝客qq群怎么拉人 编辑:程序博客网 时间:2024/06/04 23:21

kmalloc对齐方式:
所用kernel使用slob:
# CONFIG_SLAB is not set
# CONFIG_SLUB is not set
CONFIG_SLOB=y

在linux2.6.35/inclue/linux/slob_def.h中:
/**
 * kmalloc - allocate memory
 * @size: how many bytes of memory are required.
 * @flags: the type of memory to allocate (see kcalloc).
 *
 * kmalloc is the normal method of allocating memory
 * in the kernel.
 */
static __always_inline void *kmalloc(size_t size, gfp_t flags)
{
 return __kmalloc_node(size, flags, -1);
}

在linux2.6.35/mm/slob.c中:
/*
 * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend.
 */
void *__kmalloc_node(size_t size, gfp_t gfp, int node)
{
 unsigned int *m;
 int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
 void *ret;
...
}


其中的 ARCH_KMALLOC_MINALIGN 的定义:
对arm而言,可参考
linux-2.6.35\arch\arm\include\asm\Cache.h
/*
 * Memory returned by kmalloc() may be used for DMA, so we must make
 * sure that all such allocations are cache aligned. Otherwise,
 * unrelated code may cause parts of the buffer to be read into the
 * cache before the transfer is done, causing old data to be seen by
 * the CPU.
 */
#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES

对mips而言可参考 linux-2.6.35\arch\mips\include\asm\mach-generic\kmalloc.h
#ifndef CONFIG_DMA_COHERENT
/*
 * Total overkill for most systems but need as a safe default.
 * Set this one if any device in the system might do non-coherent DMA.
 */
#define ARCH_SLAB_MINALIGN 128
#endif

ARCH_KMALLOC_MINALIGN 的定义参考 linux-2.6.35\include\linux\Slob_def.h
#ifndef ARCH_SLAB_MINALIGN
#define ARCH_SLAB_MINALIGN __alignof__(unsigned long)
#endif

所以对mips而言,kmalloc是128byte对齐,对arm而言是cache line size对齐(假设: cache line size > __alignof__(unsigned long))


vmalloc的对齐方式:
void *vmalloc(unsigned long size)
{
 return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
     -1, __builtin_return_address(0));
}
static void *__vmalloc_node(unsigned long size, unsigned long align,
       gfp_t gfp_mask, pgprot_t prot,
       int node, void *caller)
{
 struct vm_struct *area;
 void *addr;
 unsigned long real_size = size;

 size = PAGE_ALIGN(size);
 if (!size || (size >> PAGE_SHIFT) > totalram_pages)
  return NULL;
...
}
可以看出vmalloc先进行了页对齐操作