上周針對一個記憶體fragment issue的研究,讓我開始重新總結kernel裡對記憶體配置設定的方式和方法,如有不對請指教:
頁配置設定
unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
直接從buddy系統中獲得原始頁。最原始的配置設定方式。
slab配置設定器
1. 通用 cache
void *kmalloc(size_t size, gfp_t flags)
kmalloc 基于以下幾種size的mem cache:32, 64, 128, 256, 512, 1,024, 2,048, 4,096,
8,192, 16,384, 32,768, 65,536 和 131,072 bytes。其本質也是調用kmem_cache_alloc來配置設定
object。是以kmalloc一次最大可配置設定的size為128KB。kmalloc配置設定速度很快,在配置設定時需注意gfp flag
參數:在不interrupt上下文(ISR, softirq, tasklet)及不可睡眠上下文使用GFP_ATOMIC。
核心還增加了記憶體清零的配置設定函數:kzalloc。
2. 專用 cache
kmem_cache_create()
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
如果你需要頻繁的配置設定和釋放某個結構,建議不要采用kmalloc,而是自己在slab系統中建立memory cache。
指定該結構的object size。配置設定時使用kmem_cache_alloc。同樣的slab object大小也有限制,一般情況
下一個MAX_OBJ_ORDER是5,也就是32個頁,128KB。
非連續記憶體配置設定
void *vmalloc(unsigned long size)
超過128KB的記憶體顯然不能使用slab配置設定,并且當申請的連續記憶體大小不能在buddy系統中得到滿足,那麼
就需要使用vmalloc。vmalloc為了把實體的非連續頁一個個映射,進而導緻比直接記憶體映射大的多的
後援緩沖區抖動。除非需要特别大的記憶體,否則盡量不要使用vmalloc。
基于DMA 配置設定
void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
在某些arch中,可以使用dma_alloc_coherent來配置設定DMA專用記憶體。列入在arch/arm/mm/consistent.c
中,該函數先配置設定最小可滿足size的2^order記憶體,然後釋放2^order-size多餘的頁給buddy。而arch/i386/
kernel/pci-dma.c中,則直接配置設定2^order塊記憶體。
直接映射配置設定
ioremap(unsigned long phys_addr, size_t size)
int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn, unsigned long size, pgprot_t prot)
在某些體系結構中,我們可以保留memory map段上的某一個區域,作為dma或其他裝置的專有記憶體。
這段記憶體并不在kernel buddy的控制之下(沒有被放入mem_maps),你也無法從以上幾種配置設定方式中得到
這些記憶體。這個時候,你可以用ioremap和remap_pfn_range将這段記憶體直接映射到vm上。