05_实验五_物理存储器与进程逻辑地址空间管理

发布时间 2023-12-07 23:30:34作者: 彬彬zhidao

物理存储器与进程逻辑地址空间管理

实验目的

  • 通过查看物理存储器的使用情况,并练习分配和回收物理内存,从而掌握物理存储器的管理方法。

  • 通过查看进程逻辑地址空间的使用情况,并练习分配和回收虚拟内存,从而掌握进程逻辑地址空间的管理方法。

预备知识

物理存储器的管理方式

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_PAGEFREE_PAGE的数据库构成链表,分配时只需要移除首部即可

MiAllocateAnyPagesMiAllocateZeroedPages两个函数分别负责优先从空闲分配空间和优先从零页分配空间。

同时还可以为EOS增加零页线程进行零初始化

实验内容

任务(一):练习分配和释放物理页以及在系统进程中分配和释放虚拟页

阅读控制台命令“pm”相关的源代码,并查看其执行的结果

分配物理页和释放物理页

阅读控制台命令“vm”相关的源代码,并查看其执行结果

任务(二):在应用程序进程中分配和释放虚拟页

本练习要求读者首先创建一个 EOS 应用程序,然后编写代码完成下列功能:

  1. 调用 API 函数 VirtualAlloc,分配 一个整型变量所需的空间,并使用一个整型变量的指针指向这个空间。

  2. 修改整型变量的值为 0xFFFFFFFF。在修改前输出整型变量的值,在修改后再输出整型变量的值。

  3. 调用 API 函数 Sleep,等待 10 秒钟。

  4. 调用 API 函数 VirtualFree,释放之前分配的整型变量的空间。

  5. 进入死循环,这样应用程序就不会结束。

实验步骤

本实验仔细阅读代码过程未来得及及时记录,详见实验报告

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分配虚拟页时,会为其映射实际的物理页。