创建子进程:本实验显示了创建子进程的基本框架。该程序只是再一次地启动自身,显示它的系统进程 ID和它在进程列表中的位置。
步骤 1:创建一个“Win32 Consol Application”工程,然后可复制下面中的程序,编译成可执行文件或者使用 VC++ 6.0创建编译执行下面代码。
步骤 2:在“命令提示符”窗口运行步骤 1 中生成的可执行文件,列出运行结果。按下ctrl+alt+del,调用 windows 的任务管理器,记录进程相关的行为属性。
步骤 3:在“命令提示符”窗口加入参数重新运行生成的可执行文件,列出运行结果。按下ctrl+alt+del,调用 windows 的任务管理器,记录进程相关的行为属性。
步骤 4:修改下面中的程序,将 nClone 的定义和初始化方法按程序注释中的修改方法进行两次修改,编译成可执行文件(执行前请先保存已经完成的工作)。再按步骤 2 中的方式运行,看看结果会有什么不一样。列出行结果。从中你可以得出什么结论?说明 nClone 的作用。 变量的定义和初始化方法(位置)对程序的执行结果有影响吗?为什么?
回答:控制程序执行过程,当nClone>5时跳出循环,创建子进程结束;有,在第二次更改中,由于nClone每次都初始化为0,会陷入死循环,不断创建子进程。
代码(注意有两次修改,每次修改之后都要重新编译):
温馨提示:请注意下面的标黑的解释也就是标数字的理解顺序,仅供各位参考理解!若发现有任何错误或者有好的建议也欢迎在评论中提出!!!
#include <windows.h> #include <iostream> #include <stdio.h> // 创建传递过来的进程的克隆过程并赋于其 ID 值 void StartClone(int nCloneID) { // 提取用于当前可执行文件的文件名 TCHAR szFilename[MAX_PATH] ; GetModuleFileName(NULL, szFilename, MAX_PATH) ; // 格式化用于子进程的命令行并通知其 EXE 文件名和克隆 ID TCHAR szCmdLine[MAX_PATH]; sprintf(szCmdLine,"\"%s\" %d",szFilename,nCloneID);**//4、将传递过来自增的nCloneID的值赋给%d对应的参数也就是下面的argv[1]** // 用于子进程的 STARTUPINFO 结构 STARTUPINFO si; ZeroMemory(&si , sizeof(si) ) ; si.cb = sizeof(si) ; // 必须是本结构的大小 // 返回的用于子进程的进程信息 PROCESS_INFORMATION pi; // 利用同样的可执行文件和命令行创建进程,并赋于其子进程的性质 BOOL bCreateOK=::CreateProcess( szFilename, // 产生这个 EXE 的应用程序的名称 szCmdLine, // 告诉其行为像一个子进程的标志 NULL, // 缺省的进程安全性 NULL, // 缺省的线程安全性 FALSE, // 不继承句柄 CREATE_NEW_CONSOLE, // 使用新的控制台 NULL, // 新的环境 NULL, // 当前目录 &si, // 启动信息 &pi) ; // 返回的进程信息 // 对子进程释放引用 if (bCreateOK) { CloseHandle(pi.hProcess) ; CloseHandle(pi.hThread) ; } } int main(int argc, char* argv[] ) { **//1、在刚开始创建程序时argc=1** // 确定派生出几个进程,及派生进程在进程列表中的位置 int nClone=0; // nClone=0; **//第一次修改将此行的(//)去掉,只剩下(nClone=0;)** if (argc > 1)**//2、只有满足条件才执行括号内的内容** { // 从第二个参数中提取克隆 ID :: sscanf(argv[1] , "%d" , &nClone) ;**//5、argv[1]从上面获取到增值之后再传递给nClone** } // nClone=0; **//第二次修改将此行的(//)去掉,只剩下(nClone=0;)*** // 显示进程位置 std :: cout << "Process ID:" << :: GetCurrentProcessId() << ", Clone ID:" << nClone << std :: endl; // 检查是否有创建子进程的需要 const int c_nCloneMax=5; if (nClone < c_nCloneMax) { // 发送新进程的命令行和克隆号 StartClone(++nClone) ;**//3、创建子进程之后,argc会自增然后大于1** } // 等待响应键盘输入结束进程 getchar(); return 0; }
第一次修改结果如下图:
第二次修改结果如下图(死循环创建子进程,这时候需要及时强行关闭程序):
创建子进程流程图