MOOC哈工大操作系统实验6:地址映射与共享

完成了本实验的前两个内容,即跟踪地址映射过程和在Unbuntu上利用共享内存编写生产者消费者程序。

1.用Bochs 调试工具跟踪 Linux 0.11 的地址翻译:

该实验的步骤在实验楼中有极其详细的说明,所以完全参照那个步骤做即可。在这里我记录了一些需要注意的点,以及我的实验过程。

先对逻辑地址、虚拟地址、线性地址、物理地址这几个概念做一个区分(来自linux0.11注释152页):
逻辑地址:指由程序产生的与段相关的偏移地址。
虚拟地址:由段选择符和段内偏移地址两个部分组成的地址。(有些资料不区分逻辑地址和虚拟地址的概念,将它们统称为逻辑地址)
线性地址:根据段选择符查段表得到的段基址,加上偏移地址就得到线性地址。是虚拟地址到物理地址变换的中间层,是处理器可寻址的内存空间(称为线性地址空间)中的地址。
物理地址:是地址变换的最终结果地址,实际内存存储器上的地址。

实验步骤:
通过sudo ./mount-hdc挂载后,进入hdc/usr/root目录,在其中创建test.c文件如下:

#include <stdio.h>

int i = 0x12345678;
int main(void)
{
   
    printf("The logical/virtual address of i is 0x%08x", &i);
    fflush(stdout);
    while (i)
        ;
    return 0;
}

接下来我们将用Bochs模拟器的调试功能,从逻辑地址开始,进行人工查找段表页表,翻译成最终的物理地址。Bochs调试的指令可以参考https://my.oschina.net/u/1777508/blog/1841996

1.得到逻辑地址
编译好 Linux 0.11 后,首先通过运行 ./dbg-asm 启动调试器,此时 Bochs 的窗口处于黑屏状态。此时打开了两个窗口,一个是Bochs窗口,一个是命令行窗口(注意如果在实验楼的话,不要点最小化,否则就打不开了。正常窗口尺寸就行,也不要最大化,否则会挡住另一个窗口)。

在命令行输入c,Bochs便会继续运行,启动了linux0.11,然后在linux中编译test.c文件,然后打开。出现如下信息,并进入无限循环。

The logical/virtual address of i is 0x00003004

打印出了变量i的逻辑地址,这个地址在任何人的机器上都是一样的。

2.寻找虚拟地址:
此时在命令行中按Ctrl+c ,暂停Bochs的运行,进入调试状态。命令行中显示如下信息:

(0) [0x00fc8031] 000f:00000031 (unk. ctxt): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000

如上图一般是000f,如果显示的是0008说明中断在了内核中,那么就要 c,然后再 ctrl+c,直到变为 000f 为止。如上图一般显示的下一条指令是 cmp …(这里指语句以 cmp 开头),否则就用 n 命令单步运行几步,直到停在 cmp …。

上图代码已经显示出变量i的虚拟地址是ds:0x3004了(段选择符+逻辑地址),我们也可以用命令 u /8,显示从当前位置开始 8 条指令的反汇编代码,即从while开始的机器语言代码反汇编成汇编语言代码(如下图),可以看到变量 i 保存在 ds:0x3004 这个地址,并不停地和 0 进行比较,直到它为 0,才会跳出循环。因此接下来我们要寻找虚拟地址 ds:0x3004 对应的线性地址。

<bochs:3> u /8
10000063: (                    ): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000
1000006a: (                    ): jz .+0x00000004           ; 7404
1000006c: (                    ): jmp .+0xfffffff5          ; ebf5
1000006e: (                    ): add byte ptr ds:[eax], al ; 0000
10000070: (                    ): xor eax, eax              ; 31c0
10000072: (                    ): jmp .+0x00000000          ; eb00
10000074: (                    ): leave                     ; c9
10000075: (                    ): ret                       ; c3

3.寻找线性地址
刚才找到的虚拟地址中,段选择符是ds,所以我们需要找到段表,再查段表得到ds段的具体信息。应用程序的段表是LDT,所以我们首先要找到段表LDT的位置。

寻找LDT表:
GDT(全局描述符表,操作系统使用的段表)中保存着 LDT 的物理地址,而ldtr 寄存器中记录着LDT物理地址在GDT表中的位置。
在命令行窗口输入sreg命令后,显示出各寄存器的信息,如下图,可以看到ldtr的值是 0x0068(不同人的机器可能得到的值不一样,之后注意对应好位置就好),转换成二进制是0000000001101000,其中1101这四位表示LDT的物理地址在GDT表中的位置(各个位的意义可以参考linux0.11注释书或者实验楼中的提示),1101转换成十进制是13。
下图中gdtr的值是GDT表的物理地址,即0x00005cb8。

<bochs:4> sreg
cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1
ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3
ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
es:s=0x0017, dl
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值