- 进程实例句柄
GetModuleHandle,传递一个字符串,它指定了已在主调进程的地址空间中加载的一个可执行文件或DLL文件的名称,GetModuleHandle返回可执行文件/DLL文件映像加载到的基地址
如果传入NULL,返回主调进程的可执行文件的基地址,即使调用GetModuleHandle的函数在一个DLL文件中,返回值仍然是可执行文件的基地址,而非DLL文件的基地址
调用GetModuleHandleEx,将GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS作为它的第一个参数,将当前的函数地址作为第二个参数。最后一个参数是一个指向HMODULE的指针,GetModuleHandleEx会用传入函数所在DLL的基地址来填写该指针
- 进程前一个实例的句柄
C/C++运行库启动代码总是向(w)WinMain的hPrevInstance参数传递NULL。
- 进程的命令行
系统在创建一个新进程时,会传一个命令行给它。这个命令行几乎总是非空的
C运行库的启动代码开始执行一个GUI程序时,会调用Windows函数GetCommonLine来获取进程的完整命令行,忽略可执行文件的名称,然后将指向命令行剩余部分的指针传给WinMain的pszCmdLine参数
GetCommandLine返回的总是同一个缓冲区的地址
想释放这部分内存,正确的做法是调用HeapFree
-
进程的环境变量
每个进程都有一个与它关联的环境块,这是在进程地址空间分配的一块内存
GetEnvironmentStrings函数获取完整的环境块
FreeEnvironmentStrings函数来释放它
GetEnvironmentVariable函数来判断一个环境变量是否存在,通过两次调用来安全的使用它
可以使用SetEnvironmentVariable函数添加一个变量 -
进程当前所在的驱动器和目录
GetCurrentDirectory
父进程可以通过调用GetFullPathName来获得它的当前目录
- 系统版本
GetVersionEx
VerifyVersionInfo
- CreateProcess函数
一个线程调用CreateProcess时,系统将创建一个进程内核对象,其初始使用计数为1。进程内核对象不是进程本身,而是操作系统用来管理这个进程的一个小型数据结构--可以把进程内核对象想象成由进程统计信息构成的一个小型数据结构。然后,系统为新进程创建一个虚拟地址空间,并将可执行文件(和所有必要的DLL)的代码及数据加载到进程的地址空间。
*pszApplicationName和pszCommandLine参数
pszApplicationName和pszCommandLine参数分别指定新进程的命令行字符串。
- psaProcess,psaThread和bInheritHandles参数
为了创建一个新的进程,系统必须创建一个进程内核对象和一个线程内核对象。由于这些都是内核对象,所以父进程有机会将安全属性关联到这两个对象上。
- fdwCreate参数
fdwCreate参数标识了影响新进程创建方式的标志。多个标志可以使用按位或起来,以便同时使用多个标志组合。
- pvEnvironment参数
pvEnvironment参数指向一块内存,其中包含新进程要使用的环境字符串。大多时候,为这个参数传入的值都是NULL,这将导致子进程继承父进程使用的一组环境字符串
- pszCurDir参数
pszCurDir参数允许父进程设置子进程的当前驱动器和目录。
- psiStartInfo
psiStartInfo参数指向一个STARTINFO机构或STARTINFOEX结构
- ppiProclnfo参数
ppiProlnfo参数指向一个PROCESS_INFORMATION结构,CreateProcee在返回前,会初始化这个结构的成员
如前所述,创建一个新的进程,会导致系统创建一个进程内核对象和一个线程内核对象,在创建时,系统会为每个对象指定一个初始的使用计数1。然后就在CreateProcee函数饭后前,它会使用完全使用权限来打开进程对象和线程对象,并将各自与进程相关的句柄放入PROCESS_INFORMATION结构的hProcee和hThread成员中,当CreateProcess在内部打开这些对象时,每个对象的使用计数就变成2。
终止进程
进程可以通过以下4中方式终止:
-
主线程的入口点函数返回
-
进程中的一个线程调用ExitProcess函数(要避免这个方式)
-
另一个进程中的一个线程调用TerminateProcess函数(避免)
-
进程中的所有线程都自然死亡(这种现象基本上从来不会发生)
-
主线程的入口点函数返回
让主线程的入口点函数返回,可以保证以下操作会被执行
- 该线程创建的任何C++对象都将由这些函数的析构函数正确销毁
- 操作系统将正确释放线程栈使用的内存
- 系统将进程的推出代码设置成入口点函数的返回值
- 系统递减进程对象的使用计数
- ExitProcess函数
该函数将终止进程,并将进程的退出代码设置为fuExitCode。
- TerminateProcess函数
只有在无法通过其他方法来强制进程退出时,才应使用TerminateProcess。
- 当进程终止运行时
一个进程终止运行时,系统会依次执行以下操作。
(1) 终止进程中遗留的任何线程
(2) 释放进程分配的所有用户对象和GDI对象,关闭所有内核对象。
(3) 进程的退出代码从STILL_ACTIVE变为传给ExitProcess或TerminateProcess函数的代码
(4) 进程内核对象的状态变成已触发
(5) 进程内核对象的使用计数递减1。
网友评论