如何获取Windows中当前进程的所有子进程的句柄?

时间:2016-03-15 12:36:50

标签: c++ winapi time process children

为了在Windows操作系统上进行性能监视,我需要一个可以报告任意进程的用户和内核时间的程序。在POSIX系统上,标准time实用程序完全可以,因为它可以报告挂钟时间,用户时间和内核时间。

对于Windows,默认情况下没有此类实用程序。我环顾四周,发现至少有三种选择。正如我在下面解释的那样,它们都不适合我的需要。

    来自Windows SDK的
  1. timeit(无法回想起确切的版本)。它不再分布,支持或保证在现代系统上工作。我无法测试它。
  2. Cygwin的time。与具有类似输出格式的POSIX对应项几乎完全相同。
  3. John(John)Hart的
  4. timep.exe,可在source code和二进制文件中找到他的书“Windows System Programming,4th Edition”。这是一个非常简单的实用程序,它使用WinAPI的GetProcessTimes()来获取完全相同的三个值。我怀疑Cygwin的time在这方面没有什么不同。
  5. 现在问题是:GetProcessTimes()仅报告由timep直接生成的PID的时间,但不是其子项。这使得timetimep对我来说毫无用处。

    我的目标EXE应用程序通常是通过BAT文件生成的,该文件再调用一个BAT文件;两个BAT都用于调整环境或更改命令行参数:

    timep.exe
    |    
    +---wrapper.bat
                  |
                  +--- real-wrapper.bat
                                      |
                                      +--- application.exe
    

    单独wrapper.bat报告的时间对application.exe一无所知。 显然,POSIX(fork-exec)和Win32(CreateProcess)的进程创建模型非常不同,这使得我的目标很难在Windows上实现。

    我想尝试编写自己的time变体。它必须递归地总结给定过程及其所有孩子,孙子等的时间。到目前为止,我可以想象以下方法:

    1. CreateProcess()并获取其PID(根PID )并处理;将此句柄添加到列表
    2. 枚举系统中的所有进程;对于每个过程
      1. 将其PID与根PID进行比较。如果相等,则获取PID并处理它,将其添加到句柄列表中。
      2. 对于每个新PID,重复进程扫描阶段以收集更多子句柄
      3. 向下递归,直到没有新的进程句柄添加到列表
    3. 等待列表中所有收集的句柄终止。
    4. 对于每个句柄,请致电GetProcessTimes()并总结
    5. 报告结果
    6. 这个算法很糟糕,因为它很活泼 - 子进程可能在任何进程的生命后期创建,或者它们可以在我们有机会获得它们的句柄之前终止。在这两种情况下,报告的结果时间都是不正确的。

      我的问题是:有更好的解决方案吗?

      编辑:我可以使用Job Objects实现目标。下面是从我的应用程序中提取的代码片段,与从进程及其所有子进程获取内核和用户时间相关。希望它可以节省一些时间。

      我使用Windows 8.1 x64和VS 2015进行了测试,但它应该可以向后移植到至少Windows 7.对于{{1},32位主机(我不确定)可能需要一些小问题。 } types - 我不熟悉CL.EXE在这些平台上处理它们的方法。

      long long

2 个答案:

答案 0 :(得分:4)

是的,从timep.exe创建一个作业,然后使用job accounting。子进程(除非在自己的作业中创建)与其父进程共享作业。

这几乎会跳过你的步骤2-4

答案 1 :(得分:0)

我已将此问题的解决方案打包到一个名为chronos的Windows独立程序中。它创建一个作业对象,然后在其中生成一个请求的进程。之后产生的所有孩子都留在同一个工作对象中,因此可以在以后计算。