我知道虚拟地址如何变成物理地址有一种映射机制。
如下所示,线性地址包含三个部分
图示如下:

现在,当我查看Memylayout.h中的Xv6源代码时
#define V2P(a) (((uint) (a)) - KERNBASE)
#define P2V(a) (((void *) (a)) + KERNBASE)
#define V2P_WO(x) ((x) - KERNBASE) // same as V2P, but without casts
#define P2V_WO(x) ((x) + KERNBASE) // same as P2V, but without casts在不执行地址转换过程的情况下,V2P或P2V如何正确工作?
发布于 2018-05-14 16:40:08
V2P和P2V宏所做的事情并不比你想象的要多。它们只是减去并添加标记为2GB的KERNBASE常量。
您似乎正确地理解了MMU的硬件映射机制。映射规则由每个进程页表保存。这些表构成进程的虚拟空间。
具体来说,在XV6中,正在构建进程的虚拟空间结构(通过适当的映射),如下所示:
如上图所示,XV6专门构建进程的虚拟地址空间,以便2GB-4GB虚拟地址映射到0到PHYSTOP物理地址(分别)。正如XV6官方评论中所解释的:
Xv6包含内核在每个进程的页面表中运行所需的所有映射;这些映射都出现在KERNBASE上面。它将虚拟地址KERNBASE:KERNBASE+PHYSTOP映射到0:PHYSTOP。
还具体说明了作出这项决定的动机:
这种映射的一个原因是内核可以使用自己的指令和数据。另一个原因是内核有时需要能够编写给定的物理内存页,例如在创建页表页时;让每个物理页都出现在可预测的虚拟地址上,这很方便。
换句话说,因为内核使所有页面表将2GB虚拟映射为0物理(并且一直到PHYSTOP),所以我们可以很容易地找到超过2GB的虚拟地址的物理地址。例如:虚拟地址0x10001000的物理地址很容易找到:它是0x00001000,我们只需减去2GB,因为这就是我们映射它的方式。
这种“解决方案”可以帮助内核轻松地完成转换,例如,用于构建和操作页表(需要计算物理地址并将其写入内存)。
当然,上面的“解决办法”不是免费的,因为这使我们浪费了宝贵的虚拟地址空间(2GB ),因为现在每个物理地址至少已经有一个虚拟地址了。即使我们永远不会使用它。这使得真正的进程只剩下整个虚拟地址留下的2GB (总共是4GB,因为我们使用32位来计数地址)。XV6的官方评论也对此作了解释:
这种安排的一个缺点是xv6不能使用超过2GB的物理内存。
我建议您在“”标题下的XV6评论中阅读更多关于这种方式的内容。XV6评论
https://stackoverflow.com/questions/50073792
复制相似问题