主题:如何管理所有正在运行的应用程序
进程:1.进程内核对象 2.进程的地址空间 两部分组成
进程使用内核对象来存放进程的信息。
地址空间包含所有可执行模块以及DLL模块的代码和数据,还包括动态内存分配的空间
C/C++运行时启动函数的功能:
具体流程如下,代码见 crtexe.c
(1) 取得指向进程的命令行(command line)的指针
(2) 取得指向进程的环境变量的指针
(3) 初始化C/C++ Run Time的全局变量,这此变量放在StdLib.h中
(4) 初始化C Run Time 内存分配函数所用的堆,从而使malloc/free 函数可用。
(5) 调用程序中的静态变量和全局变量的构造函数
(6) 调用程序中的Main/WinMain函数
(7) 当从Main中返回后,取得Main的返回值Ret,调用C Run-Time exit(Ret) 函数,参数是Ret
(8) 调用_onexit注册的函数
(9) 为所有全局和静态变量调用析构函数
(10) 若是Debug Build,如果_CRTDBG_LEAK_CHECK_DF 宏被设置了,系统会调用_CrtDumpMemoryLeaks函数 输出程序中的内存泄露的地方
(11) 以Ret参数调用操作系统的ExitProcess函数,操作系统会杀掉当前进程并设置进程的Exit Code.
注:第11条说明在Windows中主线程退出会执行ExitProcess,即使有未执行完的线程进程也会退出。这种做法与Linux不同。
若将ExitProcess改为ExitThread 那么主线程退出时 若还有其它线程在运行,进程不会退出。
GetModuleHandle:返回将可执行文件或DLL文件加载到调用进程的地址空间时,所使用的句柄地址或及地址
创建进程内核对象:BOOL CreateProcess(
PCTSTR psz ApplicationName,
PTSTR pszCommandLine,
PSECURITY_ATTRIBUTES psaProcess,
PSECURITY_ATTRIBUTES psaThread,
BOOL bInheritHandles,
DWORD fdwCreate,
PVOID pvEnvironment,
PCTSTR pszCurDir,
PSTARTUPINFO psiStartInfo,
PPRCESS_INFOMATION ppiProcInfo);
其中psiStartInfo指向的数据结构STARTUPINFO中的成员必须被初始化为0.
子进程
子进程有自已的进程地址空间,它不依附于父进程而独立存在。即使父进程终止了 子进程仍可以运行。
除非父进程给子进程共享了某些数据或资源 否则子进程无法操作父进程的数据。
父进程在创建完子进程后 根据需要 适时调用CloseHandle()函数 关闭子进程的Thread句柄和Process句柄。否则父进程会一直持有子进程的Thread和Process句柄 从而导致系统无法释放子进程的Process和Thread所占用的资源。父进程也可以通过 WaitForSingleObject 函数等待子进程结束。然后再关闭Process 句柄。
分离的子进程
在创建完子进程后, 父进程不需要与子进程有任何交互或不需要等待子进程执行完后再继续做其它的事,
那么在创建完子进程可立刻关闭父进程所持有的子进程的Process句柄和Thread句柄,从而将子进程分离出来。
例子如下:
PROCESS_INFORMATION pi;
// Spawn the child process.
BOOL fSuccess = CreateProcess(..., &pi);
if (fSuccess)
{
// Allow the system to destroy the process & thread kernel
// objects as soon as the child process terminates.
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
如何使用相关的内核对象对进程进行操作