涉及内存映射的过程
跟踪JOS内核
- 使用QEMU和GDB跟踪内核文件。在执行
movl %eax %cr0
前后,内存地址0x0010|0000
和0xf010|0000
存放着什么? - 如果上面的指令没执行,而是被跳过,那么第一条出错的指令会是什么?可以通过注释
kern/entry.S
文件的这一行来进行验证。
问题1
根据前文描述,可以先设置断点在 0x0010|000C
处,这是kernel的entry point。然后一步步运行到 movl %eax %cr0
之前。查看运行它前后的内存地址 0x0010|0000
和 0xf010|0000
处存放的32-bit,4字节分别是啥。
可以发现一开始是不相等的,后面变成相等了。下面解释2:
在实验指导中,也明确写着一旦 CR0_PG 被设置(Once CR0_PG is set),就会发生内存映射的行为,具体看原文档。
上面的指令可以看到 (new cr0) = (old cr0) or $0x80010001
,最终得到最高位为1,查阅资料3可知最高位即为PG位。因此运行完 movl %eax %cr0
后,就开启了内存映射。
另外gdb在调试时访问的内存都是虚拟内存,因此 x/4xb 0xf010|0000
其实是访问物理内存 0x0010|0000
,因此不奇怪二者的内容是一样的。
问题2
如果注释了这一句,那就没有开启内存映射,影响肯定是影响后面的内容,我们直接在上面调试的时候继续执行后面的几条语句如下:
可以发现后两条语句实现的功能是跳转到 0xf010002f
这个位置,由于没有内存映射。肯定是无法访问到这个地址空间的。如果真的注释了,也可以发现在 qemu 窗口能看到报错信息 qemu: fatal: Trying to execute code outside RAM or ROM at 0xf010002c