核心使用do_munmap()函式從當前程序的位址空間中刪除乙個線性位址區間。
該函式經過兩個主要的階段。第一階段(第1一6步),掃瞄程序所擁有的線性區鍊錶,並把包含在程序位址空間的線性位址區間中的所有線性區從鍊錶中解除鏈結。第二階段(第7~10步),更新程序的頁表,並把第一階段找到並標識出的線性區刪除。函式利用稍後要說明的split_vma()和unmap_region()函式。do_munmap()執行下面的步驟:
int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
unsigned long addr, int new_below)
pol = mpol_copy(vma_policy(vma));
if (is_err(pol))
vma_set_policy(new, pol);
if (new->vm_file)
get_file(new->vm_file);
if (new->vm_ops && new->vm_ops->open)
/* 5.如果定義了新線性區的open方法,函式就執行它。 */
new->vm_ops->open(new);
/* 6.根據new_below的值呼叫vma_adjust函式把新線性區描述符鏈結到線性區鍊錶mm->mmap和紅-黑樹mm->mm_rb。
* 此外,vma_adjust函式還要根據線性區vma的最新大小對紅-黑樹進行調整。 */
if (new_below) else
vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
return 0;
}unmap_region()函式遍歷線性區鍊錶並釋放它們的頁框。該函式作用於5個引數:記憶體描述符指標mm,指向第乙個被刪除線性區描述符的指標vma,指向程序鍊錶中vma前面的線性區的指標prev(參見do_munmap()執行步驟中心的第2步和第4步),以及兩個位址start和end,它們界定被刪除線性位址區間的範圍。
static void unmap_region(struct mm_struct *mm,
struct vm_area_struct *vma, struct vm_area_struct *prev,
unsigned long start, unsigned long end)
函式各步驟解釋:
1.呼叫lru_add_drain()(頁面**中會提到)。
2.呼叫tlb_gather_mmu()函式初始化每cpu變數mmu_gathers。mmu_gathers的值依賴於cpu體系結構:通常該變數應該存放成功更新程序頁表項所需要的所有資訊。在80x86體系結構中,tlb_gather_mmu()函式只是簡單地把記憶體描述符指標mm的值賦給本地cpu的mmu_gathers變數。
3.把mmu_gathers變數的位址儲存在區域性變數tlb中。
4.呼叫unmap_vmas()掃瞄線性位址空間的所有頁表項:如果只有乙個有效cpu,函式就呼叫free_swap_and_cache()反覆釋放相應的頁(頁面**中會提到);否則,函式就把相應頁描述符的指標儲存在區域性變數mmu_gathers中。
5.呼叫free_pgtables(tlb, prev, start, end)**在上一步已經清空的程序頁表。
6.呼叫tlb_finish_mmu(tlb, start, end)結束unmap_region()函式的工作,tlb_finish_mmu(tlb, start, end)依次執行下面的操作:
a.呼叫flush_tlb_mm()重新整理tlb。
b.在多處理器系統中,呼叫 freepages_and_swap_cache()釋放頁框,這些頁框的指標已經集中存放在mmu_gather資料結構中了。
線性位址 2
linux核心對整個系統的物理記憶體是通過型別為struct page的陣列mem map來管理的。系統中的夥伴系統分配演算法最終是通過操作這個陣列來記錄物理記憶體的分配 等操作。在這裡不要被系統的高階記憶體 低端記憶體等概念搞混淆了,高 低端記憶體的分類主要在於區分物理記憶體位址是否可以直接對映到...
線性位址的管理
eprocess中 為什麼採用二叉樹的方式管理線性位址空間呢?最主要的原因是使用二叉樹查詢的效能會更好 涉及資料結構 這個startin pn和這個endin pn是以頁為單位也就是 4kb 0x1000 在startin pn這個位址後新增3個0,也就是這個結點描述的線性位址的起始位址 endin...
線性位址和實體地址
在保護模式下32位 還是採用段機制訪問記憶體 初始化臨時的要進入到ia 32e模式的gdt資料結構 label gdt64 dq 0x0000000000000000 label desc code64 dq 0x0020980000000000 label desc data64 dq 0x000...