实验名称:地址映射与共享
实验日期:7.7
班级:物联网194
姓名:舒文杰
学号:1930110734
一、实验目的
深入理解操作系统的段、页式内存管理,深入理解段表、页表、逻辑地址、线性地址、物理地址等概念; 实践段、页式内存管理的地址映射过程; 编程实现段、页式内存管理上的内存共享,从而深入理解操作系统的内存管理。
二、实验环境
本操作系统实验的硬件环境是 IA-32(x86) 架构的 PC 机,主要软件环境是 Bochs + gcc + Linux 0.11 源代码。
三、实验内容
用 Bochs 调试工具跟踪 Linux 0.11 的地址翻译(地址映射)过程,了解 IA-32 和 Linux 0.11 的内存管理机制;
在 Ubuntu 上编写多进程的生产者—消费者程序,用共享内存做缓冲区;
在信号量实验的基础上,为 Linux 0.11 增加共享内存功能,并将生产者—消费者程序移植到 Linux 0.11。
四、实验过程及数据记录
1.准备环境
cd /home/shiyanlou/oslab
tar -zxvf hit-oslab-linux-20110823.tar.gz -C /home/shiyanlou
ls -al
copy
2.进入Linux-0.11目录内make编译系统,然后回到oslab目录
3.挂载hdc文件系统,在usr/root目录内增加test.c文件用于测试地址映射
4.使用汇编级调试
./dbg-asm
copy
输入c开始运行,编译并运行test.c
gcc -o test test.c
./test
copy
5.进入死循环,按下Ctrl+C暂停bochs进行调试,
6.寻找LDT表: GDT(全局描述符表,操作系统使用的段表)中保存着 LDT 的物理地址,而ldtr 寄存器中记录着LDT物理地址在GDT表中的位置。
输入sreg命令后,显示出各寄存器的信息
ldtr的值是 0x0068,转换成二进制是0000000001101000,其中1101这四位表示LDT的物理地址在GDT表中的位置,1101转换成十进制是13。 下图中gdtr的值是GDT表的物理地址,即0x00005cb8。
7.用 xp /32w 0x00005cb8 命令查看从GDT表的物理地址开始,32 个单位的内容,即 GDT 表的前 16 项
8.0x10003004 的页目录号是 64,页号 3,页内偏移是 4。 页目录表的位置由 CR3 寄存器指引。输入“creg”命令可以看到CR3=0x00000000,
9.此机器对于物理地址为 0x00fa6004
输入setpmem 0x00fa7004 4 0
切回boch界面
10.修改unistd.h
11.sys.h修改
12.添加shm.c
13.修改Kernel下的Makefile文件
14.编写生产者消费者 生产者:
/*producer*/
#define __LIBRARY__
#include <stdio.h>
#include <unistd.h>
#include <linux/kernel.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/sem.h>
_syscall2(sem_t *,sem_open,const char *,name,int,value);
_syscall1(int,sem_post,sem_t *,sem);
_syscall1(int,sem_wait,sem_t *,sem);
_syscall1(int, shmat, int, shmid);
_syscall2(int, shmget, unsigned int, key, size_t, size);
#define PRODUCE_NUM 200
#define BUFFER_SIZE 10
#define SHM_KEY 2018
int main(int argc, char* argv[])
{
sem_t *Empty,*Full,*Mutex;
int i, shm_id, location=0;
int *p;
Empty = sem_open("Empty", BUFFER_SIZE);
Full = sem_open("Full", 0);
Mutex = sem_open("Mutex", 1);
if((shm_id = shmget(SHM_KEY, BUFFER_SIZE*sizeof(int))) < 0)
printf("shmget failed!");
if((p = (int * )shmat(shm_id)) < 0)
printf("shmat error!");
for(i=0; i<PRODUCE_NUM; i++)
{
sem_wait(Empty);
sem_wait(Mutex);
p[location] = i;
sem_post(Mutex);
sem_post(Full);
location = (location+1) % BUFFER_SIZE;
}
return 0;
}
copy
消费者:
/*consumer*/
#define __LIBRARY__
#include <stdio.h>
#include <unistd.h>
#include <linux/kernel.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/sem.h>
_syscall2(sem_t *,sem_open,const char *,name,int,value);
_syscall1(int,sem_post,sem_t *,sem);
_syscall1(int,sem_wait,sem_t *,sem);
_syscall1(int,sem_unlink,const char*,name);
_syscall1(int, shmat, int, shmid);
_syscall2(int, shmget, unsigned int, key, size_t, size);
#define PRODUCE_NUM 200
#define BUFFER_SIZE 10
#define SHM_KEY 2018
int main(int argc, char* argv[])
{
sem_t *Empty,*Full,*Mutex;
int used = 0, shm_id,location = 0;
int *p;
Empty = sem_open("Empty", BUFFER_SIZE);
Full = sem_open("Full", 0);
Mutex = sem_open("Mutex", 1);
if((shm_id = shmget(SHM_KEY, BUFFER_SIZE*sizeof(int))) < 0)
printf("shmget failed!\n");
if((p = (int * )shmat(shm_id)) < 0)
printf("link error!\n");
while(1)
{
sem_wait(Full);
sem_wait(Mutex);
printf("pid %d:\tconsumer consumes item %d\n", getpid(), p[location]);
fflush(stdout);
sem_post(Mutex);
sem_post(Empty);
location = (location+1) % BUFFER_SIZE;
if(++used == PRODUCE_NUM)
break;
}
sem_unlink("Mutex");
sem_unlink("Full");
sem_unlink("Empty");
return 0;
}
copy
14.运行bochs,输入: gcc -o pro producer.c gcc -o con consumer.c 编译这两个程序, 然后输入 pro > proOutput & con > conOutput & 来同时运行这两个程序,并将结果保存到proOutput和conOutput中。 最后输入sync。
五、实验结果分析 用 Bochs 调试工具跟踪 Linux 0.11 的地址翻译(地址映射)过程正确,在 Ubuntu 上编写多进程的生产者—消费者程序,用共享内存做缓冲 区,结果正确无误;在信号量实验的基础上,为 Linux 0.11 增加共享内存功能,并将生产者—消费者程序移植到 Linux 0.11,运行结果正确
六、实验心得
问题1.对于地址映射实验部分,列出你认为最重要的那几步(不超过 4 步),并给出你获得的实验数据。
答:1.输入命令u/7反汇编,查看变量i对应的逻辑地址。
2.逻辑地址找虚拟地址要通过段表,也就是IDT表,然后IDT表要根据LDTR寄存器和GDT表,对应的命令就是sreg。
3.根据ds(代码段)寄存器查找IDT表,得到基址,然后通过基址 + 逻辑地址 = 虚拟地址。
4.根据虚拟地址找到物理地址,核心就是查找页表。
问题2.test.c 退出后,如果马上再运行一次,并再进行地址跟踪,你发现有哪些异同?为什么?
答:首先再运行一次程序,相当于一切都是重来的,变量i重新被赋非0值,所以仍然还是会死循环。 继续进行地址跟踪,根据虚拟地址找到物理地址,发现物理地址和第一次运行时的不一样了,因为在这个进程没有被运行时,内存是会被释放的,所以其他进程是可以利用这个内存的,虽然还是给它这个虚拟地址,但是重新分配内存的时候,物理地址并不一定还是那个地址。
本次实验深入理解了操作系统的段、页式内存管理,段表、页表、逻辑地址、线性地址、物理地址等概念。
学习时间 76分钟
操作时间 45分钟
按键次数 3917次
实验次数 5次
报告字数 5953字
是否完成 完成