现在的位置: 首页 > 综合 > 正文

linux 常用内存分配函数小结

2018年04月11日 ⁄ 综合 ⁄ 共 2026字 ⁄ 字号 评论关闭

1. ioremap :
ioremap 会按照页的大小调整映射size。另外,当地址没有页对齐的时候,ioremap会rounding down这个地址,也就是向下圆整地址,然后返回内存页的首地址+offset。下面是ldd的原文:
ioremap simulates an unaligned mapping by “rounding down” the address to be remapped and by returning an offset into the first remapped page.

2. kmalloc :
kmalloc 分配的内存物理地址连续。
1) 两个常用的flag:GFP_KERNEL和GFP_ATOMIC
2) size :
这个函数分配的内存必须是2的n次方。另外,这个函数分配的内存有大小限制。在arm平台上,最少分配32字节。最大依平台而异。比如:公司的j-one平台,最大能分配4M。

注:
下面具体分析下它的代码,
以 arm 平台为例,kmalloc 的实现在 include\linux\slab_def.h(但是不一定都在这个文件,在宏的控制下还有可能是其他两个文件 CONFIG_SLUB,CONFIG_SLOB)。其中控制分配buffer大小的代码在 #include <linux/kmalloc_sizes.h> 里面 。

由这个文件可知,KMALLOC_MAX_SIZE 就是最大 size 。下面是这个宏的定义:
#define KMALLOC_MAX_SIZE (1UL << KMALLOC_SHIFT_HIGH)
#define KMALLOC_SHIFT_HIGH    ((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
                (MAX_ORDER + PAGE_SHIFT - 1) : 25)

下面是在j-one平台上打出来的log
**********************************
KMALLOC_MAX_SIZE = 4194304
KMALLOC_SHIFT_HIGH = 22
MAX_ORDER = 11
PAGE_SHIFT = 12
failed to alloc 4194304+1
succeed to alloc 4194304
**********************************

3)物理地址与虚拟地址的关系:
在arm平台下kmalloc分配的内存的虚拟地址和物理地址只差一个偏移量。

注:
因为 kmalloc 最终还是调用 __get_free_pages,所以只要分析这个函数就好。见 page_alloc.c。
在该函数的最后一行也就是 page_alloc.c 1987行,page_address 这个宏将物理地址转换为虚拟地址。

arm平台的 page_address 参见 include/linux/mm.h 615行,
#define page_address(page) lowmem_page_address(page)

lowmem_page_address的实现参考同一个文件 590行,可以看到它是通过__va宏来做转换。

而__va可以参考 arch/arm/include/asm/memory.h, line 185。
#define __va(x)                 ((void *)__phys_to_virt((unsigned long)(x)))

在同一个文件的129行,可以看到
#define __phys_to_virt(x)    ((x) - PHYS_OFFSET + PAGE_OFFSET)
所以确实如书中所说从物理地址到虚拟地址,只差一个偏移量。

3. 大块内存的分配:
1)alloc_bootmem:
该函数族要在内存管理子系统启动前调用,另外这个函数族分配的内存即使释放也不能由内存管理子系统回收。
2)另外一个方法是在启动参数中保留一块高地址内存。

4. vmalloc:
虚拟地址连续,物理地址不一定连续。
注意:kmalloc与vmalloc的区别是,前者分配的内存虚拟地址与物理地址之间只差一个偏移量,而vmalloc分配的内存则不是,另外vmalloc需要重建页表,从而vmalloc有性能问题。另外,和 ioremap 一样,vmalloc 要按照 page 对 size 参数圆整。

5. __get_free_pages:
该函数在分配大块内存时使用。注意:在j-one平台上最大只能分配10个page,所以它实际上和 kmalloc 一样,只能分配最大 4M 内存。

6. dma_alloc_writecombine 和 dma_alloc_coherent
如果需要分配关闭 cache 或者关闭 write buffer 的内存,可以使用这两个函数。
两者区别参见:arch\arm\include\asm\dma-mapping.h
dma_alloc_coherent:uncached, unbuffered
dma_alloc_writecombine:uncached, buffered

抱歉!评论已关闭.