05_实验五_物理存储器与进程逻辑地址空间管理
物理存储器与进程逻辑地址空间管理
实验目的
-
通过查看物理存储器的使用情况,并练习分配和回收物理内存,从而掌握物理存储器的管理方法。
-
通过查看进程逻辑地址空间的使用情况,并练习分配和回收虚拟内存,从而掌握进程逻辑地址空间的管理方法。
预备知识
物理存储器的管理方式
EOS使用分页式存储管理方式,由页框号数据库PFN Database进行管理。其实质是一个数组,长度与页数量一致。定义如下
typedef struct _MMPFN
{
ULONG Unused : 9; // 未使用
ULONG PageState : 3; // 页状态
ULONG Next : 20; // 下一个框号
}MMPFN, *PMMPFN;
物理页目前有三种状态,定义如下
typedef enum _PAGE_STATE {
ZEROED_PAGE, // 0 零页,空闲,已0初始化
FREE_PAGE, // 1 自由页,空闲,未0初始化
BUSY_PAGE, // 2 占用页,被占用
} PAGE_STATE;
ZEROED_PAGE
和FREE_PAGE
的数据库构成链表,分配时只需要移除首部即可
MiAllocateAnyPages
和MiAllocateZeroedPages
两个函数分别负责优先从空闲分配空间和优先从零页分配空间。
同时还可以为EOS增加零页线程进行零初始化
实验内容
任务(一):练习分配和释放物理页以及在系统进程中分配和释放虚拟页
阅读控制台命令“pm”相关的源代码,并查看其执行的结果
分配物理页和释放物理页
阅读控制台命令“vm”相关的源代码,并查看其执行结果
任务(二):在应用程序进程中分配和释放虚拟页
本练习要求读者首先创建一个 EOS 应用程序,然后编写代码完成下列功能:
调用 API 函数 VirtualAlloc,分配 一个整型变量所需的空间,并使用一个整型变量的指针指向这个空间。
修改整型变量的值为 0xFFFFFFFF。在修改前输出整型变量的值,在修改后再输出整型变量的值。
调用 API 函数 Sleep,等待 10 秒钟。
调用 API 函数 VirtualFree,释放之前分配的整型变量的空间。
进入死循环,这样应用程序就不会结束。
实验步骤
本实验仔细阅读代码过程未来得及及时记录,详见实验报告
EOSApp代码如下:
#include "EOSApp.h"
int main(int argc, char* argv[])
{
// 1. 调用API函数`VirtualAlloc`,分配一个整型变量所需的空间,并使用一个整型变量的指针指向这个空间。
PINT space = VirtualAlloc(0, sizeof(INT), MEM_RESERVE|MEM_COMMIT);
// 2. 修改整型变量的值为`0xFFFFFFFF`。在修改前输出整型变量的值,在修改后再输出整型变量的值。
printf("Before: 0x%X\n", *space);
*space = 0xFFFFFFFF;
printf("After: 0x%X", *space);
// 3. 调用API函数`Sleep`,等待10秒钟。
Sleep(1000);
// 4. 调用API函数`VirtualFree`,释放之前分配的整型变量的空间。
VirtualFree(space, 0, MEM_RELEASE);
// 5. 进入死循环,这样应用程序就不会结束。
while(1);
return 0;
}
思考与练习:
1、如果分配了物理页后,没有回收,会对EOS操作系统造成什么样的影响?目前EOS 操作系统内核函数 MiAllocateAnyPages能处理所有物理页被分配完毕的情况吗?例如在没有可分配的物理页的情况下调用该内核函数,是否会返回失败?
操作系统将不能再使用未回收的物理页,如果分配的物理页没有回收,会造成自由页链表和零链表不断减少甚至为空,此时EOS可能会没有可用的物理页。
目前EOS操作系统内核函数 MiAllocateAnyPages不能处理物理页分配完毕的这种情况,调用该函数会返回失败。
2、尝试从性能的角度分析内核函数MiAllocateAnyPages和MiAllocateZeroedPages。尝试从安全性的角度分析分配零页的必要性。
性能上:调用MiAllocateAnyPages在某些情况下比调用MiAllocateZeroedPages更快速。
安全性上:分配零页更安全。如果一个物理页被操作系统存储过重要的信息后被释放,如果没有清零就分配给用户程序,则用户程序就可能从这个页中获取其重要信息。
3、尝试结合虚拟页的分配和释放说明产生空隙的原因。
产生空隙是由于虚拟页被释放造成的。在启动时会有一个初始化线程,初始化结束后就退出了,线程堆栈所分配的虚拟页也就被释放了。
4、调用MmAllocateVirtualMemory函数分配虚拟页时只使用了MEM_RESERVE标志,没有使用MEM_COMMIT标志,尝试说明这两个标志的区别。
使用MEM_RESERVE标志分配虚拟页时,没有为其映射实际的物理页。用MEM_COMMIT分配虚拟页时,会为其映射实际的物理页。
本文来自彬彬zhidao的博客,作者:彬彬zhidao,转载请注明原文链接:https://www.cnblogs.com/binbinzhidao/p/17884251.html