C虚拟到物理地址映射
我是C语言的初学者,我正在尝试将虚拟地址转换为物理地址 我的代码到目前为止,但不知道如何翻译 我正在使用C虚拟到物理地址映射,c,page-tables,C,Page Tables,我是C语言的初学者,我正在尝试将虚拟地址转换为物理地址 我的代码到目前为止,但不知道如何翻译 我正在使用4Kb页面 我知道的转换是:对于givin地址0x12C000,最后三个数字不会被更改000,剩余的12C将被转换,然后将固定数字与转换后的数字组合。如果我错了,请纠正我,我如何在代码中执行taht #include <stdio.h> int main() { uint page_table[512] = { 0 }; page_table[200] = 0x
4Kb
页面
我知道的转换是:对于givin地址0x12C000,最后三个数字不会被更改000,剩余的12C将被转换,然后将固定数字与转换后的数字组合。如果我错了,请纠正我,我如何在代码中执行taht
#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;
}
#包括
int main(){
uint page_表[512]={0};
页码表[200]=0x1234;
页码表[300]=0x2345;
第页表格[511]=0x8000;
uint page_table_size=(sizeof(数组)/sizeof(数组[0]);
uint页面大小\u位12///2^12=4KB;
uint mask_offset((1),除非您在CPU的特权模式下运行,这通常意味着您在内核中不能运行。OS+CPU团队阻止您访问页表,您可以这样做的唯一方法是访问页表
如果您确实可以访问它们,并且您是一个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、unmaphys提供并移除指向给定物理地址的可用指针,getcr3()从386返回页表基址寄存器。
也就是说,有一些方法可以构造这些类型的页表,以便您可以间接地对它们进行寻址页面目录表中的条目指向页面目录表,然后您可以使用高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;
}
值得注意的是,在这个递归页表中,您选择哪个索引并不重要,而且该机制通常适用于任何页表定义,即内部和叶节点具有兼容的布局。除非您在CPU的特权模式下运行,这通常意味着您在内核中无法运行OS+CPU联合起来阻止您访问页表,唯一可以做到这一点的方法是访问页表
如果您确实可以访问它们,并且您是一个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、unmaphys提供并移除指向给定物理地址的可用指针,getcr3()从386返回页表基址寄存器。
也就是说,有一些方法可以构造这些类型的页表,以便您可以间接地对它们进行寻址页面目录表中的条目指向页面目录表,然后您可以使用高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;
}
值得注意的是,在此递归页表中,您选择的索引并不重要,该机制通常适用于任何页表定义,即内部和叶节点具有兼容的布局。您需要计算两个值:物理内存中的索引(页表)以及要添加到页\表条目地址的偏移量
page_table_index = log_address >> 12;
page_offset = log_address & 0xfff;
physical = (page_table[page_table_index] << 12) | page_offset;
page\u table\u index=log\u address>>12;
页面偏移量=日志地址&0xfff;
physical=(page_table[page_table_index]您需要计算两个值:物理内存中的索引(page_table)和添加到page_table项地址的偏移量
page_table_index = log_address >> 12;
page_offset = log_address & 0xfff;
physical = (page_table[page_table_index] << 12) | page_offset;
page\u table\u index=log\u address>>12;
页面偏移量=日志地址&0xfff;
物理=(第页表格[第页表格索引]如果你是C语言的初学者,你不应该担心虚拟地址或翻译。除非你写的是一个直接到硬件的内核,作为初学者你不应该这么做。@Someprogrammerdude我是初学者,因为我从未在C语言中使用过内存管理,但在C语言中使用过Other的东西did@Someprogrammerdude我从未研究过如何进行转换或如何进行转换完成了,谢谢你的帮助。在一个普通的程序中,你从来没有做过这样的事情。你需要解决的实际问题是什么?你的作业或练习是什么?请花点时间阅读,以及。你本质上是在问如何做位运算吗(bitshift via>>如果你是C的初学者,你不应该担心虚拟地址或翻译。除非你写的是一个直接到硬件的内核,作为初学者你不应该这么做。@Someprogrammerdude是初学者,因为我从未在C中使用过内存管理,但在C I中使用过Other之类的东西did@Someprogrammerdude我从来没有学过如何做conversion或它是如何完成的,感谢您在普通程序中提供的任何帮助,您从未做过此类事情。您需要解决的实际问题是什么?您的作业或练习是什么?请花一些时间阅读,以及。您本质上是在问如何进行逐位操作(通过>>bitshift)吗