Vmalloc實現原理

2021-08-10 16:47:04 字數 4009 閱讀 1524

目錄1.vmalloc概覽...

21.1 vmalloc資料結構說明...

21.2 vmalloc資料結構關係...

22.vmalloc記憶體分配...

32.1 vmalloc開機初始化...

32.2vmalloc.

32.2.1 vmalloc記憶體分配流程...

32.2.2 vmalloc虛擬位址空間分配...

42.2.3 vmalloc物理頁分配和對映...

63.vfree.

7附:位址空間布局...

//將開機過程中分配的vmalloc區域插入紅黑樹中

vmalloc虛擬位址區間分配

分配乙個vmap_area 結構,並且在紅黑樹中查詢乙個size大小的空閒區域,空閒位址空間必須位於vstart 到vend 之間,這裡傳入的是vmalloc_start和 vmalloc_end

tatic struct vmap_area *alloc_vmap_area(unsigned long size,

unsigned long align,

unsigned long vstart, unsigned long vend,

int node, gfp_t gfp_mask)

cached_vstart = vstart;

cached_align = align;

/*free_vmap_cache用於快取上一次查詢的vmap_area,下次查詢空閒區域可以從這個位置開始,避免從vmalloc_star開始浪費時間*/

if (free_vmap_cache) else else

n = n->rb_right;

}if (!first)

goto found;

}/*從first開始查詢乙個可以容納size大小的空閒區域,找到的條件是

addr + size 小於first->va_start

addr + size 大於 vend

查詢到鍊錶vmap_area_list末尾*/

while (addr + size > first->va_start && addr + size <= vend)

found:

if (addr + size > vend)

goto overflow;

//程式走到這裡說明找打了可用的空閒區域

va->va_start = addr;

va->va_end = addr + size;

va->flags = 0;

__insert_vmap_area(va); //將初始化後的vmap_area插入紅黑樹

free_vmap_cache = &va->rb_node;

spin_unlock(&vmap_area_lock);

return va;

overflow:

spin_unlock(&vmap_area_lock);

if (!purged)

if (gfpflags_allow_blocking(gfp_mask))

}kfree(va);

return err_ptr(-ebusy);

}

vmap_area_root是紅黑樹的根節點;全域性變數vmap_area_list用於將vmap_area安位址從小到大排序。下面函式是將vmap_area同時插入紅黑樹和鍊錶vmap_area_list中、

static void __insert_vmap_area(struct vmap_area *va)

rb_link_node(&va->rb_node, parent, p);

rb_insert_color(&va->rb_node, &vmap_area_root);

tmp = rb_prev(&va->rb_node);

if (tmp) else //如果沒有prev節點就新增到vmap_area_list的末尾

list_add_rcu(&va->list, &vmap_area_list);

}

初始化vm_struct並關聯vm_struct與vmap_area

static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,

unsigned long flags, const void *caller)

vmalloc物理頁分配和對映

static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,

pgprot_t prot, int node)

else

area->pages = pages; //用於存放page結構位址的陣列

…… for (i = 0; i < area->nr_pages; i++)

if (node == numa_no_node)

page = alloc_page(alloc_mask); //分配一頁

else

page = alloc_pages_node(node, alloc_mask, 0);

area->pages[i] = page; //將頁的位址放到陣列中

if (gfpflags_allow_blocking(gfp_mask))

cond_resched();

}//對映前面分配到的物理頁到連續虛擬位址空間中去

if (map_vm_area(area, prot, pages))

goto fail;

return area->addr; //返回虛擬位址區間的起始位址

fail:

......

fail_no_warn:

vfree(area->addr);

return null;

}

vfree

void vfree(const void *addr)

schedule  free_work去釋放vfree_deferred中等待釋放的記憶體

static inline void __vfree_deferred(const void *addr)

釋放掉虛擬位址空間和對應的物理頁

static void __vunmap(const void *addr, int deallocate_pages)

if (deallocate_pages)

kvfree(area->pages); //釋放到page指標陣列

}kfree(area); //釋放掉vm_struct

kernel閱讀手記之vmalloc

vmalloc 和kmalloc 的在邏輯位址上時連續的,他們的區別在於 vmalloc 在實體地址上並不時連續的,但是 kmalloc 在實體地址上頁時連續的。vmalloc 分配分為兩種模式,一種是沒有 mmu memory management unit,記憶體管理模組 的 vmalloc 比...

Kmalloc和Vmalloc的區別

kmalloc 和vmalloc 介紹 kmalloc 用於申請較小的 連續的物理記憶體 1.以位元組為單位進行分配,在中 2.void kmalloc size t size,int flags 分配的記憶體實體地址上連續,虛擬位址上自然連續 3.gfp mask標誌 什麼時候使用哪種標誌?如下 ...

Kmalloc和Vmalloc的區別

kmalloc 和vmalloc 介紹 kmalloc 用於申請較小的 連續的物理記憶體 1.以位元組為單位進行分配,在中 2.void kmalloc size t size,int flags 分配的記憶體實體地址上連續,虛擬位址上自然連續 3.gfp mask標誌 什麼時候使用哪種標誌?如下 ...