一、实验题目
Windows 进程管理
二、实验目的
(1)学会使用 VC 编写基本的 Win32 Consol Application(控制台应用程序)。
(2)通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操 作系统的进程概念,理解 Windows 进程的“一生”。
(3)通过阅读和分析实验程序,学习创建进程、观察进程、终止进程以及父子进程同步的基本程序设计方法。
三、实验内容(实验原理/运用的理论知识、算法/程序流程图、步骤和方法、关键代码)
1-1 编写基本的 Win32 Consol Application
这个实验的主要目的是熟悉编写C/C++控制台程序,对于创建一个C/C++控制台程序,我常用的有两种方式,逐一说明其优缺点。
第一种方式是在菜单栏点击 File – New – File… ,在弹出的窗口中选择 C/C++ source ,然后选择代码类型是C还是C++,之后设置文件保存的位置,然后就会生成一个.c(.cpp)文件,在这个文件中就可以编写c(c++)代码了。编写完成后在菜单栏 点击 Build – Build and run 或者直接按F9,即可查看输出。这种方法创建C/C++控制台程序,优点是轻便,文件最后只生成三个,源代码.c文件,.o文件还有exe文件,缺点是不支持调试。适合轻量级开发
第二种方法是新建一个工程,在菜单栏点击 File – New – Project…,弹出的界面选择 Console Application ,然后选择代码类型和文件保存目录,之后它会生成一个该项目的文件夹,然后有一个main.c(main.cpp)文件,在这个文件中编写代码。这个项目中的核心文件是.cbp,还会生成很多从属文件,优点是调试方便,可以用Debug单步调试,缺点是生成文件多,适合大型项目开发。
本次操作系统课程设计均是用第二种方式生成C++项目编写。
1-2 创建进程
1.创建一个C++项目,将指导书中的1-2代码复制到main.cpp文件中,然后编译运行
2.按照代码中的注释提示修改代码,看有什么不同,共有两处修改
3.通过查阅相关资料分析为何会出现这样的结果
关键代码
BOOL bCreateOK=::CreateProcess(
szFilename, // 产生这个 EXE 的应用程序的名称
szCmdLine, // 告诉其行为像一个子进程的标志
NULL, // 缺省的进程安全性
NULL, // 缺省的线程安全性
FALSE, // 不继承句柄
CREATE_NEW_CONSOLE, // 使用新的控制台
NULL, // 新的环境
NULL, // 当前目录
&si, // 启动信息
&pi) ; // 返回的进程信息
1-3 父子进程的简单通信及终止进程
1.创建一个C++项目,将指导书中的1-3代码复制到main.cpp文件中,然后按F9查看运行结果
2.根据注释修改代码,查看结果
3.查阅资料,分析原因
关键代码
// 决定其行为是父进程还是子进程
if (argc>1 && :: strcmp(argv[1], "child" ) == 0)
{
Child() ;
}
else
{
Parent() ;
}
四、实验结果与分析
(1)基本的Win32 Console Application:
预期结果:编译成功并生成可执行文件。运行可执行文件后,在命令提示符窗口中显示运行结果。
分析:这个实验主要是为了验证编译环境的正确性,并确保能够成功编译和执行基本的Win32控制台应用程序。
(2)创建进程:
预期结果:每次运行程序时,它会启动自身的克隆进程,并显示每个进程的系统进程ID和在进程列表中的位置。
分析:通过创建进程的方式,可以生成多个相同的进程实例。每个进程将显示其自己的系统进程ID和在进程列表中的位置。通过修改nClone的定义和初始化方式,可以控制生成的进程数量。
在第一次修改中,nClone被定义为0,并将其初始化为0。这意味着在程序开始运行时,初始的克隆ID将为0。
在第二次修改中,nClone的初始化被修改为0,但定义的位置与第一次修改不同。
当修改nClone的值时,即在 :: sscanf(argv[1] , "%d" , &nClone) ;后nClone=0;重新赋值,此时nClone始终为0,此时进程不断派生。
从main()函数开始,首先判断argc的值(argc初始值默认为1)因为argc不满足大于1,所以不能将argv[1]赋值给nClone;然后nClone < c_nCloneMax ,则调用StartClone (++nClone)函数,创建子进程;创建子进程后,argc的值变为2,然后将自增的nClone赋值argv[1],然后将继续执行main()函数,直到(nClone >c_nCloneMax),跳出,结束创建新进程。
(3)父子进程的简单通信及终止进程:
预期结果:父进程创建子进程,并通过命令行参数将克隆号传递给子进程。子进程接收到克隆号后,在命令提示符窗口中显示自己的系统进程ID和克隆号。父子进程之间通过互斥体(Mutex)进行同步。
分析:从main()函数开始,首先判断argc的值(argc初始值默认为1),决定进行父进程还是子进程,因为argc不满足大于1,所以调用parent()函数,在执行parent()函数过程中调用StartClone() ;然后通过sprintf(szCmdLine, “”%s"child" , szFilename)将argv[1]赋值child,后面满足条件后调用child()函数;由于设置了互斥信号,则只允许一个进程进行,所以只有当父进程释放互斥信号hMutexSuicide时,子进程检测获得才结束进程
程序执行过程的大致描述:
1.程序开始运行,进入main()函数。
2.根据命令行参数判断当前进程是父进程还是子进程。
3.如果是父进程,则执行Parent()函数。
4.在Parent()函数中,创建一个互斥体对象,然后调用StartClone()函数创建子进程。
5.父进程等待用户的键盘输入。
6.当用户按下键盘时,父进程释放互斥体的所有权,发送信号给子进程。
7.子进程执行Child()函数。
8.在Child()函数中,子进程打开父进程创建的互斥体对象,并等待互斥体的信号。
9.当子进程收到互斥体的信号时,输出相应信息,并关闭互斥体的句柄,然后结束子进程。
10.父进程释放互斥体的句柄,并结束父进程的执行。
五、小结与心得体会
1.进程是操作系统中的基本概念,理解进程的创建、执行和管理对于学习操作系统和编程非常重要。
2.Windows提供了丰富的API和函数来管理进程,如CreateProcess、GetModuleFileName和GetProcessId等。熟悉这些函数的用法可以方便地创建、控制和通信进程。
3.创建子进程是一种常见的并发编程模式,可以通过克隆主进程来实现并行处理任务,每个进程都可以独立执行。
4.进程之间可以通过命令行参数进行通信,父进程可以将信息传递给子进程,并通过子进程的输出结果进行观察和分析。
5.互斥体(Mutex)是一种用于进程间同步的机制,可以确保多个进程之间的顺序执行和互斥访问共享资源。
6.调试工具和跟踪语句对于理解程序的执行过程和调试错误非常有帮助,可以加深对进程管理的理解。
7.实验中的代码示例是基于Windows系统和Win32 API的,但进程管理的概念和原理在其他操作系统中也是通用的。通过学习Windows进程管理,可以为理解和应用其他操作系统提供基础。