幾個內存分配API的區別

內存分配的API有:alloc_pages, kmalloc, slab分配,vmalloc, malloc,下面簡單說明一下以上幾個函數的差別:

alloc_pages:主要用來從buddy系統中分配內存,以頁爲單位分配區域需要通過gfp_flag指定,一般情況下會優先從highmem zone分配,返回的是分配到物理首個頁面的管理結構體struct page,buddy裏面頁面的組織情況如下圖:

alloc_pages返回的是滿足條件的用於管理free_area中對應大小的block的page struct的地址,同時每個free_area元素的migrationtype中的內存block的管理者都通過page組成的lru鏈表管理,而alloc_pages返回的是通過list_entry來獲取這個lru鏈表中的一個page struct返回,從管理頁面的角度,buddy可以化成如下示意圖:

而alloc_pages如果分配的order是小於等於4,則返回的是上圖中其中一個page struct

kmalloc和slab:kmalloc是slab的一個通用分配內存API,slab分配器從buddy拿到需求大小且物理內存連續的物理頁面個數,然後kmalloc再從slab分配器中獲取需要的slab對象,slab對象大小可以爲64,128,256等等個字節數,相對於專用的slab分配內存主要是部分驅動申請的slab描述符,然後再進行slab對象的內存申請。此時申請的物理內存是連續的

vmalloc:再kernel space的vmalloc area中申請內存,並建立虛擬地址到物理地址映射,此時的物理地址可能是不連續的,因爲在申請內存時時一個頁面一個頁面alloc_pages,後面建立映射過程中也是一個頁面一個頁面映射。

static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
				 pgprot_t prot, int node)
{
    ………………
	for (i = 0; i < area->nr_pages; i++) {
		struct page *page;

		if (node == NUMA_NO_NODE)
			page = alloc_page(alloc_mask);
		else
			page = alloc_pages_node(node, alloc_mask, order);

		if (unlikely(!page)) {
			/* Successfully allocated i pages, free them in __vunmap() */
			area->nr_pages = i;
			goto fail;
		}
		area->pages[i] = page;
		if (gfp_mask & __GFP_WAIT)
			cond_resched();
	}
………………
}

static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
		unsigned long end, pgprot_t prot, struct page **pages, int *nr)
{
………………
	do {
		struct page *page = pages[*nr];

		if (WARN_ON(!pte_none(*pte)))
			return -EBUSY;
		if (WARN_ON(!page))
			return -ENOMEM;
		set_pte_at(&init_mm, addr, pte, mk_pte(page, prot));
		(*nr)++;
	} while (pte++, addr += PAGE_SIZE, addr != end);
	return 0;
}

malloc:主要是在進程的虛擬地址空間user space中申請vma,但是此時並沒有分配物理內存,除分配flag帶有VM_MLOCK標誌需要立即建立虛擬地址到物理地址的映射外,其他都是在進程需要訪問此虛擬內存時,通過缺頁中斷來申請的物理地址,並建立映射,另外malloc申請到的物理內存也是不連續的。

mmap:在私有內存映射中,當malloc申請的內存size大於128KB時,glibc會自動使用mmap來代替brk分配內存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章