内核页表和进程页表
初學(xué)內(nèi)核時,經(jīng)常被“內(nèi)核頁表”和“進程頁表”搞暈,不知道這到底是個啥東東,跟我們平時理解的頁表有和關(guān)系。。
內(nèi)核頁表:即書上說的主內(nèi)核頁表,在內(nèi)核中其實就是一段內(nèi)存,存放在主內(nèi)核頁全局目錄init_mm.pgd(swapper_pg_dir)中,硬件并不直接使用。
進程頁表:每個進程自己的頁表,放在進程自身的頁目錄task_struct.pgd中。
在保護模式下,從硬件角度看,其運行的基本對象為“進程”(或線程),而尋址則依賴于“進程頁表”,在進程調(diào)度而進行上下文切換時,會進行頁表的切換:即將新進程的pgd(頁目錄)加載到CR3寄存器中。從這個角度看,其實是完全沒有用到“內(nèi)核頁表”的,那么“內(nèi)核頁表”有什么用呢?跟“進程頁表”有什么關(guān)系呢?
1、內(nèi)核頁表中的內(nèi)容為所有進程共享,每個進程都有自己的“進程頁表”,“進程頁表”中映射的線性地址包括兩部分:
用戶態(tài)
內(nèi)核態(tài)
其中,內(nèi)核態(tài)地址對應(yīng)的相關(guān)頁表項,對于所有進程來說都是相同的(因為內(nèi)核空間對所有進程來說都是共享的),而這部分頁表內(nèi)容其實就來源于“內(nèi)核頁表”,即每個進程的“進程頁表”中內(nèi)核態(tài)地址相關(guān)的頁表項都是“內(nèi)核頁表”的一個拷貝。
2、“內(nèi)核頁表”由內(nèi)核自己維護并更新,在vmalloc區(qū)發(fā)生page fault時,將“內(nèi)核頁表”同步到“進程頁表”中。以32位系統(tǒng)為例,內(nèi)核頁表主要包含兩部分:
線性映射區(qū)
vmalloc區(qū)
其中,線性映射區(qū)即通過TASK_SIZE偏移進行映射的區(qū)域,對32系統(tǒng)來說就是0-896M這部分區(qū)域,映射對應(yīng)的虛擬地址區(qū)域為TASK_SIZE-TASK_SIZE+896M。這部分區(qū)域在內(nèi)核初始化時就已經(jīng)完成映射,并創(chuàng)建好相應(yīng)的頁表,即這部分虛擬內(nèi)存區(qū)域不會發(fā)生page fault。
vmalloc區(qū),為896M-896M+128M,這部分區(qū)域用于映射高端內(nèi)存,有三種映射方式:vmalloc、固定、臨時,這里就不像述了。。
以vmalloc為例(最常使用),這部分區(qū)域?qū)?yīng)的線性地址在內(nèi)核使用vmalloc分配內(nèi)存時,其實就已經(jīng)分配了相應(yīng)的物理內(nèi)存,并做了相應(yīng)的映射,建立了相應(yīng)的頁表項,但相關(guān)頁表項僅寫入了“內(nèi)核頁表”,并沒有實時更新到“進程頁表中”,內(nèi)核在這里使用了“延遲更新”的策略,將“進程頁表”真正更新推遲到第一次訪問相關(guān)線性地址,發(fā)生page fault時,此時在page fault的處理流程中進行“進程頁表”的更新
內(nèi)核頁表:即書上說的主內(nèi)核頁表,在內(nèi)核中其實就是一段內(nèi)存,存放在主內(nèi)核頁全局目錄init_mm.pgd(swapper_pg_dir)中,硬件并不直接使用。
進程頁表:每個進程自己的頁表,放在進程自身的頁目錄task_struct.pgd中。
在保護模式下,從硬件角度看,其運行的基本對象為“進程”(或線程),而尋址則依賴于“進程頁表”,在進程調(diào)度而進行上下文切換時,會進行頁表的切換:即將新進程的pgd(頁目錄)加載到CR3寄存器中。從這個角度看,其實是完全沒有用到“內(nèi)核頁表”的,那么“內(nèi)核頁表”有什么用呢?跟“進程頁表”有什么關(guān)系呢?
1、內(nèi)核頁表中的內(nèi)容為所有進程共享,每個進程都有自己的“進程頁表”,“進程頁表”中映射的線性地址包括兩部分:
用戶態(tài)
內(nèi)核態(tài)
其中,內(nèi)核態(tài)地址對應(yīng)的相關(guān)頁表項,對于所有進程來說都是相同的(因為內(nèi)核空間對所有進程來說都是共享的),而這部分頁表內(nèi)容其實就來源于“內(nèi)核頁表”,即每個進程的“進程頁表”中內(nèi)核態(tài)地址相關(guān)的頁表項都是“內(nèi)核頁表”的一個拷貝。
2、“內(nèi)核頁表”由內(nèi)核自己維護并更新,在vmalloc區(qū)發(fā)生page fault時,將“內(nèi)核頁表”同步到“進程頁表”中。以32位系統(tǒng)為例,內(nèi)核頁表主要包含兩部分:
線性映射區(qū)
vmalloc區(qū)
其中,線性映射區(qū)即通過TASK_SIZE偏移進行映射的區(qū)域,對32系統(tǒng)來說就是0-896M這部分區(qū)域,映射對應(yīng)的虛擬地址區(qū)域為TASK_SIZE-TASK_SIZE+896M。這部分區(qū)域在內(nèi)核初始化時就已經(jīng)完成映射,并創(chuàng)建好相應(yīng)的頁表,即這部分虛擬內(nèi)存區(qū)域不會發(fā)生page fault。
vmalloc區(qū),為896M-896M+128M,這部分區(qū)域用于映射高端內(nèi)存,有三種映射方式:vmalloc、固定、臨時,這里就不像述了。。
以vmalloc為例(最常使用),這部分區(qū)域?qū)?yīng)的線性地址在內(nèi)核使用vmalloc分配內(nèi)存時,其實就已經(jīng)分配了相應(yīng)的物理內(nèi)存,并做了相應(yīng)的映射,建立了相應(yīng)的頁表項,但相關(guān)頁表項僅寫入了“內(nèi)核頁表”,并沒有實時更新到“進程頁表中”,內(nèi)核在這里使用了“延遲更新”的策略,將“進程頁表”真正更新推遲到第一次訪問相關(guān)線性地址,發(fā)生page fault時,此時在page fault的處理流程中進行“進程頁表”的更新
總結(jié)
- 上一篇: linux内存管理——kmalloc和v
- 下一篇: poll模型