@1405010304geshuaishuai
2016-04-21T09:27:23.000000Z
字数 5134
阅读 3078
windows 进程管理
步骤1:登录进入Windows 系统,启动VC++ 6.0。
步骤2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32 ConsolApplication”,然后在“Project name”处输入工程名,在“Location” 处输入工程目录。创建一个新的控制台应用程序工程。
步骤3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++ Source File”,
然后在“File” 处输入C/C++源程序的文件名。
步骤4:将清单1-1 所示的程序清单复制到新创建的C/C++源程序中。编译成可执行文件。
步骤5:在“开始”菜单中单击“程序”-“附件”-“命令提示符”命令,进入Windows“命
令提示符”窗口,然后进入工程目录中的debug 子目录,执行编译好的可执行程序,列出运行结果如图5-1.
清单1-1 一个简单的Windows 控制台应用程序// hello 项目# include <iostream>void main(){std::cout << “Hello, Win32 Consol Application” << std :: endl ;}

本实验显示了创建子进程的基本框架。该程序只是再一次地启动自身,显示它的系统进程ID和它在进程列表中的位置。
步骤1:创建一个“Win32 Consol Application”工程,然后拷贝清单1-2 中的程序,编译成可执行文件。
步骤2:在“命令提示符”窗口运行步骤1 中生成的可执行文件,列出运行结果(见图5-2)。按下ctrl+alt+del,调用windows的任务管理器,记录进程相关的行为属性(见图5-3)。
步骤3:在“命令提示符”窗口加入参数重新运行生成的可执行文件,列出运行结果(见图5-4)。按下ctrl+alt+del,调用windows 的任务管理器,记录进程相关的行为属性。
步骤4:修改清单1-2 中的程序,将nClone 的定义和初始化方法按程序注释中的修改方法进行修改,编译成可执行文件(执行前请先保存已经完成的工作)。再按步骤2 中的方式运行,看看结果会有什么不一样。
清单1-2 创建子进程#include <windows.h>#include <iostream>#include <stdio.h>// 创建传递过来的进程的克隆过程并赋于其ID 值void StartClone(int nCloneID){// 提取用于当前可执行文件的文件名TCHAR szFilename[MAX_PATH] ;GetModuleFileName(NULL, szFilename, MAX_PATH) ;// 格式化用于子进程的命令行并通知其EXE 文件名和克隆IDTCHAR szCmdLine[MAX_PATH];sprintf(szCmdLine,"\"%s\" %d",szFilename,nCloneID);// 用于子进程的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[] ){// 确定派生出几个进程,及派生进程在进程列表中的位置int nClone=0;//修改语句:int nClone;//第一次修改:nClone=0;if (argc > 1){// 从第二个参数中提取克隆ID:: sscanf(argv[1] , "%d" , &nClone) ;}//第二次修改:nClone=0;// 显示进程位置std :: cout << "Process ID:" << :: GetCurrentProcessId()<< ", Clone ID:" << nClone<< std :: endl;// 检查是否有创建子进程的需要const int c_nCloneMax=5;if (nClone < c_nCloneMax){// 发送新进程的命令行和克隆号StartClone(++nClone) ;}// 等待响应键盘输入结束进程getchar();return 0;}

步骤1:创建一个“Win32ConsolApplication”工程,然后拷贝清单1-3中的程序,编译成可执行文件。
步骤2:在VC 的工具栏单击“Execute Program”(执行程序) 按钮,或者按Ctrl + F5键,或者在“命令提示符”窗口运行步骤1 中生成的可执行文件,列出运行结果(见图5-5)。
步骤3:按源程序中注释中的提示,修改源程序1-3,编译执行(执行前请先保存已经完成的工作),列出运行结果(见图5-6)。在程序中加入跟踪语句,或调试运行程序,同时参考MSDN中的帮助文件CreateProcess()的使用方法,理解父子进程如何传递参数。给出程序执行过程的大概描述。
步骤4:按源程序中注释中的提示,修改源程序1-3,编译,列出运行结果(见图5-7)。
步骤5:参考MSDN 中的帮助文件CreateMutex() 、OpenMutex() 、ReleaseMutex()和WaitForSingleObject()的使用方法,理解父子进程如何利用互斥体进行同步的。给出父子进程同步过程的一个大概描述。
清单1-3 父子进程的简单通信及终止进程的示例程序// procterm 项目# include <windows.h># include <iostream># include <stdio.h>static LPCTSTR g_szMutexName = "w2kdg.ProcTerm.mutex.Suicide" ;// 创建当前进程的克隆进程的简单方法void StartClone(){// 提取当前可执行文件的文件名TCHAR szFilename[MAX_PATH] ;GetModuleFileName(NULL, szFilename, MAX_PATH) ;// 格式化用于子进程的命令行,字符串“child”将作为形参传递给子进程的main 函数TCHAR szCmdLine[MAX_PATH] ;//实验1-3 步骤3:将下句中的字符串child 改为别的字符串,重新编译执行,执行前请先保存已经完成的工作sprintf(szCmdLine, "\"%s\"child" , szFilename) ;// 子进程的启动信息结构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) ;}}void Parent(){// 创建“自杀”互斥程序体HANDLE hMutexSuicide=CreateMutex(NULL, // 缺省的安全性TRUE, // 最初拥有的g_szMutexName) ; // 互斥体名称if (hMutexSuicide != NULL){// 创建子进程std :: cout << "Creating the child process." << std :: endl;StartClone() ;// 指令子进程“杀”掉自身std :: cout << "Telling the child process to quit. "<< std :: endl;//等待父进程的键盘响应getchar() ;//释放互斥体的所有权,这个信号会发送给子进程的WaitForSingleObject 过程ReleaseMutex(hMutexSuicide) ;// 消除句柄CloseHandle(hMutexSuicide) ;}}void Child(){// 打开“自杀”互斥体HANDLE hMutexSuicide = OpenMutex(SYNCHRONIZE, // 打开用于同步FALSE, // 不需要向下传递g_szMutexName) ; // 名称if (hMutexSuicide != NULL){// 报告我们正在等待指令std :: cout <<"Child waiting for suicide instructions. " << std :: endl;//子进程进入阻塞状态,等待父进程通过互斥体发来的信号WaitForSingleObject(hMutexSuicide, INFINITE) ;//实验1-3 步骤4:将上句改为WaitForSingleObject(hMutexSuicide, 0) ,重新编译执行// 准备好终止,清除句柄std :: cout << "Child quiting." << std :: endl;CloseHandle(hMutexSuicide) ;}}int main(int argc, char* argv[] ){// 决定其行为是父进程还是子进程if (argc>1 && :: strcmp(argv[1] , "child" )== 0){Child() ;}else{Parent() ;}return 0;}
