Virtual, Linear, and Physical Addresses
在x86体系中,虚拟地址(Virtual Address)是由两部分组成,一个是段选择子(segment selector),另一个是段内偏移(segment offset)。线性地址(Linear Address)指的是通过段地址转换机构把虚拟地址进行转换之后得到的地址。物理地址(Physical Addresses)是分页地址转换机构把线性地址进行转换之后得到的真实的内存地址,这个地址将会最终送到你的内存芯片的地址总线上。
我们所编写的C语言程序中的指针的值是虚拟地址中段内偏移部分的值。在boot/boot.S文件中,我们引入了一个全局描述符表,这个表通过把所有段的基址设置为0,界限设置为0xffffffff的方式,关闭了分段管理的功能。因此虚拟地址中的段选择子字段的内容已经没有任何意义,线性地址的值总是等于虚拟地址中段内偏移的值。
回顾一下lab1中的part 3,我们引入了一个简单的页表,使得内核可以运行与0xf0100000的虚拟地址空间,尽管它所在的真实位置是物理地址0x00100000处,刚刚好在ROM BIOS之上。这个页表仅仅映射了4MB的内存空间。在我们这个JOS操作系统中,我们希望把这种映射扩展到物理内存的头256MB空间上,并且把这部分物理空间映射到从0xf0000000开始的虚拟空间中,以及一些其他的虚拟地址空间中。
Exercise3:
通过GDB,我们只能通过虚拟地址来查看内存所存放的内容,但是如果我们能够访问物理内存的话,肯定会更有帮助的。我们可以看一下QEMU中的一些常用指令,特别是xp指令,可以允许我们去访问物理内存地址。
“QEMU中有一个内置的监控器(moniter),首先通过在运行着QEMU软件的terminal里面输入 ctrl-a c,可以让我们切换到这个监控器。” 这个是官方给出的做法,但是我是通过xshell远程连接,貌似快捷键冲突,没有响应的。后来发现在lab目录下面输入如下指令,一样可以打开moniter:
qemu-system-i386 -hda obj/kern/kernel.img -monitor stdio -gdb tcp::26000 -D qemu.log
打开monitor后,就可以输入如下比较常见的指令:
xp/Nx paddr – 查看paddr物理地址处开始的,N个字的16进制的表示结果。
info registers – 展示所有内部寄存器的状态。
info mem – 展示所有已经被页表映射的虚拟地址空间,以及它们的访问优先级。
info pg – 展示当前页表的结构。(我这版本的qemu没有该指令)
在之后的实验中,你将会经常遇到一种情况,多个不同的虚拟地址被同时映射到相同的物理页上面。这时我们需要记录一下每一个物理页上存在着多少不同的虚拟地址来引用它,这个值存放在这个物理页的PageInfo结构体的pp_ref成员变量中。当这个值变为0时,这个物理页才可以被释放。通常来说,任意一个物理页p的pp_ref值等于它在所有的页表项中,被位于虚拟地址UTOP之下的虚拟页所映射的次数(UTOP之上的地址范围在启动的时候已经被映射完成了,之后不会被改动)。
当我们使用page_alloc函数的时