地址映射与共享
实验内容
- 用
Bochs
调试工具跟踪Linux 0.11
的地址翻译(地址映射)过程,了解IA-32
和Linux 0.11
的内存管理机制; - 在
Ubuntu
上编写多进程的生产者-消费者程序,用共享内存做缓冲区; - 在信号量实验的基础上,为
Linux 0.11
增加共享内存功能,并将生产者-消费者程序移植到Linux 0.11
。
实验步骤
创建test.c
寻找物理地址
首先进入Linux-0.11目录内make编译系统,然后运行系统,编译运行test.c文件
1 | gcc -o test test.c |
此时会进入在test.c内的while死循环,然后ctrl+c暂停bochs。
此时需要让Linux-0.11的test跳出死循环,所以需要找到逻辑地址ds:0X00003004对应的物理地址,将它的内容更改为0。
在终端中输入sreg,得到gdtr的基址值为0x00005cb8,ldtr为0x0068即0000 0000 0110 1000 b,可知索引为1101b即13,TI位为0,即GDT中的第13项为LDT的段描述符。
输入
1 | xp /2w 0x00005cb8+13*8 |
可以得到LDT的基址为0x00fe92d0
ds段选择子为0x0017 => 0000 0000 0001 0111 b,可知索引为10b即2,TI位为1,即LDT中的第2项为ds的段描述符
输入
1 | xp/2w 0x00fe92d0+2*8 |
得到ds段描述符
可以知道ds的基址为0x10000000,所以0x3004对应的线性地址为0x10000000+0x3004=0x10003004
输入
1 | xp /w 64*4 |
获取页目录项
表所在的物理页框号为0x00fa7
,即页表在物理内存为0x00fa7000
处,从该位置开始查找3
号页表项
输入
1 | xp /w 0x00fa7000 + 3*4 |
线性地址0x10003004
对应的物理页框号为0x00fa6
,和页内偏移0x004
接到一起,得到0x00fa6004
,这就是变量i的物理地址
用
1 | xp /w 0x00fa6004 |
验证
修改物理地址,使其变量i为0
1 | setpmem 0x00fa6004 4 0 |
输入c,可以看到,会在bochs中顺利退出
添加系统调用
在unistd.h中增加下面的代码
再添加系统调用
注意:要在挂载下再修改一次
修改sys.h文件
增加函数声明
在system_call.s中把nr_system_calls改为78
增加shm.c
在kernel目录下
然后修改kernel下的Makefile
编写消费者和生产者程序
producer.c
consumer.c
运行验证
编译
1 | gcc -o pro producer.c |
输入
1 | pro > proOutput & |
输入
1 | sync |
关闭linux-0.11回到ubunt终端,输入sudo less hdc/usr/root/conOutput查看结果如下
问题回答
对于地址映射实验部分(第一部分),列出你认为最重要的几步(不超过四步),并给出你获得的实际数据。
1 | 输入命令u/7反汇编,查看变量i对应的逻辑地址 |
test.c
退出后,如果马上再运行一次程序,并再进行地址跟踪,你会发现哪些异同?为什么?
1 | 再运行一次程序,等同于重来,变量i重新被赋非0值,所以仍然会死循环。 |