[转载]kmalloc vmalloc kcalloc kzalloc malloc 和 get_free_page()

来源:互联网 发布:linux transmission 编辑:程序博客网 时间:2024/06/06 18:55

kmalloc vmalloc kzalloc get_free_page()是内核空间申请内存空间函数

malloc是用户空间申请内存函数

一 ,kmalloc() 与 kfree() 和get_free_page的区别

1,用于申请较小的、连续的物理内存:使用的是内存分配器slab一小片。申请的内存位于物理内存的映射区域。其正真的物理地址只相差一个固定的偏移。

可以用这两个宏来简单转换 __pa(address) {virt_to_phys()} 和 __va(address){phys_to_virt()}

get_free_page()申请的内存是一整页,一页的大小一般是128K。它们的区别只有这一点不同,其它的都相同。

本质上讲,kmalloc()和get_free_page()最终调用实现都是相同的,只不过在调用最终函数时所传的flag不同而以。

  1. void *kmalloc(size_t size, int flags) 分配的内存物理地址上连续,虚拟地址上也是连续

  2. gfp_mask标志:

情形 相应标志
进程上下文,可以睡眠 GFP_KERNEL
进程上下文,不可以睡眠 GFP_ATOMIC
中断处理程序 GFP_ATOMIC
软中断 GFP_ATOMIC
Tasklet GFP_ATOMIC
用于DMA的内存,可以睡眠 GFP_DMA | GFP_KERNEL
用于DMA的内存,不可以睡眠 GFP_DMA | GFP_ATOMIC
4. void kfree(const void *ptr)

释放由kmalloc()分配出来的内存块

二,vmalloc() 与 vfree()

用于申请较大的内存空间,虚拟内存是连续的:申请内存位于vmalloc_start —–vmalloc_end之间,与物理内存没有简单的转换关系。物理上不要求连续。

  1. 以字节为单位进行分配,在linux/vmalloc.h中

  2. void *vmalloc(unsigned long size) 分配的内存虚拟地址上连续,物理地址不连续

  3. 一般情况下,只有硬件设备才需要物理地址连续的内存,因为硬件设备往往存在于MMU之外,根本不了解虚拟地址;但为了性能上的考虑,内核中一般使用kmalloc(),而只有在需要获得大块内存时才使用vmalloc(),例如当模块被动态加载到内核当中时,就把模块装载到由vmalloc()分配的内存上。

4.void vfree(void *addr),这个函数可以睡眠,因此不能从中断上下文调用。

三,malloc(), vmalloc()和kmalloc()区别

[1]kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存

[2]kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc和vmalloc一样,也是虚连,物不一定连。

[3]kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大

[4]内存只有在要被DMA访问的时候才需要物理上连续

[5]vmalloc比kmalloc要慢

四,kzalloc

kzalloc实现了kmalloc以及memset的功能,一个函数起到了两个函数的作用

/**  * kzalloc - allocate memory. The memory is set to zero.  * @size: how many bytes of memory are required.  * @flags: the type of memory to allocate (see kmalloc).  */  static inline void *kzalloc(size_t size, gfp_t flags)  {      return kmalloc(size, flags | __GFP_ZERO);  } 

五,目前kzalloc将取代kmalloc和memset功能。

以后在内核,看到此函数的比率将会更高。

六,kcalloc 分配n块内存,kmalloc + memset 0

/**  * kcalloc - allocate memory for an array. The memory is set to zero.  * @n: number of elements.  * @size: element size.  * @flags: the type of memory to allocate.  *  * The @flags argument may be one of:  *  * %GFP_USER - Allocate memory on behalf of user. May sleep.  *  * %GFP_KERNEL - Allocate normal kernel ram. May sleep.  *  * %GFP_ATOMIC - Allocation will not sleep. May use emergency pools.  * For example, use this inside interrupt handlers.  *  * %GFP_HIGHUSER - Allocate pages from high memory.  *  * %GFP_NOIO - Do not do any I/O at all while trying to get memory.  *  * %GFP_NOFS - Do not make any fs calls while trying to get memory.  *  * %GFP_NOWAIT - Allocation will not sleep.  *  * %GFP_THISNODE - Allocate node-local memory only.  *  * %GFP_DMA - Allocation suitable for DMA.  * Should only be used for kmalloc() caches. Otherwise, use a  * slab created with SLAB_DMA.  *  * Also it is possible to set different flags by OR'ing  * in one or more of the following additional @flags:  *  * %__GFP_COLD - Request cache-cold pages instead of  * trying to return cache-warm pages.  *  * %__GFP_HIGH - This allocation has high priority and may use emergency pools.  *  * %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail  * (think twice before using).  *  * %__GFP_NORETRY - If memory is not immediately available,  * then give up at once.  *  * %__GFP_NOWARN - If allocation fails, don't issue any warnings.  *  * %__GFP_REPEAT - If allocation fails initially, try once more before failing.  *  * There are other flags available as well, but these are not intended  * for general use, and so are not documented here. For a full list of  * potential flags, always refer to linux/gfp.h.  */  static inline void *kcalloc(size_t n, size_t size, gfp_t flags)  {      if (size != 0 && n > ULONG_MAX / size)          return NULL;      return __kmalloc(n * size, flags | __GFP_ZERO);  }  
0 0