操作系统实验.docx
《操作系统实验.docx》由会员分享,可在线阅读,更多相关《操作系统实验.docx(47页珍藏版)》请在冰豆网上搜索。
![操作系统实验.docx](https://file1.bdocx.com/fileroot1/2022-10/29/d83f8152-5575-4501-bd26-dd301cb82250/d83f8152-5575-4501-bd26-dd301cb822501.gif)
操作系统实验
操作系统
实验报告
课程名称
操作系统实验
课程编号
201420110
学号
2015201128
班级
20152011
姓名
赵子翔
专业
软件工程
年级
2015级
指导教师
王红滨
实验室名称地点
21#B427实验室
哈尔滨工程大学
软件学院
实验一:
进程的创建
一、实验概述
1.实验目的
(1)练习使用EOSAPI函数CreateProcess创建一个进程,掌握创建进程的方法,理解进程和程序的区别。
(2)调试跟踪CreateProcess函数的执行过程,了解进程的创建过程,理解进程是资源分配的单位。
2.实验内容
(1)准备实验
(2)使用控制台命令创建EOS应用程序的进程
(3)练习练习通过编程的方式让应用程序创建另一个应用程序的进程
(4)调试CreateProcess函数
(5)调试PsCreateProcess函数
(6)练习通过编程的方式创建应用程序的多个进程
2、实验环境
实验环境:
OSLab集成环境
操作系统:
EOS操作系统
三、实验过程
1.设计思路和流程图
2.算法实现
略
3.需要解决的问题及解答
略
4.主要数据结构、实现代码及其说明
略
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"。
intmain(intargc,char*argv[])
{
//启动调试EOS应用程序前要特别注意下面的问题:
//1、如果要在调试应用程序时能够调试进入内核并显示对应的源码,
//必须使用EOS核心项目编译生成完全版本的SDK文件夹,然
//后使用此文件夹覆盖应用程序项目中的SDK文件夹,并且EOS
//核心项目在磁盘上的位置不能改变。
//2、在启动调试应用程序之前必须首先删除/禁用所有的断点,在断
//点中断(int3)被命中后才能重新添加/启用断点,否则启动
//调试会失败。
STARTUPINFOStartupInfo;
PROCESS_INFORMATIONProcInfo[10];
inti=0;
ULONGulExitCode;
//子进程退出码INTnResult=0;
//main函数返回值。
0表示成功,非0表示失败。
#ifdef_DEBUG
__asm("int$3\nnop");
#endif
#endif//_DEBUG
printf("Createtwoprocessesandwaitfortheprocessesexit...\n\n");
//使子进程和父进程使用相同的标准句柄。
StartupInfo.StdInput=GetStdHandle(STD_INPUT_HANDLE);
StartupInfo.StdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
StartupInfo.StdError=GetStdHandle(STD_ERROR_HANDLE);
//为一个应用程序同时创建两个子进程。
for(i=0;i<10;i++)if(CreateProcess("A:
\\Hello.exe",NULL,0,&StartupInfo,&ProcInfo[i]))
{
//创建子进程成功,等待子进程运行结束。
WaitForSingleObject(ProcInfo[i].ProcessHandle,INFINITE);
//得到并输出子进程的退出码。
GetExitCodeProcess(ProcInfo[i].ProcessHandle,&ulExitCode);
printf("\nTheprocessoneexitwith%d.\n",ulExitCode);//关闭不再使用的句柄。
CloseHandle(ProcInfo[i].ProcessHandle);
CloseHandle(ProcInfo[i].ThreadHandle);
}
else
{
printf("CreateProcessFailed,Errorcode:
0x%X.\n",GetLastError());
nResult=1;
}
returnnResult;
}
6.程序运行时的初值和运行结果
1)新建一个EOSKernel项目,分别用Debug配置和Release配置生成此项目,从而在该项目文件夹中生成完全版的EOSSDK文件夹,在新建一个EOS应用程序项目,将之前的SDK文件夹进行覆盖;
2)使用FloppyImageEditor工具打开Floppy.img文件;
3)将本实验文件夹中的Hello.exe文件拖动到FloppyImageEditor工具窗口的文件列表中释放,Hello.exe文件即被添加到软盘镜像文件中。
Hello.exe一个EOS应用程序,其源代码可以参见本实验文件夹中的Hello.c源文件;
4)生成项目,并启动调试,激活虚拟机窗口,待该应用程序执行完毕后,在EOS控制台中输入命令“A:
\Hello.exe”后回车,结束调试;
5)使用NewProc.c文件中的源代码替换之前创建的EOS应用程序项目中的EOSApp.c文件内的源代码;
6)生成修改后的项目,启动调试,激活虚拟窗口查看应用程序内容,可看到父进程(EOSApp.exe),首先开始执行并输出内容,父进程创建了子进程(Hello.exe)后,子进程开始执行并输出内容,待子进程结束后父进程再继续执行,结束调试;
7)启动EOS应用程序,选择调试异常,中断调试,在main函数中添加断点,继续调试,按F11(逐语句)调试进入CreateProcess函数,此时已经开始进入EOS内核进行调试;
具体进程描述如下图。
从图中可以看出,当EOS应用程序eosapp.exe存储在软盘上的时候,它是静态的,只包含应用程序的指令和数据,而创建进程后,进程不但包含应用程序的指令和数据,也会包含操作系统内核(kernel.dll)的指令和数据,同时该图也说明了一个进程可以包含多个程序,该进程包含了eosapp.exe和kernel.dll两个程序;
8)由于此时在内核的CreateProcess函数内中断执行,所以在“调试”菜单的“窗口”中选择“反汇编”,会在“反汇编”窗口中显示CreateProcess函数的指令对应的反汇编代码。
“反汇编”窗口的左侧显示的是指令所在的虚拟地址。
可以看到所有指令的虚拟地址都大于0x80000000,说明内核(kernel.dll)处于高2G的虚拟地址空间中;
9)在“调用堆栈”窗口中双击main函数项,设置main函数的调用堆栈帧为活动的。
在“反汇编”窗口中查看main函数的指令所在的虚拟地址都是小于0x80000000,说明应用程序(eosapp.exe)处于低2G的虚拟地址空间中;
10)在“调用堆栈”窗口中双击CreateProcess函数项,重新设置CreateProcess函数的调用堆栈帧为活动的。
关闭“反汇编”窗口。
11)在PsCreateProcess函数中找到调用PspCreateProcessEnvironment函数的代码行,并在此行添加一个断点;
12)继续调试,并逐语句进入PapCreateProcessEnvironment函数(的主要功能是创建进程控制块并初始化其中的部分信息);
13)在调用ObCreateObject函数的代码行添加一个断点,继续调试,将表达式*NewProcess添加到“监视”窗口中;
14)创建进程的地址空间,即4G虚拟地址空间,在代码行NewProcess->Pas=MmCreateProcessAddressSpace();添加一个断点,继续调试,并查看监视窗口,此时进程控制块的成员变量Pas的值已经不再是0。
说明已经初始化了进程的4G虚拟地址空间;
15)逐过程一步步调试PspCreateProcessEnvironment函数中后面的代码,在调试的过程中根据执行的源代码,查看“监视”窗口中*NewProcess表达式的值,观察进程控制块中哪些成员变量是被哪些代码初始化的,哪些成员变量还没有被初始化;
当进入if(NULL==NewsProcess->Pas)
进入NewProcess->PrimaryThread=NULL时
16)当从PapCreateProcessEnvironment函数返回到PsCreateProcess函数后,停止逐过程调试,。
此时“监视”窗口中已经不能再显示表达式*NewProcess的值了,在PsCreateProcess函数中是使用ProcessObject指针指向进程控制块的,所以将表达式*ProcessObject添加到“监视”窗口中就可以继续观察新建进程控制块中的信息;
17)接下来继续使用F10一步步调试PsCreateProcess函数中的代码,同样要注意观察执行后的代码修改了进程控制块中的哪些成员变量。
当调试到PsCreateProcess函数的最后一行代码时,查看进程控制块中的信息,此时所有的成员变量都已经被初始化了(注意观察成员ImageName的值);
进入if(!
EOS_SUCCESS(Status))时
18)继续执行,EOS内核会为刚刚初始化完毕的进程控制块新建一个进程。
激活虚拟机窗口查看新建进程执行的结果,结束此次调试,并删除所有的断点;
19)使用OSLab打开本实验文件夹中的参考源代码文件NewTwoProc.c,仔细阅读此文件中的源代码。
使用NewTwoProc.c文件中的源代码替换EOS应用程序项目中EOSApp.c文件内的源代码,生成后启动调试,查看多个进程并发执行的结果。
多个进程并发时,EOS操作系统中运行的用户进程如下图,验证一个程序(hello.exe)可以同时创建多个进程。
两个进程:
十个进程:
四.实验体会
通过本次试验了解了进程的创建过程,并利用添加断点、监视的方式观察每一步的执行状况,加深了对进程、程序区别的理解。
1)进程是动态的,而程序是静态的;
2)程序是可以长时间存在的,而进程是暂时的,当程序运行时进行创建,是程序的一次执行;
3)进程是计算机分配资源的单位,而程序不是;
4)程序和进程不是一一对应的,一个程序可以有多个进程。
在进行程序调试的时候,了解逐过程和逐语句执行