课程名称 实验项目名称 学号 操作系统实验 课程编号 0906553 物理存储器与进程逻辑地址空间的管理 年级 2011 计算科学与姓名 专业 技术 学生所在学院 计算科学与技术 指导教师 实验室名称地点 21B276
哈尔滨工程大学 计算机科学与技术学院
第四讲 物理存储器与进程逻辑地址空间的管理
一、实验概述
1. 实验名称
物理存储器与进程逻辑地址空间的管理 2. 实验目的
通过查看物理存储器的使用情况,并练习分配和回收物理内存,从而掌握物理存储器的管理方法。
通过查看进程逻辑地址空间的使用情况,并练习分配和回收虚拟内存,从而掌握进程逻辑地址空间的管理方法。
3. 实验类型
验证+设计
4. 实验内容
1 准备实验
2 阅读控制台命令“pm”相关的源代码,并查看其执行的结果 3 分配物理页和释放物理页
5 在系统进程中分配虚拟页和释放虚拟页
4 阅读控制台命令“vm”相关的源代码,并查看其执行的结果 6 在应用程序进程中分配虚拟页和释放虚拟页
二、实验环境
EOS操作系统和OS Lab集成实验环境。
三、实验过程
3.1 阅读控制台命令“pm”相关的源代码,并查看其执行的结果 阅读ke/sysproc.c文件中第1059行的ConsoleCmdPhysicalMemory函数,学习“pm”命令是如何统计并输出物理存储器信息的。在阅读的过程中需要注意下面几点:
在统计输出物理存储器信息之前要关闭中断,之后要打开中断,这样可以防止在命令执行的过程中有其它线程分配或者释放物理页。
全局变量MiTotalPageFrameCount保存了物理页的总数。每个物理页的大小是4KB,由宏PAGE_SIZE定义。
全局变量MiZeroedPageCount和MiFreePageCount分别保存了零页和空闲页的数量。 计算已用物理页数量的方法是:物理页总数减去零页数量,再减去空闲页数量。
按照下面的步骤执行控制台命令“pm”,查看物理存储器的信息: 1. 按F7生成在本实验3.1中创建的EOS Kernel项目。
1
2. 按F5启动调试。
3. 待EOS启动完毕,在EOS控制台中输入命令“pm”后按回车。 结果如下图1:
3.2 分配物理页和释放物理页
接下来,在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”后按回车。 结果如下截图2:
2
3.3阅读控制台命令“vm”相关的源代码,并查看其执行的结果
阅读ke/sysproc.c文件中第959行的ConsoleCmdVM函数,学习“vm”命令是如何统计并输出进程的虚拟地址描述符信息的。在阅读的过程中需要注意下面几点:
与“pm”命令输出的是整个系统的物理存储器的使用情况不同,“vm”命令输出的是某个进程的虚拟地址描述符信息,所以“vm”命令使用了一个参数——进程ID,用来指定一个进程。这个进程既可以是系统进程,也可以是用户进程。
在统计输出指定进程的虚拟地址描述符信息之前要关闭中断,之后要打开中断,这样可以防止在命令执行的过程中有其它线程分配或者释放虚拟页。
EOS操作系统的进程有4G的虚拟地址空间,但并不是所有的虚拟地址空间都使用虚拟地址描述符来管理,有一些地址空间是静态的,还有一些地址空间由其他的动态方式来管理(例如系统内存池)。 进程4G虚拟地址空间中由虚拟地址描述符所管理空间的低地址和高地址是固定的,在这段地址空间中,如果有虚拟页被占用,就会使用虚拟地址描述符来标识,并放入链表中管理。
结果如下截图3:
系统进程中由虚拟地址描述符所管理的虚拟页只会分配给进程的句柄表(句柄表占用一个虚拟页)和线程的堆栈(堆栈占用两个虚拟页)。结合之前“pt”命令输出的进程和线程信息可知,当前系统中只有1个系统进程以及10个系统线程,所以在图1中,1号描述符所包含的一个虚拟页即为系统进程的句柄表,而2到11号这10个描述符所分别包含的两个虚拟页即为10个系统线程的堆栈。 截图4:
3
截图5:
1.在实验指导的P160-4.和5.按F10单步调试MmAllocateVirtualMemory函数的执行过程,要求给出监视窗口BaseAddress和RegionSize个变量前后变化截图界面。(即共2张截图(每张截图2个变量)进入MmAllocateVirtualMemory函数前和函数
4
执行完后)
MmAllocateVirtualMemory函数,监视窗口BaseAddress和RegionSize个变量前后变化截图:
2. 在实验指导的P160-1.和2. 按F10单步调试MmFreeVirtualMemory函数的执行过程,要求给出监视窗口BaseAddress和RegionSize个变量前后变化截图界面。 (即共2张截图(每张截图2个变量)进入MmFreeVirtualMemory函数前和函数执行完后)
MmFreeVirtualMemory函数,监视窗口BaseAddress和RegionSize个变量前后变化截图:
3.按照《实验指导》的P160-3.6 在应用程序进程中分配虚拟页和释放虚拟页,编写代码。要求至少给出源代码及其解释。
1. 代码修改完毕后,按F7生成EOS应用程序项目。
2. 按F5启动调试,应用程序自动执行后输出的结果可以参照图6所示。 截图6:
3. 在应用程序分配虚拟页后,利用10秒后才释放虚拟页的间隙,可以在控制台2中执行命令“vm 31”,查看此时应用程序进程的虚拟地址描述符信息;在应用程序释放虚拟页后,可以在控制台2中再次执行命令“vm 31”,查看此时应用程序进程的虚拟地址描述符信息。 截图7:
5
源代码:
#include \"EOSApp.h\" //
// main 函数参数的意义:
// argc - argv 数组的长度,大小至少为 1,argc - 1 为命令行参数的数量。
// argv - 字符串指针数组,数组长度为命令行参数个数 + 1。其中 argv[0] 固定指向当前 // 进程所执行的可执行文件的路径字符串,argv[1] 及其后面的指针指向各个命令行 // 参数。
// 例如通过命令行内容 \"a:\\hello.exe -a -b\" 启动进程后,hello.exe 的 main 函 // 数的参数 argc 的值为 3,argv[0] 指向字符串 \"a:\\hello.exe\",argv[1] 指向 // 参数字符串 \"-a\",argv[2] 指向参数字符串 \"-b\"。 //
int main(int argc, char* argv[]) {
#ifdef _DEBUG
__asm(\"int $3\\n nop\"); //
// 启动调试 EOS 应用程序前要特别注意下面的问题: //
// 1、如果要在调试应用程序时能够调试进入内核并显示对应的源码, // 必须使用 EOS 核心项目编译生成完全版本的 SDK 文件夹,然 // 后使用此文件夹覆盖应用程序项目中的 SDK 文件夹,并且 EOS // 核心项目在磁盘上的位置不能改变。 //
// 2、在启动调试应用程序之前必须首先删除/禁用所有的断点,在断 // 点中断 (int 3) 被命中后才能重新添加/启用断点,否则启动 // 调试会失败。 //
#endif
/* TODO: 在此处添加自己的代码 */ INT *d;
6
if(d=VirtualAlloc(0,sizeof(int),MEM_RESERVE|MEM_COMMIT))
{//调用API函数VirtualAlloc,分配一个整型变量所需的空间,并使用一个整型变量的指针指向这个空间。 printf(\"Allocated %d bytes virtual memory of 0x%x\\n\\n\ printf(\"virtual memory original value:0x%x\\n\\n\输出原始整型变量的值 *d=0xFFFFFFFF;//修改整型变量的值为0xFFFFFFFF
printf(\"virtual memory new value:0x%x\\n\\n\输出修改后的整型变量的值
printf(\"\\nWait for 10 seconds\\n\"); Sleep(10000);// 调用API函数Sleep,等待10秒钟。系统以毫
秒为单位
if(VirtualFree(d,0,MEM_RELEASE))//// 调用API函数VirtualFree,释放之前分配的整型变量的空间 printf(\"\\nRealease virtual memory success!\\n\"); else { printf(\"realease error\\n\");
return -1; } }
return 0;
printf(\"\\nEndless loop!\"); for(;;){; }//进入死循环,这样应用程序就不会结束 return 0; } else
{ printf(\"error\\n\"); return -1;//若不能成功,打印error,并返回-1。 } printf(\"Hello world!\\n\");
四、实验体会
通过这实验对物理存储器与进程逻辑地址空间的管理更加了解,并掌握物理存储器的管理方法和进程逻辑地址空间的管理方法。 不过每次试验不可能一帆风顺的,而且是很容易出错,每次出错就让人很烦恼,很可能漏掉了什么步骤,这意味著要重新开始,所以这是很难受的事情。因此我觉得做实验不要盲目的去追求快,而是一边做一边思考其中的意义,争取一次性做好。遇到问题有时候向网络需求帮助也是一个不错的选择,但是不能一味的抄袭复制,那样就失去做实验的目的,而应该借鉴别人东西的同时要思考为什么会这样子用,这样子做,我为什么错了。搞清楚问题的所在,才能算是真正的解决了问题。
7
因篇幅问题不能全部显示,请点此查看更多更全内容