“操作系统实验”实验报告

地址映射与共享

实验名称:地址映射与共享

实验日期:2021.7.6

班级:物联网193

姓名:潘峰浩

学号:1930110720

一、实验目的

  • 深入理解操作系统的段、页式内存管理,深入理解段表、页表、逻辑地址、线性地址、物理地址等概念;
  • 实践段、页式内存管理的地址映射过程;
  • 编程实现段、页式内存管理上的内存共享,从而深入理解操作系统的内存管理

二、实验环境

  • oslab虚拟环境
  • 实验楼

三、实验内容

3.1 主要内容

  • 用 Bochs 调试工具跟踪 Linux 0.11 的地址翻译(地址映射)过程,了解 IA-32 和 Linux 0.11 的内存管理机制;
  • 在 Ubuntu 上编写多进程的生产者—消费者程序,用共享内存做缓冲区;
  • 在信号量实验的基础上,为 Linux 0.11 增加共享内存功能,并将生产者—消费者程序移植到 Linux 0.11。

3.2 跟踪地址翻译过程 首先以汇编级调试的方式启动 Bochs,引导 Linux 0.11,在 0.11 下编译和运行 test.c。它是一个无限循环的程序,永远不会主动退出。然后在调试器中通过查看各项系统参数,从逻辑地址、LDT 表、GDT 表、线性地址到页表,计算出变量 i 的物理地址。最后通过直接修改物理内存的方式让 test.c 退出运行。

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;
}
copy
copy

3.3 基于共享内存的生产者—消费者程序 本项实验在 Ubuntu 下完成,与信号量实验中的 pc.c 的功能要求基本一致,仅有两点不同:

不用文件做缓冲区,而是使用共享内存; 生产者和消费者分别是不同的程序。生产者是 producer.c,消费者是 consumer.c。两个程序都是单进程的,通过信号量和缓冲区进行通信。 Linux 下,可以通过 shmget() 和 shmat() 两个系统调用使用共享内存。

3.4 共享内存的实现 进程之间可以通过页共享进行通信,被共享的页叫做共享内存。本部分实验内容是在 Linux 0.11 上实现上述页面共享,并将上一部分实现的 producer.c 和 consumer.c 移植过来,验证页面共享的有效性。

所有使用同一块共享内存的进程都要使用相同的 key 参数。

如果 key 所对应的共享内存已经建立,则直接返回 shmid。如果 size 超过一页内存的大小,返回 -1,并置 errno 为 EINVAL。如果系统无空闲内存,返回 -1,并置 errno 为 ENOMEM。 shmflg 参数可忽略。 shmat() void *shmat(int shmid, const void *shmaddr, int shmflg); copy shmat() 会将 shmid 指定的共享页面映射到当前进程的虚拟地址空间中,并将其首地址返回。 如果 shmid 非法,返回 -1,并置 errno 为 EINVAL。 shmaddr 和 shmflg 参数可忽略。

四、实验过程及数据记录

  • 在linux-0.11/boot中添加test.c用于测试地址映射 图片描述

  • 通过运行./dbg-asm启动调试器,此时窗口处于黑屏状态 图片描述

    • 命令行窗口显示 图片描述
  • 命令行中输入c,继续程序的运行 图片描述

  • 在命令行中按下ctrl+c暂停程序的运行,使用反汇编指令u/7显示从当前位置开始的七条指令的反汇编指令 图片描述

  • 输入sreg显示所有寄存器信息 图片描述

  • LDTR寄存器值为0x0068,就是二进制的0000000001101000,表示LDT表存放在1101位置,使用xp/32w 0x00005cb8可以查看GDT表。 图片描述

  • 表中每一项占64位,所以要找的项的地址为0x00005cb8+138,使用命令:xp/2w 0x00005cb8 + 138 图片描述

  • 保证后面的两个数字和sreg输出中,LDTR后面的dl和dh值一致,将加粗的数字组合成0x00fd52d0,即为LDT表的物理地址 图片描述

  • 使用命令验证线性地址是否正确:calc ds:0x3004 图片描述

  • 使用命令creg查看页目录表位置,再使用命令:xp/68w 0查看内容 图片描述

  • 输入:xp/w 0+64获取页目录项,获得页表基地址,输入:xp/w 0x00ffe000+34得到物理基址,输入:xp/w 0x00fa6004得到内容即为test.c中变量值 图片描述

  • 输入setpmen 0xfa6004 4 0,将它设为0,在输入c跳出死循环,说明修改成功 图片描述

  • 在实验六的基础上在unitsd.h中添加系统调用 图片描述

  • 定义两个系统调用 图片描述

  • 将该文件复制到include中,在sys.h中添加函数声明,并将system_call.s中nr_system_calls改为78

  • 修改makefile文件 图片描述

  • 在kernel中添加shm.c 图片描述

  • 编写生产者消费者程序

    • producer.c 图片描述
    • consumer.c 图片描述
  • 将生产者消费者挂载虚拟磁盘进行编译 图片描述

  • 终端中输入sudo less hdc/usr/root/conOutput 图片描述

五、实验结果分析

用Bochs调试工具跟踪linux 0.11的地址映射过程没有错误,编写多进程的生产者消费者程序,使用共享内存进行缓冲,结果正确。将程序移植到linux 0.11中,结果正确。

六、问题解析

1、对于地址映射实验部分,列出你认为最重要的那几步(不超过 4 步),并给出你获得的实验数据。

  • 获得逻辑地址,LDT逻辑地址:0x00003004、物理地址:0x00005cb8。局部位置选择子:ldtr:0x0068。
  • 获得线性地址:DS段选择子ds:s=0x0017
  • 获得页目录及页表地址计算的物理地址,0x00fa3004 bochs:8 xp/w 0x00fa6004

2、test.c 退出后,如果马上再运行一次,并再进行地址跟踪,你发现有哪些异同?为什么?

  • 逻辑地址不变,但是物理地址改变了。逻辑地址是用户规模的所以是不会变的,只与test.c文件本身相关。
  • 物理地址改变可能是因为在test.c退出后可能有其他进程占用了之前的物理地址。

七、实验心得

这次实验让我更加的了解操作系统中段、页式内存管理、段表、页表逻辑地址与物理地址等概念,也让我对地址映射以及两种地址之间的转换有了更深的理解。
copy
最新评论
暂无评论~