操作系统——认识保护模式(二)分页
实验目的
- 认真阅读章节资料,掌握什么是分页机制
- 调试代码,掌握分页机制基本方法与思路
– 代码3.22中,212行—237行,设置断点调试这几个循环,分析究竟在这里做了什么? - 掌握PDE,PTE的计算方法
– 动手画一画这个映射图 - 熟悉如何获取当前系统内存布局的方法
- 掌握内存地址映射关系的切换
– 画出流程图 - 基础题:依据实验的代码,
– 自定义一个函数,给定一个虚拟地址,能够返回该地址从虚拟地址到物理地址的计算过程,如果该地址不存在,则返回一个错误提示。
– 完善分页管理功能,补充alloc_pages, free_pages两个函数功能 - 进阶题(选做)
– 设计一个内存管理器,选择其一实现:首次适应算法、最佳适应算法、伙伴算法,要求实现内存的分配与回收。(提示,均按照页为最小单位进行分配、对于空闲空间管理可采用位图法或者双向链表法管理)
实验环境:
VMware + Ubuntu32位
实验步骤:
1. 认真阅读章节资料,掌握什么是分页机制;
2. 调试代码3.22;
使用的是在断点位置添加jmp $的方法进行调试。从上图可以看出,他在不断执行一个循环,那么这个循环是在干什么呢?
从代码的注释我们可以看到一个大致过程,总的来说就是在初始化页目录以及页表项,之后再初始化所有页表,申请对应的页表空间。
1k个表项,指向1k个页表,共4M内存空间;每一页指向4K的空间。
3.分析PTE,PDE的映射;
从PTE基址开始,根据地址偏移寻找到所指PDE的基址;
根据上步找到的PDE基址,加上地址偏移寻找到页的基址;
根据获得的页的基址,加上地址偏移寻找到物理地址。
为什么PageTblBase初始值为2M+4K?
因为页目录表大小共4K.
4.获取当前系统内存布局;
中断15h!
但是,在使用15h之前,我们需要了解它的原理。
中断调用之后,结果将存在下列寄存器中:
根据书上的提示,我们发现我们需要的是ARDS结构。
其中,type如下所示:
到此,我们发现可以从ARDS中提取我们内存是否可用信息,也能计算出总内存大小。
于是我们申请一个缓冲区,存储我们得到的所有内存信息。
得到了内存信息之后,我们进入保护模式,把信息打印出来:
这里要注意的是,保护模式的寻址和实模式寻址是不同的,所以保护模式下要用上图的符号dwMemSize。
5. 掌握内存地址映射关系的切换;
– 画出流程图
根据CR3的值,决定使用的页目录表和页表,在偏移相同的情况下将映射到不同的物理地址。
自己画的感觉还不如书上的。。。
6. 基础题:依据实验的代码,
– 自定义一个函数,给定一个虚拟地址,能够返回该地址从虚拟地址到物理地址的计算过程,如果该地址不存在,则返回一个错误提示。
思路:1)读取虚拟地址
2)将16进制数转化为2进制数,并以10位(.a)、10位(.b)、12位(.c)分块
3)读取cr3寄存器的值
4)将cr3寄存器的值加上.a * 4的值,作为页目录表地址;
5)将.b的值加上页目录表所指的地址值,作为页表地址;
6)将页表所指的地址加上.c的值,作为寻址的结果,即物理地址。
7)如果其中有寻址出错,则报错。
– 完善分页管理功能,补充alloc_pages, free_pages两个函数功能
选择维护一个栈,当alloc的时候则进栈,当free的时候则出栈;
由于使用栈操作,所以我们需要一个栈顶指针,并且需要记录栈中元素的标志位:
地址 | 标志位
标志位表示是否已被分配,是否在使用。
分页寻址,在这里我们采用的是非常简单的分页形式,即虚拟地址=物理地址
置位。
表指针加一,指向当前栈顶位置。
而对于free函数,则和alloc函数步骤相反,总体原理是相同的。
7. 进阶题(选做)
– 设计一个内存管理器,选择其一实现:首次适应算法、最佳适应算法、伙伴算法,要求实现内存的分配与回收。(提示,均按照页为最小单位进行分配、对于空闲空间管理可采用位图法或者双向链表法管理)