如何获得进程在windows内核模式下使用的CPU时钟周期



正如标题所示,我对仅在内核模式下获取进程使用的CPU时钟周期感兴趣。我知道有一个名为"QueryProcessCycleTime"的API,它返回CPU时钟进程线程使用的循环。但是这个值包括在用户模式和内核模式下花费的周期。如何获取仅在内核模式下花费的周期?我需要使用性能计数器来获取它吗?如果是,我应该使用哪一个?

提前感谢您的回答。

我刚刚发现了一篇有趣的文章,它几乎描述了您的要求。它在MSDN Internal上。

他们在那里写道,如果您使用C#或C++/CLI,那么您可以很容易地从指向正确PID的System.Diagnostic.Process类的实例中获得该信息。但它会给你一个来自PrivilegedProcessorTimeTimeSpan,所以这是一个"美好的时间",而不是"周期"。

然而,他们也指出,所有这些.Net代码实际上都是非托管API的精简包装器,因此您也应该能够轻松地从本机C++中获得它。他们使用ILDASM来显示该类的调用,但是缺少图像。我刚刚做了同样的操作,它使用了kernel32.dll中的GetProcessTimes

因此,再次使用MSDN—它返回LPFILETIME结构。所以,"美好的时光",而不是"循环"。

该方法的描述指出,如果要获取时钟周期,则应使用QueryProcessCycleTime函数。这实际上返回了时钟周期的数量。。但是用户模式和内核模式一起计算。

现在,总结一下:

  • 您可以阅读userTIME
  • 你可以阅读kernelTIME
  • 您可以读取(用户+内核)CYCLES

所以你几乎拥有了所需的一切。通过一些简单的数学运算:

u_cycles = u_time * allcycles / (utime+ktime)
k_cycles = k_time * allcycles / (utime+ktime)

当然,由于四舍五入等原因,这将是一些近似值。

此外,这将有一个棘手的问题:您必须调用两个函数(GetTimes、QueryCycles)来获取所有信息,因此它们的读数之间会有一个轻微的延迟,因此您的所有计算可能会有一点滑动,因为目标进程仍在运行并消耗时间。

如果你不能在测量中考虑到这种(小?)噪声,我认为你可以通过暂时暂停过程来规避它:

  • 暂停目标
  • 请稍等,确保它已挂起
  • 读取第一个统计数据
  • 读取秒统计数据
  • 然后继续处理并计算值

我认为这将确保两个读数一致,但反过来,每个这样的读数都会影响测量过程的整体性能,也就是说,除非你对暂停所花费的时间进行一些更正,否则像"壁时间"这样的事情将无法再测量。。

也许有一些更好的方法可以获得单独的时钟周期,但我没有找到它们,对不起。你可以试着查看QueryProcessCycleTime的内部,以及它从哪个源读取数据——也许你很幸运,它读取A、B并返回A+B,也许你可以查看源是什么。我没有检查过。

查看GetProcessTimes。它将为您提供进程所使用的内核和用户时间。

最新更新