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