9.1.2 创建/终止进程
1.问题阐述
进程的创建通过CreateProcess()函数来实现,CreateProcess()通过创建一个新的进程及在其地址空间内运行的主线程来启动并运行一个新的程序。具体地,在执行CreateProcess()函数时,首先由操作系统负责创建一个进程内核对象,初始化计数为1,并立即为新进程创建一块虚拟地址空间。随后将可执行文件或其他任何必要的动态链接库文件的代码和数据装载到该地址空间中。在创建主线程时,也是首先由系统负责创建一个线程内核对象,并初始化为1。最后启动主线程并执行进程的入口函数WinMain(),完成对进程和执行线程的创建。
2.实现技巧
CreateProcess()函数的原型声明如下:
BOOL CreateProcess( LPCTSTR lpApplicationName, // 可执行模块名 LPTSTR lpCommandLine, // 命令行字符串 LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程的安全属性 LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性 BOOL bInheritHandles, // 句柄继承标志 DWORD dwCreationFlags, // 创建标志 LPVOID lpEnvironment, // 指向新的环境块的指针 LPCTSTR lpCurrentDirectory, // 指向当前目录名的指针 LPSTARTUPINFO lpStartupInfo, // 指向启动信息结构的指针 LPPROCESS_INFORMATION lpProcessInformation // 指向进程信息结构的指针 );
|
3.实例代码
在程序设计时,某一个具体的功能模块可以通过函数或线程等不同的形式来实现。对于同一进程而言,这些函数、线程都是存在于同一个地址空间下的,而且在执行时,大多只对与其相关的一些数据进行处理。如果算法存在某种错误,将有可能破坏与其同处一个地址空间的其他一些重要内容,这将造成比较严重的后果。为保护地址空间中的内容可以考虑将那些需要对地址空间中的数据进行访问的操作部分放到另外一个进程的地址空间中运行,并且只允许其访问原进程地址空间中的相关数据。具体地,可在进程中通过CreateProcess()函数去创建一个子进程,子进程在全部处理过程中只对父进程地址空间中的相关数据进行访问,从而可以保护父进程地址空间中与当前子进程执行任务无关的全部数据。对于这种情况,子进程所体现出来的作用同函数和线程比较相似,可以看成是父进程在运行期间的一个过程。为此,需要由父进程来掌握子进程的启动、执行和退出。下面这段代码即展示了此过程:
CString sCommandLine; char cWindowsDirectory[MAX_PATH]; char cCommandLine[MAX_PATH]; DWORD dwExitCode; PROCESS_INFORMATION pi; STARTUPINFO si = {sizeof(si)}; // 得到Windows目录 GetWindowsDirectory(cWindowsDirectory, MAX_PATH); // 启动“记事本”程序的命令行 sCommandLine = CString(cWindowsDirectory) + "\\NotePad.exe"; ::strcpy(cCommandLine, sCommandLine); // 启动“记事本”作为子进程 BOOL ret = CreateProcess(NULL, cCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); if (ret) { // 关闭子进程的主线程句柄 CloseHandle(pi.hThread); // 等待子进程的退出 WaitForSingleObject(pi.hProcess, INFINITE); // 获取子进程的退出码 GetExitCodeProcess(pi.hProcess, &dwExitCode); // 关闭子进程句柄 CloseHandle(pi.hProcess); }
|
4.小结
此段代码首先通过CreateProcess()创建Windows自带的“记事本”程序为子进程,子进程启动后父进程通过WaitForSingleObject()函数等待其执行的结束,在子进程没有退出前父进程是一直处于阻塞状态的,这里子进程的作用同单线程中的函数类似。一旦子进程退出,WaitForSingleObject()函数所等待的pi.hProcess对象将得到通知,父进程将得以继续,如有必要可以通过GetExitCodeProcess()来获取子进程的退出代码。
【责任编辑:
夏书 TEL:(010)68476606】