操作系统实验七 - 图文

更新时间:2023-12-26 02:58:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

操作系统 实 验 报 告

课程名称 实验项目名称 学号 姓名 学生所在学院 实验室名称地点

操作系统实验 课程编号 0906553 物理存储器与进程逻辑地址空间的管理 年级 专业 指导教师 哈尔滨工程大学 计算机科学与技术学院

实验七 物理存储器与进程逻辑地址空间的管理

一、实验概述

1. 实验名称

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

2. 实验目的

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

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

3. 实验类型 验证、设计 4. 实验内容

4.1 准备实验

4.2 阅读控制台命令“pm”相关的源代码,并查看其执行的结果 4.3 分配物理页和释放物理页

4.4阅读控制台命令“vm”相关的源代码,并查看其执行的结果 4.5 在系统进程中分配虚拟页和释放虚拟页 4.6 在应用程序进程中分配虚拟页和释放虚拟页 4.6.1 要求 4.6.2 测试方法

二、实验环境

OS Lab实验环境,EOS操作系统

三、实验过程

1. 设计思路和流程图

MiAllocateAnyPages函数的流程图

MiFreePages函数的流程图

2. 需要解决的问题及解答

(1)在本实验3.3 中,如果分配了物理页后,没有回收,会对 EOS 操作系统造成什么样的影响?目前EOS操作系统内核函数MiAllocateAnyPages 能处理所有物理页被分配完毕的情况吗?例如在没有可分配的物理页的情况下调用该内核函数,是否会返回失败?如果内核函数MiAllocateAnyPages 还不能处理这种极端情况,尝试修改代码解决这个问题。 答:如果分配了物理页后,没有回收,将会使可分配自由页和零页越来越少,最终导致内存溢出,系统无法运行。目前 EOS操作系统内核函数 MiAllocateAnyPages 不能处理所有物理页被分配完毕的情况,在没有可分配的物理页的情况下,不会分配物理页,但仍然会返回成功,添加以下代码即可:Else{ return STATUS_MEMORY_NOT_ALLOCATED;} (2)在本实验 3.3 中,在分配物理页时是调用的内核函数 MiAllocateAnyPages,该函数会优先分配空闲页,尝试修改代码,调用内核函数MiAllocateZeroedPages优先分配零页,并调试分配零页的情况。尝试从性能的角度分析内核函数MiAllocateAnyPages 和MiAllocateZeroedPages。尝试从安全性的角度分析分配零页的必要性。

答:将MiAllocateAnyPages(1, PfnArray);修改为MiAllocateZeroedPages(1, PfnArray);即可。系统启动时,所有空闲物理页都是未初始化的,此时零页链表为空,

MiAllocateAnyPages函数可以直接从自由页链表分配,而MiAllocateZeroedPages函数会对从自由页链表中分配的每一页进行零初始化,确保所有分配页都是被零初始化的,再进行分配,因此MiAllocateZeroedPages函数效率较低。但因为MiAllocateZeroedPages函数对自由页进行了初始化,减小了出错的可能性,从而安全性较高。

(3)按F10单步调试MiAllocateAnyPages函数的执行过程,尝试回答下面的问题: ①本次分配的物理页的数量是多少?分配的物理页的页框号是多少? ②物理页是从空闲页链表中分配的?还是从零页链表中分配的?

③哪一行语句减少了空闲页的数量?哪一行语句将刚刚分配的物理页由空闲状态修改为忙状态?

④绘制MiAllocateAnyPages函数的流程图。

答:①本次分配的物理页的数量是1,分配的物理页的页框号是0x409;②物理页是从空闲页链表中分配的;③第226行MiFreePageListHead = MiGetPfnDatabaseEntry(Pfn)->Next;和第227行MiFreePageCount--;减少了空闲页的数量,第229行将刚刚分配的物理页由空闲状态修改为忙状态;④见实验过程开头流程图部分。

