linux --- 內存管理

1. 內核初始化:     * 內核創建好內核頁目錄頁表數據庫,假設物理內存大小爲len,則創建了[3G--3G+len]::[0--len]這樣的虛地址vaddr和物理地址paddr的線性對應關係;     * 內核創建一個page數組,page數組和物理頁面系列徹底是線性對應,page用來管理該物理頁面狀態,每一個物理頁面的虛地址保存在page->virtual中;     * 內核創建好一個free_list,將沒有使用的物理頁面對應的page放入其中,已經使用的就不用放入了; 2. 內核模塊申請內存vaddr = get_free_pages(mask,order):     * 內存管理模塊從free_list找到一個page,將page->virtual做爲返回值,該返回值就是對應物理頁面的虛地址;     * 將page從free_list中脫離;     * 模塊使用該虛擬地址操做對應的物理內存; 3. 內核模塊使用vaddr,例如執行指令mov(eax, vaddr):     * CPU得到vaddr這個虛地址,利用創建好的頁目錄頁表數據庫,找到其對應的物理內存地址;     * 將eax的內容寫入vaddr對應的物理內存地址內; 4. 內核模塊釋放內存free_pages(vaddr,order):     * 依據vaddr找到對應的page;     * 將該page加入到free_list中; 5. 用戶進程申請內存vaddr = malloc(size):     * 內存管理模塊從用戶進程內存空間(0--3G)中找到一塊還沒使用的空間vm_area_struct(start--end);     * 隨後將其插入到task->mm->mmap鏈表中; 6. 用戶進程寫入vaddr(0-3G),例如執行指令mov(eax, vaddr):     * CPU得到vaddr這個虛地址,該虛地址應該已經由glibc庫設置好了,必定在3G一下的某個區域,根據CR3寄存器指向的current->pgd查當前進程的頁目錄頁表數據庫,發現該vaddr對應的頁目錄表項爲0,故產生異常;     * 在異常處理中,發現該vaddr對應的vm_area_struct已經存在,爲vaddr對應的頁目錄表項分配一個頁表;     * 隨後從free_list找到一個page,將該page對應的物理頁面物理首地址賦給vaddr對應的頁表表項,很明顯,此時的vaddr和paddr不是線性對應關係了;     * 將page從free_list中脫離;     * 異常處理返回;     * CPU從新執行剛剛發生異常的指令mov(eax, vaddr);     * CPU得到vaddr這個虛地址,根據CR3寄存器指向的current->pgd,利用創建好的頁目錄頁表數據庫,找到其對應的物理內存地址;     * 將eax的內容寫入vaddr對應的物理內存地址內;   7. 用戶進程釋放內存vaddr,free(vaddr):     * 找到該vaddr所在的vm_area_struct;     * 找到vm_area_struct:start--end對應的全部頁目錄頁表項,清空對應的全部頁表項;     * 釋放這些頁表項指向物理頁面所對應的page,並將這些page加入到free_list隊列中;     * 有必要還會清空一些頁目錄表項,並釋放這些頁目錄表項指向的頁表;     * 從task->mm->mmap鏈中刪除該vm_area_struct並釋放掉; 綜合說明:     * 可用物理內存就是free_list中各page對應的物理內存;     * 頁目錄頁表數據庫的主要目的是爲CPU訪問物理內存時轉換vaddr-->paddr使用,分配以及釋放內存時不會用到,可是須要內核內存管理系統在合適時機爲CPU創建好該庫;     * 對於用戶進程在6中得到的物理頁面,有兩個頁表項對應,一個就是內核頁目錄頁表數據庫的某個pte[i ],一個就是當前進程內核頁 目錄頁表數據庫的某個 pte[j],可是隻有一個page和其對應。若是此時調度到其餘進程,其餘進程申請並訪問某個內存,則不會涉及到該物理頁面,因 爲其分配時首先要從 free_list中找一個page,而該物理頁面對應的page已經從free_list中脫離出來了,所以不存在該物理頁面被其 他進程改寫操做的狀況。內核中經過get_free_pages等方式獲取內存時,也不會涉及到該物理頁面,原理同前所述。
相關文章
相關標籤/搜索