本文主要是介绍【此后无良辰】 实验3 进程的创建,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
实验目的
了解操作系统中内核程序和应用程序之间的关系;了解操作系统创建进程的过程;掌握在应用程序中创建进程的方法。
实验内容与记录
3.1 复制SDK文件夹的目的是什么?尝试在复制后把本地所生成的EOS内核项目文件夹删除,应用程序执行是否会受到影响?如果发生错误请进行记录并说明原因。如果无错误也请说明原因。
(1)EOS SDK文件夹主要是供EOS应用程序使用。EOS内核提供的API函数及重要数据类型的定义都是通过将相关的头文件复制到SDK文件夹中,然后EOS应用程序再包含SDK文件夹中的这些头文件,使EOS应用程序能够调用API函数,或者使用已经定义好的数据类型来定义变量。同时,SDK文件夹中还保存了Debug和Release版本的EOS的二进制文件,分别供Debug和Release版本的EOS应用程序使用。
(2)应用程序的执行没有影响,该文件已在应用程序中,无需再通过内核调用,可直接调用应用程序中,因而删除内核项目文件夹应用程序执行不会受到影响。
但如果使用F5调试则会出现问题,因为原来的文件
已经被删除了,会出现找不到原项目也就是路径错误。
如下图所示:
原 :3…2 EOSApp和Hello两个程序的区别是什么?请调整顺序让操作系统启动后自动执行Hello,再从命令行执行EOSApp,并截图证明结果。
在执行后,打开floppy添加可执行文件执行会报错
现:3.2 EOSApp和Hello两个程序内容上的区别是什么?磁盘上Autorun.txt文件中写入的是哪一个程序?可以尝试建立一个Hello的应用程序项目自动写入Autorun.txt并让它先执行,将EOSApp的内容编译成一个可执行文件提前放入磁盘中,采用命令行方式执行。并截图证明结果。
注:程序输出的Without nights为自己昵称,证明是自己做的
(1) 当打开的项目名字为EOSApp时,EOSApp就是系统默认自动执行的文件,而Hello程序需要手动输入执行。
(2) 当创建的项目名字是Hello时,Autorun.txt写入的为Hello.exe
如下图所示:
(3)将EOSAPP1的内容编译成一个可执行文件提前放入磁盘中 如下图所示:
Hello先执行了,并且采用命令行输入EOSAPP1.exe可以执行EOSAPP1
注:输出的Without nights为自己昵称,证明是自己做的
3.3 记录并解释CreateProcess函数的参数。
EOS提供了一个用于创建进程的API函数CreateProcess,EOS应用程序可以调用此函数为一个可执行文件(应用程序)创建进程。CreateProcess函数定义如下
①ImageName : 用来指定应用程序的可执行文件的路径和名称。EOS会使用指定的可执行文件创建一个进程。此参数不能为空指针(NULL)。例如,如果要使用软盘根目录下的可执行文件Hello.exe创建进程,可以将此参数设置为”A:\Hello.exe”
②参数CmdLine:应用程序的命令行参数,如果应用程序不需要任何参数,可以设置此参数为空指针(NULL)。
③参数CreateFlags:用于标识标志,以便用于规定如何来创建新进程。
④参数StartupInfo:是一个STARTUPINFO结构体变量的指针。STARTUPINFO结构体在inc/eosdef.h文件中定义如下:
在此结构体中定义了子进程需要用到的标准句柄(标准输入、标准输出、标准错误)。在调用CreateProcess函数之前,应该首先定义一个STARTUPINFO结构体的变量,在正确初始化此变量的各个成员后,才能将此变量的指针做为参数传入CreateProcess函数。例如在调用CreateProcess函数之前,先调用三次GetStdHandle函数(分别使用参数STD_INPUT_HANDLE、STD_OUTPUT_HANDLE和STD_ERROR_HANDLE)来得到父进程拥有的标准句柄,然后将这些句柄分别赋值给STARTUPINFO结构体变量对应的成员,这样,子进程和父进程就可以使用相同的标准句柄了。
⑤参数ProcInfo是一个PPROCESS_INFORMATION结构体变量的指针,用来返回子进程的信息。PPROCESS_INFORMATION结构体在eosdef.h文件中定义如下:
在调用CreateProcess函数之前,应该首先定义一个PPROCESS_INFORMATION结构体的变量,然后将此变量的指针做为参数传入CreateProcess函数,用来返回子进程的信息。子进程创建成功后,父进程可以调用WaitForSingleObject函数,并将PPROCESS_INFORMATION结构体变量的ProcessHandle成员(子进程句柄)做为第一个参数,将INFINITE做为第二个参数。这样WaitForSingleObject函数将一直等待,直到子进程执行完毕后才会返回。待WaitForSingleObject函数返回后,可以调用GetExitCodeProcess函数来得到子进程的退出码,从而判断子进程执行的结果。最后,如果不再使用子进程的句柄,应该调用函数CloseHandle关闭由此参数返回的子进程句柄和子进程的主线程句柄。
3.4 截图记录子进程执行时和允许结束时候的进程列表,并说明截图时调试指向的代码
(1) 子进程执行时:指向54行
(2)允许结束时:指向第59、60、65行,66行时子进程已经结束
3.5 绘制进程创建过程的流程图
3.6 请截图记录多个进程并发执行的结果,并尝试修改程序以体现程序执行的异步性,请给出修改策略以及相应执行截图。
(1) 并发执行:
(2) 异步执行:
修改sleep的时间,以达到异步
注:输出的Without nights为自己昵称,证明是自己做的
但此时还不是真正的异步,所谓异步性是指进程以不可预知的速度向前推进。内存中的每个进程何时执行,何时暂停,以怎样的速度向前推进,每道程序总共需要多少时间才能完成等,都是不可预知的。
需要将hello的程序中sleep的时间变成随机数,才能模拟程序不可预知的速度前进,sleep函数的参数需要用到随机数生成,但是由于软件中的C语言库中不包含随机数生成函数,故未成功实现真实的异步性,若是支持C语言自带的随机数生成函数
hello代码应该为:
3.7 绘制创建线程过程的流程图
实验思考题
1.在源代码文件NewTwoProc.c提供的源代码基础上进行修改,要求使用hello.exe同时创建10个进程。提示:可以使用PROCESS_INFORMATION类型定义一个有10个元素的数组,每一个元素对应一个进程。使用一个循环创建10个子进程,然后再使用一个循环等待10个子进程结束,得到退出码后关闭句柄。 (主要程序部分截图以及程序执行结果截图)
注:输出的Without nights为自己昵称,证明是自己做的
(1)主要程序部分截图:
(2)执行结果截图:
- (选作)在PsCreateProcess函数中调用了PspCreateProcessEnvironment函数后又先后调用了PspLoadProcessImage和PspCreateThread函数,学习这些函数的主要功能。能够交换这些函数被调用的顺序吗?思考其中的原因。
①PspCreateProcessEnvironment:
创建进程控制块,并且为进程创建了地址空间和分配了句柄表。
②PspLoadProcessIma:
将进程的可执行映像加载到了进程的地址空间中。
③PspCreateThread:
创建了进程的主线程。
这三个函数被调用的顺序是不能够改变的,加载可执行映像之前必须已经为进程创建了地址空间,这样才能够确定可执行映像可以被加载到内存的什么位置;而且在创建主线程之前必须已经加载了可执行映像,这样主线程才能够知道自己要从哪里开始执行,执行哪些指令。
望能对诸君有所帮助,切忌直接抄袭(觉得有用记得点赞呀~)
这篇关于【此后无良辰】 实验3 进程的创建的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!