地址映射与共享
实验内容
- 用
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值,所以仍然会死循环。 |