实验基本内容

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

实验一

过程:

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

目的:

主要理解从逻辑地址到线性地址,再到物理地址的过程中,GDT、LDT表以及相关页表是怎么进行查找的过程。

编译Linux0.11

进入实验楼环境
cd oslab/
tar -zxvf hit... -C /home/shiyanlou

cd linux-0.11

linux-0.11目录中是linux的源代码,然后执行make all得到对应的Image,生成的目标文件是一个软盘镜像文件—— linux-0.11/Image。

到这里linux-0.11编译完成。

退回到oslab目录,执行./dbg-asm启动调试器

cd /home/shiyanlou/oslab
./dbg-asm

Bochs窗口处于黑屏状态

命令行窗口如下:

Next at t=0表示下面的指令是Bochs启动后要执行的第一条软件指令。这里单步跟踪进去就可以看到BIOS代码。

直接输入命令c,continue程序运行,启动linux0.11。

在Bochs界面编写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;
}

同时执行

gcc -o test test.c

得到如下:

执行test程序:

在命令行窗口按Ctrl+c,Bochs暂停运行,进入调试状态

注意其中红色框,因为第四个红框中没有出现cmp指令,因此使用n命令单步运行,如下

到这样即可。

使用u /8命令,显示从当前位置开始的8条指令的反汇编代码:

<bochs:4> 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

这就是 test.c 中从 while 开始一直到 return 的汇编代码。变量 i 保存在 ds:0x3004 这个地址,并不停地和 0 进行比较,直到它为 0,才会跳出循环。

为了让linux-0.11中运行的test跳出循环,需要找到逻辑地址ds:0x3004对应的物理地址,将其内容(变量i)改为0。

寻找ds:0x3004对应的线性地址

ds:0x3004是虚拟地址,ds表明这个地址属于ds段。

首先要找到段表LDT,然后通过ds的值在段表中找到ds段的具体信息,才能继续进行地址翻译。

LDT的段描述符

段描述符放在LDT中,而LDT的描述符放在GDT中,GDT的地址与LDT在GDT中的项的索引分别保存在gdtr和ldtr中。

可以看到ldtr的值是0x0068=0000 0000 0110 1000(二进制),根据段选择子的结构看

可以知道索引为1101(二进制),即为13,TI位为0,表示GDT中的第13项为LDT的段描述符,每个段描述符64bit—>8byte。

由于GDT的地址已经由gdtr给出,在物理地址的0x00005cb8,那么用xp /32w 0x00005cb8查看从该地址开始,32个字内容,及GDT表的前16项:

那么我们要查找的项的地址是0x00005cb8+ 13*8。

得到的LDT段描述符(与sreg指令得到的ldtr中的dl、dh相同),从而我们可以得到LDT的基址为0x00faa2d0。

上面的LDT的基址是根据段描述符的结构得来的:

上图中0xa2d00068是低32位,0x000082fa是高32位,从段描述符结构看,低32位的16到31位是基址的0-15位,然后高32位的0-7和24-31位是基址的16-31位,所以结果是LDT的基址为0x00faa2d0。

ds的段描述符和段基址

LDT表的前4项

<bochs:7> xp /8w 0x00faa2d0
[bochs]:
0x00faa2d0 <bogus+       0>:    0x00000000    0x00000000    0x00000002    0x10c0fa00
0x00faa2e0 <bogus+      16>:    0x00003fff    0x10c0f300    0x00000000    0x00fab000

ds段选择子为0x0017 => 0000 0000 0001 0111(二进制),可知索引为10(二进制)即2,TI位为1,即LDT中的第2项为ds的段描述符,每个段描述符64bit => 8byte。这里的TI位为1,所以去LDT表中查找。

从索引为2可知,ds的段描述符在LDT表的第3个,每个段描述符64bit,因此ds的段描述符为:

 0x00003fff    0x10c0f300

当然可以使用xp /2w 0x00faa2d0+2*8

同样根据段描述符的结构可得段基址为0x10000000。

ds:0x3004的线性地址

由于线性地址=段基址+段内偏移,所以ds:0x3004的线性地址为0x10000000+0x3004=0x10003004。

用calc ds:3004验证:

寻址ds:0x3004的物理地址

从线性地址到物理地址需要查找页表,页表工作原理如下:

首先需要算出线性地址中的页目录号、页表号和页内偏移,分别对应32位线性地址的10位+10位+12位,所以0x10003004的页目录号为64,页号为3,页内偏移为4。

页目录表的位置由CR3寄存器指引。creg命令可以看到:

所以页目录表的基址为0。

页目录表和页表中的内容很简单,是 1024 个 32 位(正好是 4K)数。这 32 位中前 20 位是物理页框号,后面是一些属性信息(其中最重要的是最后一位 P)。其中第 65 个页目录项就是我们要找的内容,用“xp /w 0+64*4”查看:

其中027为属性。页表所在物理页框号为0x00fa5,即页表在物理内存的0x00fa5000位置。从该位置开始查找3号页表项,得到(xp /w 0x00fa5000+3*4)

其中067是属性,那么线性地址0x10003004对应的物理页框号为0x00fa3,和页内偏移0x004接到一起就是0x00fa3004。

使用命令xp /w 0x00fa3004,进行验证,如下:

