windows进程(4)
windows支持GUI和CUI这两个程序,前者是(图形化),后者是(控制台)。GUI的链接器开关是/SUBSYSTEM:CONSOLE;CUI的链接器开关是/SUBSYSTEM:WINDOWS。
相应的开关会让操作系统...(P67顶)。
windows应用程序的入口是Int WINAPI _tWinMain()【GUI程序】和int _tmain() 【控制台程序】。注意:操作系统并不实际调用我们所写的入口点程序。它调用C/C++运行库实现并连接时使用-entry:命令行选项来设置一个c/c++运行时启动函数。该函数将初始化c/c++运行库,使我们能使用malloc和free等函数。它还确保我们声明的全局和静态的C++对象的正确的被构造。(具体函数是WinMainCRTStartup和mainCRTStartup)
如果创建了Win32程序,但是主程序却命名为main后,那么链接器会报错,因为找不到WinMain或wWinMain函数,这时可以修改main为WinMain或者将属性配置->Linker->system->subsystem中的/SUBSYSTEM:WINDOWS开关改为/SUBSYSTEM:CONSOLE即可。
c/c++库启动函数作用:P69(5点)
完成以上作用后,其会调用应用程序入口点函数。
入口点函数返回后,启动函数将调用C运行库函数exit,想起传递返回值(nMainRetVal即入口点函数的返回值)。exit执行的作用如下:(四点)
1.调用_onexit函数去调用所注册的每一个函数。
2.调用全局或静态对象的析构函数。
3.在DEBUG中,如果设置了_CRTDBG_LEAK_CHECK_DF标志,就通过调用_CrtDumpMemoryLeaks函数生成内存泄漏报表。
4.调用操作系统的ExitProcess函数,向其传入nMainRetVal。这样,操作系统会“杀死”进程,并设置退出代码。
我们用CreateProcess函数创建一个进程时,其先创建一个进程内核对象,进程内核对象不是进程本身,而是操作系统用来管理这个进程的一个小型数据结构。1.系统为新进程创建一个虚拟地址空间,并将可执行文件(和所有必要的DLL)的代码和数据都加载到进程的地址空间中。2.然后,system为此进程的主线程开辟一个新的线程内核对象(使其使用计数为1)。线程内核对象也同进程内核对象一样,都是一个小型数据结构,不是线程本身。3.这个主线程一开始会执行c/c++运行时的启动函数,最终会调用应用程序WinMain或者main函数。如果系统成功创建了新进程和主线程,CreateProcess将返回TRUE。
进程有四种方式终止。1.主线程的入口函数返回 (强烈推荐)2.进程中的一个线程调用ExitProcess(不推荐)3.另一个进程调用TerminateProcess(不推荐)4.进程中的所有线程都“自然死亡”(几乎不会发生)
如果使用返回的方式,会返回到C/C++运行库启动代码中,然后其清除相应的c运行库资源后调用ExitProcess,并将入口点函数返回值传给它。注意:系统定义一个进程中还有线程存在,那么这个进程就不会被终止,但是c运行库在其主线程入口函数返回后会显示调用ExitProcess去终止进程,但是如果在主线程中调用ExitThread,那么主线程会停止执行,但是只要还有其他线程存在,进程就不会终止。
当创建一个应用程序后,可以调用CloseHandle函数,断绝其子进程和父进程的父子关系。
PROCESS_INFORMATION pi;
if(CreateProcess(.....,&pi));
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}