[英]C Virtual to physical address mapping
我是 C 的初學者,我正在嘗試將虛擬地址轉換為物理地址。
我的代碼到目前為止,但不知道如何翻譯。
我正在使用4Kb
頁面。
我知道的轉換是:對於給定地址:0x12C000,最后三個數字不會變成000,其余的12C將被轉換,然后將固定數字與轉換后的數字結合起來。 如果錯了,請糾正我,我該如何在代碼中做到這一點?
#include <stdio.h>
int main() {
uint page_table[512] = { 0 };
page_table[200] = 0x1234;
page_table[300] = 0x2345 ;
page_table[511] = 0x8000 ;
uint page_table_size = (sizeof(array)/sizeof(array[0]));
uint page_size_bits 12 // // 2^12 = 4KB;
uint mask_offset ((1<<page_size_bits)-1);
// example of correct outputs:
uint log_addr = 0x12C000;
/* should be 0x2345000 */
uint correctoutput;
log_addr = 0x12CFFF;
/* should be 0x2345FFF */
correctoutput;
log_addr = 0x1FF84A;
/* should be 0x800084A */
correctoutput;
}
除非你在 CPU 的特權模式下運行,這通常意味着你在 kernel 中你不能。 OS + CPU 聯手阻止您訪問頁表,而您可以做到這一點的唯一方法是訪問頁表。
如果您確實可以訪問它們,並且您是一個沒有 PAE 運行的 32 位 386 程序,它看起來像這樣:
extern void *mapphys(unsigned pa);
extern unsigned getcr3(void);
unsigned vtop(unsigned va) {
unsigned *pt, t;
pt = mapphys(getcr3());
t = pdir[va>>22];
unmapphys(pt);
if (t & 1) {
pt = mapphys(t & ~ 0xfff);
t = pt[(va >> 12) & 0x3ff];
unmapphys(pt);
if (t & 1) {
return (t &~ 0xfff) | (va & 0xfff);
}
error("page table entry undefined for %#x\n", va);
return -1;
} else {
error("page directory entry undefined for %#x\n", va);
return -2;
}
}
其中 maphys、unmapphys 提供和刪除指向給定物理地址的可用指針,getcr3() 從 386 返回頁表基址寄存器。也就是說,有一些方法可以構建這些類型的頁表,以便您可以間接尋址它們. 例如,如果您將頁目錄表中的最后一個(索引 1023)條目指向頁目錄表,那么您可以使用地址空間的高 4M-4K 作為一種頁表 map; 最后4K的地址空間是頁面目錄本身的map。 使用此設置,我可以改為:
unsigned vtop(unsigned va) {
unsigned *pmap = (unsigned *)0xff800000;
unsigned *pdmap = (unsigned *)0xfffff000;
if (pdmap[va>>22] & 1) {
if (pmap[va>>12] & 1) {
return (pmap[va>>12]&~0xfff) | (va & 0xfff);
}
error("page table entry undefined for %#x\n, va);
return -1;
}
error("page dir entry undefined for %#x\n", va);
return -2;
}
值得注意的是,在這個遞歸頁表中,選擇哪個索引並不重要,該機制一般適用於任何內部和葉節點布局兼容的頁表定義。
您需要計算兩個值:物理 memory (page_table) 的索引和添加到 page_table 條目地址的偏移量。
page_table_index = log_address >> 12;
page_offset = log_address & 0xfff;
physical = (page_table[page_table_index] << 12) | page_offset;
低 12 位是偏移量。 你保留地址的那部分。 您將這 12 位移開,剩下的就是 page_table 數組中的頁碼。 然后,您可以查找 page_table 以獲取基地址,為該地址中的 12 位騰出空間並插入偏移量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.