C Отображение виртуального адреса в физический - PullRequest
0 голосов
/ 04 ноября 2019

Я новичок в C, я пытаюсь преобразовать виртуальные адреса в физические.

Мой код пока, но не знаю, как с переводом.

Я использую 4Kb страниц.

Я знаю следующее преобразование: для адреса givin: 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; 

}

Ответы [ 2 ]

1 голос
/ 04 ноября 2019

Если вы не работаете в привилегированном режиме ЦП, что обычно означает, что вы в ядре , вы не можете. Процессор OS + объединяется, чтобы предотвратить доступ к таблицам страниц, и единственный способ сделать это - получить доступ к таблицам страниц.

Если у вас был доступ к ним, и вы были 32-битным 386программа, запущенная без PAE, будет выглядеть примерно так:

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 в качестве своего рода таблицы таблиц страниц;и последние 4K адресного пространства - это карта самого каталога страниц. С помощью этой настройки я могу вместо этого:

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;
}

Стоит отметить, что в этой рекурсивной таблице страниц выбранный вами индекс не важен, и механизм обычно применим к любымОпределение таблицы страниц, которое является внутренним и конечным узлами, имеет совместимые макеты.

0 голосов
/ 05 ноября 2019

Вам необходимо вычислить два значения: индекс в физической памяти (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 битов в этом адресе и вставить смещение.

...