可以看到这个数值确实是test.c中i的初始值。

说明0x00fa3004是对应物理地址。

修改对应物理地址中的值完成实验

现在,通过直接修改内存来改变 i 的值为 0,命令是: setpmem 0x00fa3004 4 0,表示从 0x00fa3004 地址开始的 4 个字节都设为 0。然后再用“c”命令继续 Bochs 的运行,可以看到 test 退出了,说明 i 的修改成功了,此项实验结束。

linux0.11—内存管理实验相关推荐

  1. Linux0.11内存管理,linux0.11内存管理

    描述linux 0.11的内存管理主要内容. 1:内存初始化 linux 0.11最大支持16MB的物理内存. main函数和mem_init函数对内存进行了初始化. 主要使用数组mem_map[]来 ...

  2. 操作系统实验11:内存管理实验(DAY 62)

    文章目录 1:实验要求: 2:代码实现 3:实验分析: 4:结果分析 1:出现两个进程 2:设置内存空间为256 3:再重复一次上一步操作 4:输入5,展示内存空间 5:输入4,杀死2号进程. 1:实 ...

  3. 708-Linux内存管理实验

    Linux内存管理实验 一.实验内容 1.利用boches观测 linux0.11 下的 GDT 表和 LDT 表内容. 2.利用bochs观测 linux0.11 下的内存地址映射过程以及分页机制的 ...

  4. Linux系统内存管理实验报告,linux内存管理实验报告

    <linux内存管理实验报告>由会员分享,可在线阅读,更多相关<linux内存管理实验报告(13页珍藏版)>请在人人文库网上搜索. 1.操作系统实验报告院别:XXXXXX班级: ...

  5. (实验37)单片机,STM32F4学习笔记,代码讲解【内存管理实验】【正点原子】【原创】

    文章目录 其它文章链接,独家吐血整理 实验现象 主程序 内存池初始化程序 代码讲解 其它文章链接,独家吐血整理 (实验3)单片机,STM32F4学习笔记,代码讲解[按键输入实验][正点原子][原创] ...

  6. 1709 ltsb 内存占用_「正点原子STM32Mini板资料连载」第三十二章 内存管理实验

    1)实验平台:正点原子STM32mini开发板 2)摘自<正点原子STM32 不完全手册(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第三十二章 内存管理实验 上一章,我 ...

  7. linux内存实验,LINUX编程-实验五 内存管理实验

    实验五内存管理实验 1.目的要求 (1)学习使用内存管理库函数. (2)学习分析.改正内存错误. 2.实验内容 (1)内存库函数实验 ●malloc函数 原型:extern void *malloc( ...

  8. linux内存管理实验malloc,linux内存管理实验报告.doc

    linux内存管理实验报告 操作系统实验报告 院别:XXXXXX 班级:XXXXXX 学号:XXXXXX 姓名:稻草人 实验题目:内存管理实验 实验目的 通过本次试验体会操作系统中内存的分配模式: 掌 ...

  9. Linux系统内存管理实验报告,Linux 内存管理 综合实验报告.pdf

    Linux 内存管理 综合实验报告 计算机与通信学院 Linux 内存管理 综合实验报告 指导老师:孙建华 组员 :夏槟 20040810720 段翼真 20040810503 米晓亮 2004081 ...

最新文章

  1. 用C#钩子写一个改键外挂
  2. linux下top命令参数解释
  3. C语言 | 求级数的和
  4. android插件化-获取apkplug框架已安装插件-03
  5. java基础学习笔记(二)
  6. 【原创】为什么 Redis 重启后没有正确恢复之前的内存数据
  7. css中调整高度充满_6个很棒的PostCSS插件,让您成为一个CSS向导
  8. 远程连接mysql速度慢的解决方法:skip-name-resolve取消DNS的反向解析
  9. golang for循环时修改自身的值
  10. server2008实验之七 利用FSRM实现文件服务器精确管理.
  11. Hyperion神器之SmartView产品(下篇)
  12. 干货分享:【IT-PMP学堂】PMP 文档与配置管理
  13. 学术论文写作之引言(Introduction)怎么写
  14. 学写网页 #05# CSS Mastery 笔记 1~3
  15. 解决ValueError: too many values to unpack
  16. 企业微信禁用成员是什么意思?
  17. 【递推】HDU -2018 母牛的故事斐波那契兔子数列
  18. 【NOI OJ】18 Tomorrow never knows?(未知的明天)
  19. python最新版本是多少(python最新版)
  20. 分享一下米佳汇作者对网络新人的建议

热门文章

  1. 提示ora-04098:触发器无效且未通过重新验证
  2. 找人要代码的邮件怎么写
  3. 计组课设:单周期31条MIPS指令CPU设计(含代码)
  4. 微信小程序实现订单多商品评价(页面模板)
  5. 相机sd卡受损怎么修复?sd卡数据恢复靠这招
  6. IntelliJ IDEA自带的接口测试神器HttpClient
  7. 【SpringMVC架构】SpringMVC入门实例,解析工作原理(二)
  8. FL Studio21水果编曲高级版本音乐编曲工具
  9. teamviewer 文件传输服务器关机,teamviewer进行文件传输的详细步骤讲述
  10. 别怕变老吉他谱(完美还原艾热个人直播版本)