天天看點

linux kernel 記憶體,總結一下 Linux Kernel中記憶體配置設定方式

上周針對一個記憶體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上。