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