1

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

提前感谢您的回答。

4

2 回答 2

2

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

他们在那里写道,如果您使用 C# 或 C++/CLI,您可以轻松地从类的实例中获取该信息System.Diagnostic.Process,并指向正确的 PID。但它会给你一个“漂亮的时间”而不是“周期” TimeSpanPrivilegedProcessorTime

但是,他们还指出,所有 .Net 代码实际上都是非托管 API 的瘦包装器,因此您也应该能够轻松地从本机 C++ 获取它。他们正在 ILDASM'ing 那个类以显示它所调用的内容,但图像丢失了。我刚刚做了同样的事情,它使用GetProcessTimesfromkernel32.dll

所以,再次,MSDN'ing it - 它返回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,也许您可​​以查看源是什么。我没有检查过。

于 2014-02-24T12:51:33.827 回答
1

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

于 2014-02-24T12:27:46.603 回答