(4) 按 F10单步调试MiFreePages函数的执行过程,尝试回答下面的问题: ① 本次释放的物理页的数量是多少?释放的物理页的页框号是多少?释放的物理页是之前分配的物理页吗?

② 释放的物理页是被放入了空闲页链表中?还是零页链表中? ③ 绘制MiFreePages函数的流程图。

答:① 本次释放的物理页的数量是1,释放的物理页的页框号0x409,释放的物理页是之前分配的物理页;② 释放的物理页被放入了空闲页链表中;③ 见实验过程开头流程图部分。

(5)按F10单步调试MmAllocateVirtualMemory函数的执行过程,尝试回答下面的问题: ①分配的虚拟页的起始地址是多少?分配的虚拟页的数量是多少?它们和参数BaseAddress和RegionSize初始化的值有什么样的关系?

② 配虚拟页的同时有为虚拟页映射实际的物理页吗?这是由哪个参数决定的?

③ 分配的虚拟页是在系统地址空间(高2G)还是在用户地址空间(低2G)?这是由哪个参数决定的?

④参考MiReserveAddressRegion函数的定义和注释,说明该函数的功能。

答:①分配的虚拟页的起始地址是0xa0003000,分配的虚拟页的数量是1,BaseAddress和

RegionSize初始化的值是期望保留或者提交的地址区域的起始地址和大小;②分配虚拟页的同时有为虚拟页映射实际的物理页,这是由第三个参数AllocationType决定的;③ 分配的虚拟页是在系统地址空间(高2G),这是由第四个参数SystemVirtual 决定的;④MiReserveAddressRegion函数的功能是保留一段虚拟地址区域。

(6)按F10单步调试MmFreeVirtualMemory函数的执行过程,尝试回答下面的问题:

① 本次释放的虚拟地址是多少?释放的虚拟页是之前分配的虚拟页吗? ②参考MiFindReservedAddressRegion函数、MiFreeAddressRegion函数和MiDecommitPages函数的定义和注释,说明这些函数的功能。 答:①本次释放的虚拟地址是0xa0003000,是之前分配的虚拟页;

② MiFindReservedAddressRegion函数用于查找已保留地址区域,如果目标区域非已保留区域则返回失败,MiFreeAddressRegion函数用于释放已保留地址区域和MiDecommitPages

函数用于释放映射在连续虚拟页框上的物理页框。

3. 源程序并附上注释 #include \// main 函数参数的意义:

// argc - argv 数组的长度,大小至少为 1,argc - 1 为命令行参数的数量。 // argv - 字符串指针数组,数组长度为命令行参数个数 + 1。其中 argv[0] 固定指向当前

// 进程所执行的可执行文件的路径字符串,argv[1] 及其后面的指针指向各个命令行

// 参数。

// 例如通过命令行内容 \启动进程后,hello.exe 的 main 函

// 数的参数 argc 的值为 3,argv[0] 指向字符串 \,argv[1] 指向

// 参数字符串 \,argv[2] 指向参数字符串 \。

//

