实验任务:
- 用Bochs调试工具跟踪Linux 0.11的地址翻译(地址映射)过程,Linux 0.11的内存管理机制;
- 在信号量实验的基础上,为Linux 0.11增加共享内存功能,并将生产者—消费者程序移植到Linux 0.11
地址映射
Step1:运行命令./dbg-asm 后再输入c 即可进入虚拟机调试模式
Step2:在Linux011下写入如下程序
#include <stdio.h>
int i=0x12345678;
int mian(void){
printf("the logcial address of i is 0x%08x",&i);
fflush(stdout);
while(i);
return 0;
}
由于while(i)是一个死循环,所以test是一个无限循环的进程,注意:绝对不能写while(1),因为这样就不能知道i这个变量具体储存在哪个地方了。
运行test会出现一下信息:
The logical address of i is 0x00003004
这打印出来的是逻辑地址,即离开程序段首的偏移地址。
由于test有一个死循环,进程不会退出,正是因为如此才可以查到逻辑地址、LDT表、GDT表、页表的信息才能在调试命令查看。
使用Ctrl+C,Bochs会暂停运行,进入调式状态。
可知i存在逻辑地址DS:0X3004中,目前的任务是寻找DS:0x3004对应的物理地址,追踪地址转换的过程。
在保护模式下DS并非直接指向内存空间,DS寄存器仍然要通过找到DS寄存器的对应的段表,在段表中找到DS段的信息,用DS对应的值在段表中查询即可获得DS段的地址,才能最终查到虚拟地址。
要查到DS段,首先得找到对应的段表,目前进程对应的段表(LDT),正在被LDTR寄存器所指向。
故先用serg命令找到相关信息。
MMU先通过CS的值去查LDT表。步骤:首先,从ldtr寄存器中找到LDT表的基址,再根据CS寄存器中的偏移地址找到对应的LDT段表项。
LDTR寄存器的值为0000 0000 0110 1000,而LDTR后三位为特权级,故当前进程的LDT表存放在GDT表的1101(13号)位置。GDT表的位置由GTDR给出,故当前LDT表的位置为"0x00005cb8+13*8"。
可知内容为“0X52d00068 0x00082fd”,根据GDT表的格式,可以写出物理基址。
LDT表的物理地址为“00fd52d0”
再执行指令“00fd52d0”可以得到:
即为LDT表的前四项内容。
DS=0x0017,则索引值为0x10,表示要从LDT表找第16个字节开始的内容,LDT每项占8个字节,故DS的基址为“0x00003ff 0x10c0f300”按照同样的格式基址为DS为“10000000” 。