Windows学习——进程(一)
进程
在C/C++所编写的程序中,我们所看到的主函数并不是程序一开始执行的函数,它也只是一个函数,而我们常用的就是命令行主函数入口也就是main,而Windows程序中还有一个主函数入口,就是下面所述
Int WINAPI _tWinMain(
HINSTANCE hInstanceExe,
HINSTANCE,
PTSTR pszCmdLine,
int nCmdShow);
我们常用的命令行入口原型如下:
int _tmain(
int argc,
TCHAR* argv[],
TCHAR* envp[]);
而在进入主函数之前,需要对环境做一些初始化之内的工作,这些工作是交给启动函数去做的,启动函数有几个用途如下:
1.获取指向新进场的完整命令行的一个指针
2.获取指向新进场的环境变量的一个指针
3.初始化C/C++运行库的全局变量。如果包含了StdLih.h,我们的代码就可以访问这些变量。可以通过GetVersionEx、GetCommandLine、GetEnvironmentString、GetEnvironmentVariable、GetModuleFileName等函数获取这些全局变量的值
4.初始化C运行库内存分配函数和其他底层I/O例程使用的堆
5.调用所有全局和静态C++类对象的构造函数
入口点函数返回后,启动函数将调用C运行库函数exit,向其传递返回值(nMainRetVal)。exit函数会执行以下任务:
1.调用_onexit函数调用所注册的任何一个函数
2.调用所有全局和静态C++类对象的析构函数
3.在DEBUG生成中,如果设置了_CRTDBG_LEAK_CHECK_DF标志,就通过调用_CrtDumpMemoryLeaks函数来生成内存泄露报告
4.调用操作系统的ExitProcess函数,向其传入nMainRetVal。这回导致操作系统“杀死”我们的进程,并设置它的推出代码。
进程实例句柄
先说明一下HINSTANCE类型和HMODULE类型这两种参数是一样的,之所以取不一样的名字,这要从16位WIndows说起(网上找找)
HMODULE GetModuleHandle(PCTSTR pszModule);
调用这个函数时,要传递一个以0位终止符的字符串,它指定了已在主调进程的地址空间中加载的一个可执行文件或DLL文件的名称。如果系统找到了指定的可执行文件或DLL文件名称,GetModuleHandle就会返回可执行文件/DLL文件映象加载到的基地址,如果没有则返回null,还有一种用法就是,传进NULL值,可以返回主调进程的可执行文件的基地址。
示例:如果我们的代码在一个DLL中,那么可利用两种方法来了解代码正在什么模块中运行。
第一个方法是利用链接器提供的伪变量_ImageBase,它执行当前正在运行的模块的基地址。如前所述,这是C运行库启动代码在调用我们的WinMain函数时所作的事情
第二方法调用GetModuleHandleEx,将GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS作为他的第一个参数,将当前函数的地址作为第二个参数。最后一个参数时一个执行HMOUDLE的指针,GetModuleHandleEx会传入函数所在DLL的基地址来填写该指针
GetModuleHandleEx函数的两大重要特性:
1.它只检查主调进程的地址空间。如果主调进程没有使用任何通用对话框函数,那么一旦调用该函数,比向其传递ComDlg32,就会导致返回NULL
2.向其传递NULL值,会返回进程的地址空间中的可执行文件的基地址。所以即使是DLL中运行,返回值仍然是可执行文件的基地址,而非DLL文件的基地址