int main(int argc, char* argv[]) { //

// 启动调试 EOS 应用程序前要特别注意下面的问题: //

// 1、如果要在调试应用程序时能够调试进入内核并显示对应的源码, // 必须使用 EOS 核心项目编译生成完全版本的 SDK 文件夹,然 // 后使用此文件夹覆盖应用程序项目中的 SDK 文件夹,并且 EOS // 核心项目在磁盘上的位置不能改变。 //

// 2、在启动调试应用程序之前必须首先删除/禁用所有的断点,在断 // 点中断 (int 3) 被命中后才能重新添加/启用断点,否则启动 // 调试会失败。 //

#ifdef _DEBUG

//__asm(\#endif

/* TODO: 在此处添加自己的代码 */ INT *p;

if(p=VirtualAlloc(0,sizeof(int),MEM_RESERVE|MEM_COMMIT))//申请空间 {

//如果分配成功进行以下操作 printf(\

printf(\申请空间大小 printf(\赋值之前 *p=0xFFFFFFFF;

printf(\

printf(\等10s

Sleep(10000);

if(VirtualFree(p,0,MEM_RELEASE))//释放

//RegionSize -- 作输入时,如果参数FreeType的值为

MEM_RELEASE则必须为0,否则输入

域大小。

{ }

printf(\

//期望MEM_DECOMMIT的内存大小;作输出时,输出实际释放的区

{;} }

else { }

printf(\for(;;)//死循环

printf(\

else//如果分配失败 { } return 0; }

4. 程序运行时的初值和运行结果

4.1 准备实验

按照下面的步骤准备实验:

1. 启动OS Lab。

2. 新建一个EOS Kernel项目。

printf(\return -1;

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

阅读ke/sysproc.c文件中第1059行的ConsoleCmdPhysicalMemory函数,学习“pm”命令是如何统计并输出物理存储器信息的。在阅读的过程中需要注意下面几点: 量。

??在统计输出物理存储器信息之前要关闭中断,之后要打开中断,这样可以防止??全局变量MiTotalPageFrameCount保存了物理页的总数。每个物理页的大小是??全局变量MiZeroedPageCount和MiFreePageCount分别保存了零页和空闲页的数

在命令执行的过程中有其它线程分配或者释放物理页。 4KB,由宏PAGE_SIZE定义。

??计算已用物理页数量的方法是:物理页总数减去零页数量,再减去空闲页数量。

按照下面的步骤执行控制台命令“pm”,查看物理存储器的信息:

1. 按F7生成在本实验3.1中创建的EOS Kernel项目。 2. 按F5启动调试。

3. 待EOS启动完毕,在EOS控制台中输入命令“pm”后按回车。

观察命令执行的结果,可以了解当前物理存储器的使用情况。 4.3 分配物理页和释放物理页

接下来,在pm命令函数中添加分配物理页和释放物理页的代码,单步调试管理物理页的方法。按照下面的步骤修改pm命令的源代码:

1. 使用OS Lab打开本实验文件夹中的pm.c文件(将文件拖动到OS Lab窗口中释放即

可打开)。此文件中有一个修改后的ConsoleCmdPhysicalMemory函数,主要是在原有代码的后面增加了分配物理页和释放物理页的代码。

2. 使用pm.c文件中ConsoleCmdPhysicalMemory函数的函数体替换ke/sysproc.c文件

中ConsoleCmdPhysicalMemory函数的函数体。

3. 按F7生成修改后的EOS Kernel项目。 4. 按F5启动调试。

5. 待EOS启动完毕,在EOS控制台中输入命令“pm”后按回车。

观察命令执行的结果,尝试说明分配物理页或者释放物理页后物理存储器的变化情况。 按照下面的步骤调试分配物理页和释放物理页的过程:

1. 结束之前的调试。

2. 在ke/sysproc.c文件的ConsoleCmdPhysicalMemory函数中,在调用

MiAllocateAnyPages函数的代码行(第1103行)添加一个断点,在调用MiFreePages函数的代码行(第1115行)添加一个断点。

3. 按F5启动调试。

4. 待EOS启动完毕,在EOS控制台中输入命令“pm”后按回车。

5. pm命令开始执行后,会在调用MiAllocateAnyPages函数的代码行处中断,按F11

调试进入MiAllocateAnyPages函数。

6. 按F10单步调试MiAllocateAnyPages函数的执行过程,尝试回答下面的问题: (1) 本次分配的物理页的数量是多少?分配的物理页的页框号是多少? (2) 物理页是从空闲页链表中分配的?还是从零页链表中分配的?

(3) 哪一行语句减少了空闲页的数量?哪一行语句将刚刚分配的物理页由空闲状态(4) 绘制MiAllocateAnyPages函数的流程图。

修改为忙状态?

继续调试释放物理页的过程:

1. 按F5继续执行,会在调用MiFreePages函数的代码行处中断,按F11调试进入2. 按F10单步调试MiFreePages函数的执行过程,尝试回答下面的问题: (1) 本次释放的物理页的数量是多少?释放的物理页的页框号是多少?释放的物理(2) 释放的物理页是被放入了空闲页链表中?还是零页链表中? (3) 绘制MiFreePages函数的流程图。

MiFreePages函数。

页是之前分配的物理页吗?

结束此次调试。继续修改pm命令的源代码,尝试在调用MiAllocateAnyPages函数时分配多个物理页,然后在调用MiFreePages函数时将分配的多个物理页释放,并练习调试这两个函数在分配多个物理页和释放多个物理页时执行的过程。

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

阅读ke/sysproc.c文件中第959行的ConsoleCmdVM函数,学习“vm”命令是如何统计并输出进程的虚拟地址描述符信息的。在阅读的过程中需要注意下面几点:

??与“pm”命令输出的是整个系统的物理存储器的使用情况不同,“pm”命令

输出的是某个进程的虚拟地址描述符信息,所以“pm”命令使用了一个参数??进程ID,用来指定一个进程。这个进程既可以是系统进程,也可以是用户进程。

??在统计输出指定进程的虚拟地址描述符信息之前要关闭中断,之后要打开中断,??EOS操作系统的进程有4G的虚拟地址空间,但并不是所有的虚拟地址空间都使

这样可以防止在命令执行的过程中有其它线程分配或者释放虚拟页。

用虚拟地址描述符来管理,有一些地址空间是静态的,还有一些地址空间由其他的动态方式来管理(例如系统内存池)。

??进程4G虚拟地址空间中由虚拟地址描述符所管理空间的低地址和高地址是固定

的,在这段地址空间中,如果有虚拟页被占用,就会使用虚拟地址描述符来标识,并放入链表中管理。

按照下面的步骤执行控制台命令“pm”,查看系统进程的虚拟地址描述符信息:

1. 按F5启动调试。

2. 待EOS启动完毕,在EOS控制台中输入命令“pt”后按回车。“pt”命令可以输

出当前系统中的进程列表,其中系统进程的ID为1。

3. 在EOS控制台中输入命令“vm 1”后按回车。

观察命令执行的结果,如图15-3所示,可以了解系统进程的虚拟地址描述符信息。 系统进程中由虚拟地址描述符所管理的虚拟页只会分配给进程的句柄表(句柄表占用一个虚拟页)和线程的堆栈(堆栈占用两个虚拟页)。结合之前“pt”命令输出的进程和线程信息可知,当前系统中只有1个系统进程以及10个系统线程,所以在图15-3中,1号描述符所包含的一个虚拟页即为系统进程的句柄表,而2到11号这10个描述符所分别包含的两个虚拟页即为10个系统线程的堆栈。

可以按照下面的步骤执行控制台命令“vm”,查看当创建了一个应用程序进程后,系统进程和应用程序进程中虚拟地址描述符的信息:

1. 在“项目管理器”窗口中双击Floppy.img文件,使用FloppyImageEditor工具打开

此软盘镜像。

2. 将本实验文件夹中的LoopApp.exe文件添加到软盘镜像的根目录中(将

LoopApp.exe文件拖动到FloppyImageEditor窗口中释放即可)。EOS应用程序LoopApp.exe的源代码可以参考本实验文件夹中的LoopApp.c文件。

3. 点击FloppyImageEditor工具栏上的保存按钮,关闭该工具。 4. 按F5启动调试。

5. 待EOS启动完毕,在EOS控制台中输入命令“A:\\LoopApp.exe”后按回车。此时就

使用EOS应用程序文件LoopApp.exe创建了一个应用程序进程,由于此进程执行了一个死循环,所以此进程不会结束执行,除非关闭虚拟机。

6. 此时按Ctrl+F2切换到“Console-2”,然后输入命令“pt”后按回车。输出的信息

如图15-4所示。其中ID为31的进程就是应用程序进程,ID为33的线程就是应用程序进程的主线程。

7. 输入命令“vm 1”后按回车,可以查看系统进程中虚拟地址描述符的信息。输出的信息如图15-5所示。与图15-3比较可知,3号描述符所包含的一个虚拟页即为应用程序进程的句柄表,13号描述符所包含的两个虚拟页即为应用程序进程主线程的堆

栈。

8. 输入命令“vm 31”后按回车,可以查看应用程序进程中虚拟地址描述符的信息。 在进程的4G逻辑地址空间中,应用程序进程可以自行管理低2G的用户空间。从图15-6中的信息可以得知,低2G的用户空间又被分为了三部分:

??0x00000000-0x0000FFFF 由16个虚拟页构成的64KB静态空间,用于捕捉对空指??0x00010000-0x7FFEFFFF 由虚拟地址描述符管理的动态空间,用于存储应用程

针的非法访问。

序进程的代码和数据。图15-6显示应用程序进程的代码和数据占用了此空间中的5个虚拟页,并且是用从应用程序的基址0x00400000起始的。

??0x7FFF0000-0x7FFFFFFF由16个虚拟页构成的64KB静态空间,用于捕捉对空指

针的非法访问。

为了加深对进程逻辑地址空间的理解,可以在控制台1至控制台7中都执行命令

“A:\\LoopApp.exe”,从而让应用程序创建7个进程,然后在控制台8中执行“pt”、“vm”等命令,查看系统进程和应用程序进程的虚拟地址描述符。

4.5 在系统进程中分配虚拟页和释放虚拟页

接下来,在vm命令函数中添加分配虚拟页和释放虚拟页的代码,单步调试管理虚拟页的方法。首先,按照下面的步骤修改vm命令的源代码:

1. 使用OS Lab打开本实验文件夹中的vm.c文件(将文件拖动到OS Lab窗口中释放即

可打开)。此文件中有一个修改后的ConsoleCmdVM函数,主要是在原有代码的后面增加了分配虚拟页和释放物理页的代码。

2. 使用vm.c文件中ConsoleCmdVM函数的函数体替换ke/sysproc.c文件中

ConsoleCmdVM函数的函数体。

3. 按F7生成修改后的EOS Kernel项目。 4. 按F5启动调试。

5. 待EOS启动完毕,在EOS控制台中输入命令“vm 1”后按回车。

命令执行的结果会同时转储在“输出”窗口中。尝试说明分配虚拟页或者释放虚拟页后虚拟地址描述符以及物理存储器的变化情况。

按照下面的步骤调试分配虚拟页和释放虚拟页的过程:

1. 在ke/sysproc.c文件的ConsoleCmdVM函数中,在调用MmAllocateVirtualMemory

函数的代码行(第1082行)添加一个断点,在调用MmFreeVirtualMemory函数的代码行(第1147行)添加一个断点。

2. 按F5启动调试。

3. 待EOS启动完毕,在EOS控制台中输入命令“vm 1”后按回车。

4. vm命令开始执行后,会在调用MmAllocateVirtualMemory函数的代码行处中断。

此时要注意参数BaseAddress和RegionSize初始化的值。按F11调试进入MmAllocateVirtualMemory函数。

题:

5. 按F10单步调试MmAllocateVirtualMemory函数的执行过程,尝试回答下面的问(1) 分配的虚拟页的起始地址是多少?分配的虚拟页的数量是多少?它们和参数(2) 分配虚拟页的同时有为虚拟页映射实际的物理页吗?这是由哪个参数决定的? (3) 分配的虚拟页是在系统地址空间(高2G)还是在用户地址空间(低2G)?这是(4) 参考MiReserveAddressRegion函数的定义和注释,说明该函数的功能。

BaseAddress和RegionSize初始化的值有什么样的关系?

由哪个参数决定的? 继续调试释放虚拟页的过程:

1. 按F5继续执行,会在调用MmFreeVirtualMemory函数的代码行处中断。此时要注2. 按F10单步调试MmFreeVirtualMemory函数的执行过程,尝试回答下面的问题: (1) 本次释放的虚拟地址是多少?释放的虚拟页是之前分配的虚拟页吗? (2) 参考MiFindReservedAddressRegion函数、MiFreeAddressRegion函数和

意参数BaseAddress和RegionSize初始化的值。按F11调试进入MmFreeVirtualMemory函数。

MiDecommitPages函数的定义和注释,说明这些函数的功能。

结束此次调试后,继续按照下列要求修改ConsoleCmdVM函数的源代码,加深对虚拟页分配和释放过程的理解:

1. 尝试在调用MmAllocateVirtualMemory函数时将RegionSize参数的值设置为

PAGE_SIZE+1或者PAGE_SIZE*2+1。观察“输出”窗口中转储的信息,并说明申请虚拟内存的大小与实际分配的大小之间的关系,以及分配的虚拟内存大小会对分配的虚拟地址产生什么样的影响。将“输出”窗口中转储的信息保存在文本文件中。

2. 尝试在调用MmAllocateVirtualMemory函数时将BaseAddress参数的值设置为已

经被占用的虚拟内存,例如0xA0000000,观察“输出”窗口中转储的信息。将“输出”窗口中转储的信息保存在文本文件中。

3. 尝试在调用MmAllocateVirtualMemory函数时将RegionSize参数的值设置为

PAGE_SIZE*2,将BaseAddress参数的值设置为0xA0017004,观察“输出”窗口中转储的信息,并说明申请虚拟内存的大小与实际分配的大小之间的关系,以及申请的虚拟地址会对分配的虚拟内存大小产生什么样的影响。将“输出”窗口中转储的信息保存在文本文件中。 4.6 在应用程序进程中分配虚拟页和释放虚拟页 4.6.1 要求

创建一个EOS应用程序,并编写代码完成下列功能:

1. 调用API函数VirtualAlloc,分配一个整型变量所需的空间,并使用一个整型变2. 修改整型变量的值为0xFFFFFFFF。在修改前输出整型变量的值,在修改后再输3. 调用API函数Sleep,等待10秒钟。

4. 调用API函数VirtualFree,释放之前分配的整型变量的空间。 5. 进入死循环,这样应用程序就不会结束。

量的指针指向这个空间。 出整型变量的值。

4.6.2 测试方法

1. 代码修改完毕后,按F7生成EOS应用程序项目。 2. 按F5启动调试。

3. 在应用程序分配虚拟页后,利用10秒后才释放虚拟页的间隙,可以在控制台2中

执行命令“vm 31”,查看此时应用程序进程的虚拟地址描述符信息;在应用程序释放虚拟页后,可以在控制台2中再次执行命令“vm 31”,查看此时应用程序进程的虚拟地址描述符信息。 4.6.3 提示

1. API函数VirtualAlloc定义在api/eosapi.c文件的第48行。此API函数主要调用

了EOS内核函数MmAllocateVirtualMemory。在EOS应用程序中调用函数VirtualAlloc时,除了使用MEM_RESERVE标志外,还必须使用MEM_COMMIT标志。

2. API函数VirtualFree定义在api/eosapi.c文件的第70行。此API函数主要调用了EOS内核函数MmFreeVirtualMemory。在EOS应用程序中调用函数VirtualFree时,要使用MEM_RELEASE标志

3. 可以参考本实验文件中的LoopApp.c文件,在应用程序的最后执行一个死循环。

四、实验体会

通过本次实验,我对调试EOS操作系统对物理存储空间和虚拟存储空间的分配和回收

函数,对操作系统的内存管理机制和实现有了更深一步的认识,并自己设计了在应用程序进程中分配虚拟页和释放虚拟页的程序。本次实验中已经能够较为熟练运用EOS操作系统,遇到的问题相对于前几次实验有明显减少。

本文来源:https://www.bwwdw.com/article/w49x.html

Top