Linux内存管理(二)

ARM结构物理内存和内核空间关系:
在前文中讲述过X86的内存存储空间,其实32位ARM处理器与X86是存在区别的,对于ARM来说,没有IO空间,采用的是哈佛结构,指令和数据是分开的,其物理地址和内核地址空间的映射关系如下图所示,假设内核编译时指定的VMSPLIT_3G(3G/1G usr/kernel split)
Linux内存管理(二)
DMA,常规,高端内存均采用伙伴算法,把空闲页面以2的n次方为单位进行管理,buddy算法的优点就是避免了外部碎片,任何时候都是以2的n次方进行拆分合并。
Linux内存管理(二)
内核空间内存的动态申请:
1.kmalloc:
void *kmalloc(size_t size,int flags);
第一个参数为分配快的大小,第二个参数为分配标志,kmalloc底层依赖于__get_free_pages()来实现,常用的标志为GFP_KERNEL,此标志为阻塞性标志,因此不能在中断或者持有自旋锁的情况下使用此标志,取而代之的时GFT_ATOMIC标志。
kfree()用来释放kmalloc内存,__get_free_pages最多申请1024页
2.vmalloc:
vmalloc的开销比较大,只是用vmalloc分配较小的的内存时是不划算的,vmalloc使用vfree进行释放,vmalloc不能用于原子上下文中,由于其内部使用了GFP_KERNEL,vmalloc申请的虚拟内存在物理上不是连续的,因此在DMA这些以页为单位,有严格物理地址连续性要求的一般不采用vmalloc。
3.slab与内存池
在申请小内存时(如少量字节),如果按照页去申请内存必然造成资源的浪费,因此采用slab算法可以解决此问题,slab算法在buddy算法基础上进行二次管理,与物理内存之间也是一个简单的线性关系
创建slab缓存
struct kmem_cache kmem_cache_cfreate
分配slab缓存
void
kmem_cache_clloc(struct kmem_cache *cachep,gfp_t flags)
释放slab缓存
void kmem_cache_free(struct kmem_cache *cachep,vod *objp )
收回slab缓存
int kmem_cache_destory(struct kmem_cache *cachep)
可以通过/proc/slabinfo查看slab分配情况