进程的终止
若要终止进程的运行,可以使用下面四种方法:
• 主线程的进入点函数返回(最好使用这个方法) 。
• 进程中的一个线程调用ExitProcess函数(应该避免使用这种方法) 。
• 另一个进程中的线程调用TerminateProcess函数(应该避免使用这种方法) 。
• 进程中的所有线程自行终止运行(这种情况几乎从未发生) 。
1、主线程的进入点函数返回
始终都应该这样来设计应用程序,即只有当主线程的进入点函数返回时,它的进程才终止运行。这是保证所有线程资源能够得到正确清除的唯一办法。
让主线程的进入点函数返回,可以确保下列操作的实现:
• 该线程创建的任何C + +对象将能使用它们的析构函数正确地撤消。
• 操作系统将能正确地释放该线程的堆栈使用的内存。
• 系统将进程的退出代码(在进程的内核对象中维护)设置为进入点函数的返回值。
• 系统将进程内核对象的返回值递减1。
2、ExitProcess函数
(1)当进程中的一个线程调用ExitProcess函数时,进程便终止运行:
VOID ExitProcess(UINT fuExitCode)
该函数用于终止进程的运行,函数并不返回任何值,因为进程已经终止运行。如果在调用 ExitProcess之后又增加了什么代码,那么该代码将永远不会运行。
(2) 当主线程的进入点函数( WinMain、wWinMain、main或wmain)返回时,它将返回给C/C++运行期启动代码,它能正确地清除该进程使用的所有的C运行期资源。当C运行期资源被释放之后,C运行期启动代码就显式调用ExitProcess,并将进入点函数返回的值传递给它。(只需要主线程的进入点函数返回,就能够终止整个进程的运行。请注意,进程中运行的任何其他线程都随着进程而一道终止运行)。
(3)Windows Platform SDK文档声明,进程要等到所有线程终止运行之后才终止运行。就操作系统而言,这种说法是对的。但是,C/C++运行期对应用程序采用了不同的规则,通过调用ExitProcess,使得C/C++运行期启动代码能够确保主线程从它的进入点函数返回时,进程便终止运行,而不管进程中是否还有其他线程在运行。不过,如果在进入点函数中调用 ExitThread,而不是调用ExitProcess或者仅仅是返回,那么应用程序的主线程将停止运行,但是,如果进程中至少有一个线程还在运行,该进程将不会终止运行。
(4)调用ExitProcess或ExitThread可使进程或线程在函数中就终止运行。ExitProcess函数强制进程在现场终止运行,C/C++运行期没有机会进行清除。只要让主线程的进入点函数返回,C/C++运行期就能够执行它的清除操作,并且正确地撤消任何或所有的C + +对象。在调用ExitThread时,进程将继续运行,但是可能会泄漏内存或其他资源。
3、TerminateProcsee函数
调用TerminateProcsee函数也能够终止进程的运行
BOOL TerminateProcsee(HANDLE hProcess, UINT fuExitCode);
(1) 任何线程都可以调用TerminateProcsee来终止另一个进程或它自己的进程的运行。hProcess参数用于标识要终止运行的进程的句柄。当进程终止运行时,它的退出代码将成为你作为fuExitCode参数来传递的值。
只有当无法用另一种方法来迫使进程退出时,才应该使用 TerminateProcsee。终止运行的进程绝对得不到关于它将终止运行的任何通知,因为应用程序无法正确地清除,并且不能避免自己被撤消(除非通过正常的安全机制)。
(2)TerminateProcsee函数是个异步运行的函数,也就是说,它会告诉系统,你想要进程终止运行,但是当函数返回时,你无法保证该进程已经终止运行。
4、进程终止运行时出现的情况
当进程终止运行时,下列操作将启动运行:
1) 进程中剩余的所有线程全部终止运行。
2) 进程指定的所有用户对象和G D I对象均被释放,所有内核对象均被关闭(如果没有其他进程打开它们的句柄,那么这些内核对象将被撤消。但是,如果其他进程打开了它们的句柄,内核对象将不会撤消) 。
3) 进程的退出代码将从STILL_ACTIVE改为传递给ExitProcess或TerminateProcsee的代码。
4) 进程内核对象的状态变成收到通知的状态,系统中的其他线程可以挂起,直到进程终止运行。
5) 进程内核对象的使用计数递减1。
来源:https://www.cnblogs.com/dyufei/archive/2009/04/26/2574004.html