5.3.6 虛擬地址、線性地址和物理地址之間的關係

內核代碼和數據的地址linux

  對於linux 0.11內核代碼和數據來講,在head.s程序的初始化操做中已經把內核代碼段和數據段都設置成長度爲16M的段。在線性地址空間中這兩個段的範圍重疊,都是從線性地址0開始到地址0XFFFFFF共16M地址範圍。在該範圍中含有內核全部的代碼、內核段表(GDT,IDT,TSS)、頁目錄表和內核的二級頁表、內核局部數據和內核臨時堆棧(將被用做第一個任務即任務0的用戶堆棧)。其頁目錄表和二級頁表已設置成把0-16M的線性地址空間一一對應到物理地址上,佔用了4個目錄項即4個二級頁表。所以對於內核代碼和數據來講,咱們能夠直接把它看做是物理內存中的地址。以下圖:shell

  所以,默認狀況下Linux 0.11內核最多可管理16MB的物理內存,共有4096個物理頁面,每一個頁面4KB。經過上述分析能夠看出:數據結構

1.內核代碼段和數據段區域在線性地址空間和物理地址空間中是同樣的,這樣設置能夠大大簡化內核的初始化操做函數

2.GDT和IDT在內核數據段中,所以他們的線性地址也一樣等同於他們的物理地址。在實模式下setup.s程序初始化操做中,咱們曾經設置過臨時的GDT和IDT,這是進入保護模式以前必須設置的。因爲這兩個表當時處於物理內存大約0x90200處,而進入保護模式以後內核系統模塊處於物理內存0開始位置,而且0x90200處的空間也被挪做他用(用於高速緩衝),所以在進入保護模式後,在運行的第一個程序head.s中要從新設置這兩個表。即設置GDTR和IDTR指向新的GDT和IDT,描述符也須要從新加載。因爲開啓分頁機制時這兩個表的位置沒有變更,所以無需再從新創建或移動表位置。spa

3.除任務0之外,全部其餘任務所須要的物理頁面與線性地址中不一樣或部分不一樣,所以內核須要動態的在主內存區中爲他們做映射操做,動態的創建頁目錄項和頁表項。雖然任務的代碼和數據也在內核中,但因爲它須要另行分配得到內存,所以也須要本身的映射表項。blog

任務0的地址對應關係進程

  任務0是系統中第一我的工啓動的任務。他的代碼段和數據段長度被設置爲640kb。該任務的代碼和數據直接包含在內核代碼和數據中,是從地址0開始的640KB的內容,所以它能夠直接使用內核代碼已經設置好的頁目錄和頁表進行分頁地址變換,一樣,它的代碼和數據在線性地址空間也是重疊的,對應的任務狀態段TSS0也是手工預設值好的,而且位於任務0數據結構中,參見sched.h第113行開始的內容。TSS0段位於內核sched.c程序的代碼中,長度爲104字節,具體位置參加圖5-23中"任務0結構信息"所示。三個位置的對應關係如圖5-15所示:內存

 

  因爲任務0直接包含在內核中,再也不須要爲其從新分配內存頁,它運行時須要的內核態堆棧和用戶態堆棧空間也都在內核代碼區中,而且因爲在內核初始化時(head.s)這些內核頁面在頁表項中的屬性都已經被設置成了0b111,即對應頁面用戶可讀寫且存在,所以用戶堆棧user_stack[]空間雖然在內核空間中,但任務0仍能對其進行讀寫操做。it

任務1的地址對應關係內存管理

  與任務0相似,任務1也是一個特殊任務。它的代碼也在內核代碼區域中。與任務0不一樣的是在線性地址空間中系統在使用fork()建立任務1(init進程)時爲存聽任務1的二級頁表而在內存中申請了一頁內存區域來存放,並複製了父進程的頁目錄和二級頁表項。所以任務1擁有本身的頁目錄和頁表表項,它把任務1佔用的線性空間範圍64M-128M(其實是64M-64M+640KB)也一樣映射到物理地址0-640KB處。此時任務1的長度也是640KB,而且其代碼段和數據段相重疊,只佔用一個頁目錄項和一個二級頁表。另外,系統還會爲任務1在主內存區域中申請一頁內存來存放它的任務數據結構和用做任務1的內核堆棧空間。任務數據結構中包括任務1的TSS段結構信息,以下圖:


  任務1的用戶態堆棧空間將直接共享使用處於內核代碼和數據區域(線性地址0-640KB)中任務0的用戶態堆棧空間user_stack[](參見kernek/sched.c,第67-72行),所以這個堆棧須要在任務1實際使用時保持「乾淨」,以確保被複制用於任務1的堆棧不含有無用數據,在剛開始建立任務1時,任務0的用戶態堆棧user_stack[]與任務1共享使用,但當任務1 開始運行時,因爲任務1映射到user_stack[]處的頁表被設置成只讀,使得任務1在執行堆棧操做時將會引發寫頁面異常,從而由內核另行分配主內存區頁面做爲堆棧空間使用。

  其餘任務的地址對應關係

  對於被建立的從任務2開始的其餘任務,它們的父進程都是init(任務1)進程,咱們已經知道,在linux 0.11系統中共能夠有64個進程同時存在,下面以任務2爲例來講明其餘任何任務隊地址空間的使用狀況。

  從任務2開始若是任務號以nr表示,那麼任務nr在線性地址空間中的起始位置被設定在nr*64M處,例如任務2的開始位置=nr*64M=2*64M=128M。任務代碼段和數據段的最大長度被設置爲64M,所以任務2佔有的線性地址空間範圍是128M-192M,共佔用64M/4M=16個頁目錄項,虛擬空間中任務代碼段和數據段都被映射到線性地址空間中相同的範圍,所以它們也會徹底重疊。圖5-17顯示出了任務2的代碼段和數據段在三種地址空間中的對應關係。


  在任務2被建立出來以後,將在其中運行execve()函數來執行shell程序,當內核經過複製任務1剛建立任務2時,除了佔用線性地址空間範圍不一樣之外(128M-128M+640K),此時任務2的代碼和數據在三種地址空間中的對應關係和任務1的相似。當任務2的代碼(init())調用execve()系統調用開始加載並執行shell()程序時,該系統調用會釋放掉從任務1複製的頁目錄和頁表表項及相應的內存頁面,而後爲新的執行程序shell從新設置頁目錄和頁表表項。在執行execve()函數時,系統雖然爲任務2分配了64M的空間範圍,可是內核並不會馬上爲其分配和映射物理頁面,只有當任務2開始執行時因爲發生缺頁而引發異常時纔會由內存管理程序爲其在主內存區中分配並映射一頁物理內存到其線性地址空間中,這種分配和映射物理內存的方法稱爲需求加載(load on demand).

相關文章
相關標籤/搜索