Closehandle()未终止进程

8

CloseHandle()在关闭句柄后进程并没有终止。

我使用CreateProcess() api创建了一个进程。即使我关闭了它的句柄,它仍在运行。

根据msdn的说法,CloseHandle()只是关闭句柄,而不是终止进程。必须调用TerminateThread()才能终止进程。那么CloseHandle()的作用是什么呢?

但是当我检查CloseHandle()的返回值时,它是成功的。那么我想知道CloseHandle()实际上做了什么,为什么它会成功返回。我还想知道使用进程句柄可以进行哪些操作。我感到有些误导,因为CloseHandle()成功了,但进程仍在运行!

同时,了解一下进程句柄中实际包含了什么,与其他类型的句柄(如文件、I/O等)有何不同,会更好。


1
类比地说,关闭文件句柄并不会删除文件。 - Harry Johnston
3个回答

11

为什么关闭句柄不会终止进程?必须调用TerminateProcess

关闭句柄不会终止进程,因为这是荒谬的。进程通常相互独立运行。如果关闭进程句柄终止相应的进程,当程序退出时,它持有的所有打开的句柄都将被关闭,这将导致您启动的每个程序都会立即终止,这将是一场灾难。因此,设计上关闭进程句柄不会终止程序。

终止进程几乎总是非常糟糕的主意。终止线程也是如此。如果可以避免,请勿执行此操作。如果要使线程/进程退出,请发送消息并等待其自己退出。这确保保存数据并处于一致状态,没有资源泄漏,并且不会发生严重冲突(例如,线程在持有锁时被终止)。

那么为什么您需要关闭句柄,如果必须关闭它,则为什么还要获取它?

您可以使用句柄执行某些操作,其中包括ReadProcessMemoryWriteProcessMemoryCancelIoEx、运行调试器、使用PSAPI等。此外,您可以等待句柄,在进程退出时将其标记。这是一种非常简单的进程间同步方式。
另一方面,只要您持有句柄打开,并且具有访问这些资源的“合法权利”,操作系统就无法释放资源。例如,如果进程(或至少其结构)已经不存在,您如何等待进程呢?

这就是为什么如果您不需要它,应尽快关闭句柄(并且句柄本身就是资源)。无限期保持它需要操作系统保留不需要但无法释放的资源。
关闭句柄告诉操作系统“您不再需要它”,因此每当操作系统想要释放与进程关联的所有资源时,它都可以这样做。

进程句柄包含什么?

像所有句柄一样,进程句柄只是一个不包含任何内容的不透明整数。它是内核拥有的表中的索引,技术上是一个void*,但这只是一个实现细节。它所指向的实际内核结构不是您可以直接访问的东西,至少不是一种简单的方式。

5
一个句柄是对一些由内核管理的、引用计数对象的引用。通常,关闭对一个对象的最后一个句柄会导致该对象被销毁。
但:当关闭最后一个句柄时,进程和线程并不被杀死,可以认为它们在启动后“独立运行”。如果没有这个例外,你就不能让一个进程比其父进程存在更长的时间,因为每个进程的句柄都会在进程终止时自动关闭(而使线程比其父进程存在更长时间将需要不必要的复杂性)。
总之,所有这些都有文档记录:如果你阅读 CloseHandle 的文档,你会发现:
关闭线程句柄不会终止相关的线程或删除线程对象。关闭进程句柄不会终止相关的进程或删除进程对象。要删除线程对象,必须终止线程,然后关闭到该线程的所有句柄。有关详细信息,请参阅终止线程。要删除进程对象,必须终止进程,然后关闭到该进程的所有句柄。有关详细信息,请参阅终止进程。

2
您所描述的是设计行为。一个进程自己运行,它可能打开零个或多个句柄,这些句柄使持有者能够以某种方式控制进程。一旦您拥有了一个句柄,就需要负责将其关闭。
进程终止是一个不同的事情,并且你基本上不应该在外部终止:你永远不知道确切的终止点。你需要以某种方式发出信号表明你想要进程终止,这样进程才能找出并在内部优雅地终止其活动。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接