题
根据 SDK,有些 Win32 对象可以“继承”给给定进程创建的子进程。(事件、互斥体、管道……)
这实际上意味着什么?
假设我有一个命名事件对象,使用以下命令创建 CreateEvent
, 一次与 bInheritHandle == true
, ,还有一次 == false
.
现在我启动一个子进程。这两个事件句柄如何影响子进程?它们在哪些场景下有不同?
解决方案
如果您创建/打开一个对象并允许继承该句柄,则允许继承句柄的子进程(例如你可以指定 bInheritHandles = TRUE
对于 CreateProcess)将拥有这些句柄的副本。这些继承的句柄将具有与父句柄相同的句柄值。例如:
CreateEvent
返回事件对象的句柄,句柄是0x1234
.- 您允许继承该句柄。
- 您创建一个继承您的句柄的子进程。
- 该子进程现在可以使用句柄
0x1234
无需打电话CreateEvent
或者OpenEvent
. 。例如,您可以在子进程的命令行中传递句柄值。
这对于未命名的对象很有用 - 因为它们是未命名的,所以其他进程无法打开它们。如果需要,使用句柄继承子进程可以获得未命名对象的句柄。
其他提示
现有答案中尚未提出的一点是,允许子进程继承句柄不仅会影响子进程,还会影响子进程。它还可能影响句柄所引用的对象的生命周期。如果父进程退出,子进程中的句柄将使对象保持活动状态。
当允许子进程继承句柄时,您必须考虑这是否会导致对象的生存时间比应有的时间长;例如,某些应用程序只想允许一次运行一个实例,并且可能通过创建具有给定名称的事件对象并查看它是否已存在来实现这一点。如果他们创建一个继承该事件对象的子进程,并且比父进程寿命更长,则可能会导致误报。
更常见的是,继承的文件句柄可能会导致文件的使用时间(因此无法访问)比应有的时间长。
因此,最佳实践是:
使所有句柄不可继承,除非它们特别需要继承。
如果子进程不需要继承句柄,则传递
FALSE
为了bInheritHandles
.如果子进程确实需要继承句柄, 只允许它继承那些需要的特定句柄.
另一方面,这有时也很有用。例如,如果您 想 子进程算作父进程的实例,或者文件在子进程退出之前保持不可访问。另一个技巧是让子进程继承命名对象的句柄,然后使用该对象的存在或不存在来确定子进程是否仍然存在,而无需传递进程句柄或进程 ID。
如果你创建事件,并允许通过子进程继承手柄,那么孩子过程可以使用手柄将由父创建完全相同的对象。这可以在儿童使用事件句柄信号到父当任务已经完成的方式使用(有许多其它用途可继承事件对象处理)。
编辑: 除去假。