簡體   English   中英

C 虛擬到物理地址映射

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM