【发布时间】:2011-07-06 07:36:01
【问题描述】:
我正在开发一个函数,它可以让我获得给定 PID 的父进程的 PID。该函数的原型是
DWORD getParentPid( DWORD pid );
为此,我使用CreateToolhelp32Snapshot 函数(和相关函数)来获取给定PID pid 的PROCESSENTRY32 结构。然后我可以使用结构的th32ParentProcessId 字段来获取创建给定进程的进程的PID。
但是,由于父进程可能已经被销毁(并且它的 PID 可能已被 Windows 重用),我使用GetProcessTimes 函数来获取假定的父进程和子进程的创建时间,然后比较那些使用CompareFileTime的。
如果CompareFileTime返回-1,我知道父ID的进程是在我的子进程之前创建的,所以它确实是父进程。否则,它显然是一个重复使用的 ID - 并且父 PID 无效(它不再引用原始父)。
问题在于它非常依赖严格单调的系统时钟和GetProcessTimes 的粒度。我确实遇到过CompareFileTime 返回0(意思是“相等的时间”)的案例,尽管所考虑的过程确实是亲子关系。我可以更改我的检查,以便将 CompareFileTime 结果值 <= 0 视为指示父进程,但随后我将打破父进程创建子进程,然后父进程被销毁,然后Windows 重新使用了 PID - 都在 100ns 内(这是GetProcessTimes 的分辨率)。
我想知道 - 是否有不同的、更可靠的机制来验证某个进程确实是 C++ 中另一个进程的父进程?
编辑:我需要这个函数来确定所有子进程(这意味着包括孙子进程)。 CreateToolhelp32Snapshot 让我可以遍历所有进程,但我需要查看每个进程的父 PID,以判断它是否是我手头进程的子进程。
【问题讨论】:
-
并非如此。但是你为什么需要这个?如果您甚至不知道父进程是否仍在运行,即使可以可靠地识别它,您会如何处理它?听起来像是寻找问题的解决方案。
-
@jalf:我编辑了我的问题以提供更多背景信息。
-
这不是上下文。您只是在解释您正在尝试做的任何事情的下一步。因此,如果我问您“为什么需要确定所有子进程”...? ;) 如果您甚至不知道父进程是否仍在运行,那么很难看出确定的父/子会实现什么。
-
@jalf:我试图在 GUI 中显示一个进程树(或者,可选地,进程树的一个子集)。如果这也不是上下文,则这是用于监视失控进程的应用程序的一部分。如果这还不够上下文,那么它适用于想要调试正在运行的进程的客户(这往往会跑掉,在这种情况下,他可能想要也可能不想杀死整个进程树,有点像 Process Explorer)。
-
无法判断一个进程是否由另一个特定进程创建。您所指的“th32ParentProcessId”字段实际上在内核EPROCESS结构中称为“InheritedFromUniqueProcessId”,它表示继承属性的进程。虽然大多数时候它确实表明了哪个进程创建了子进程,但这根本不能保证。