我想出了這個問題,因爲我不明白如何在內核區域執行地址轉換。CPU要求地址高於0xC0000000時如何執行地址轉換(virt-> phy)?
據我所知,要翻譯0xC0000000
以上的任何地址,我們只需要減去這個地址PAGE_OFFSET
(除了內核初始化過程,我們需要一個8MB範圍的頁表)。但是在CPU執行需要地址的指令時,例如0xF0000020
,而系統只有256MB RAM,這沒有意義。
由於上述原因,我認爲內核確實有一個頁表,它允許MMU將高於0xC0000000
的虛擬地址轉換爲物理地址。因此,在什麼情況下我們可以直接減去PAGE_OFFSET
以及在什麼情況下我們需要內核頁表?
我可能在開始的時候出錯,所以請更正。
編輯
從< <瞭解Linux的虛擬內存管理>>,它說:內核頁表存在。現在,越來越迷茫......
3.6內核頁表
當系統第一次啓動,分頁沒有啓用,因爲頁表不 神奇初始化自己。每個體系結構實現這個不同,所以只討論x86情況。頁表初始化分爲兩個 階段。引導階段爲8MiB設置頁表,以便可以啓用分頁 單元。 第二階段初始化其餘頁表。我們 在下面的章節中討論這兩個階段。
3.6.1自舉
...
3.6.2敲定
負責敲定頁表的函數被調用paging_init()。圖3.4中可以看到x86上該函數的調用圖。
功能首先調用pagetable_init()來初始化必要 頁表以引用的所有物理存儲器中ZONE_DMA和ZONE_NORMAL。請記住,無法直接引用ZONE_HIGHMEM中的 高內存,並且臨時爲其設置映射 。對於內核使用的每個pgd t,調用引導存儲器 分配器(請參閱第5章)爲PGD分配一個頁面,並且如果可以使用PSE 位,則使用4MiB TLB條目而不是4KiB。如果不支持PSE 位,則會爲每個pmd分配一個PTE頁面。如果CPU 支持PGE標誌,則它也將被設置,以便頁表項將爲全局 ,並且對所有進程都可見。然後,pagetable_init()調用fixrange_init()在FIXADDR_START開始的虛擬地址空間末尾設置固定地址 空間映射。這些映射用於諸如本地高級可編程中斷控制器(APIC)之類的用途以及kmap_atomic()所需的FIX_KMAP_BEGIN 和FIX_KMAP_END之間的原子映射。最後,該函數調用 fixrang_init()來初始化與kmap()映射的普通高內存映射所需的頁表項。
pagetable_init()返回之後,內核空間中的頁表現在完全 初始化,因此靜態PGD(swapper_pg_dir)被裝入CR3寄存器,從而 該靜態表現在正在使用的尋呼單元。
paging_init()的下一個任務是負責調用kmap_init()到 用PAGE_KERNEL保護標誌初始化每個PTE。最後的任務是 來調用zone_sizes_init(),它初始化所有使用的區域結構。
正如你所說,要將虛擬地址從3G轉換到3G + 900MB,我們可以直接用PAGE_OFFSET減去這些地址。這是否意味着內核不需要任何頁表?但是,它確實存在,所以我不明白爲內核頁表提供什麼服務。請參閱編輯。 – sliter 2012-03-28 20:49:55
一切都需要線性模式的頁表;這個映射只是一個約定,可以更容易地訪問第一個900MB的物理內存。 – Neil 2012-03-29 20:43:51