通过汇编程序检测上下文切换的方法

3
我知道在Windows机器上,通过C#、Java等托管语言不能侦听、检测和执行与上下文切换相关的操作。但是,我想知道是否有办法使用汇编语言(或其他语言,例如C语言)来实现这一点?如果可以,请提供一个小代码片段,以便我了解如何实现它(因为我对内核编程还比较新手)。

这段代码的设计目的实质上是在标准的Windows UI后台运行,并监听特定进程何时从CPU中进行上下文切换。一旦听到任何一个动作,它将发送一个信号。澄清一下,我只想检测涉及特定进程的上下文切换,而不是任何上下文切换。我最终想要实现的是在特定进程开始使用CPU时通过互联网信号通知另一台机器,以及在它停止使用时也通知。

我首次尝试做到这一点的方法仅涉及计算特定进程的CPU使用百分比,但最终证明这太粗糙了,无法捕捉最微小的计算。例如,我编写了一个测试程序,它只是执行2 + 2的操作并将答案放入一个int中。 CPU使用方法没有检测到这一点。因此,我正在寻找更低级别的方法,这就是我提出这个问题的原因。如果有潜在的替代方案,我会很愿意考虑它们。


你需要提供更多关于你想要的信息。这段代码将在哪里运行,以及何时运行? - dkagedal
C++不是一种托管语言。 - japreiss
我现在已经解决了这两个问题。 - John Roberts
2
你应该意识到这些上下文切换可能每秒发生一千次...而发送信号本身就是一种上下文切换!这个信号应该做什么?你还没有描述你要解决的问题。 - Raymond Chen
正如我在问题中提到的,我只关注特定进程的上下文切换(当该进程被切换进或切换出时),而不是任意的上下文切换。我试图解决的问题是在进程被切换进时发送一个信号,然后在它被切换出时发送另一个信号,依此类推。 - John Roberts
显示剩余3条评论
2个回答

4

Windows事件跟踪(ETW),您可以配置它接收有关系统中发生的各种事件的消息。

您应该能够接收有关线程调度事件的消息。 CSwitch类 的事件就是为此而设计的。

抱歉,我不知道任何好的ETW示例,您可以轻松地重用它们来完成您的任务。 阅读MSDN并四处查找。

Simon 指出了一个很好的链接,解释了为什么ETW可能很有用。非常启发人:http://randomascii.wordpress.com/2012/05/11/the-lost-xperf-documentationcpu-scheduling/


1
Visual Studio 中的性能监视器可能会很有用,或者可以访问 http://msdn.microsoft.com/en-us/performance/cc825801.aspx。 - Simon

2
请查看下面的编辑。特别是第三点,ETW似乎是一条可行的途径。
理论上,您可以为旧的int 2Eh和新的sysenter安装自己的陷阱处理程序。然而,在实践中,由于Patchguard(自Vista以来)和签名要求,这将不再像以前那样容易。我不知道任何其他通用的方法来检测上下文切换,这意味着你必须自己动手。所有操作系统的上下文切换都经过调用门(前面提到的陷阱处理程序),如果您对调试/反汇编感到不舒服,ReactOS允许您窥视幕后。
但是,在任何情况下,没有一种通用的方法可以在没有内核模式权限(通常称为环形0)的情况下安装此类内容——其他任何内容都将成为Windows的安全漏洞。我也不知道有什么Windows提供的方法可以实现你想要的。
书籍“未记录的Windows NT”有一个非常好的章节,涵盖了确切的主题(尽管显然针对旧的int 2Eh方法)。
如果您只能接受挂钩某些函数,则可以使用某些过滤器驱动程序或用户模式API挂钩来解决问题。具体取决于您的确切要求。
更新:阅读您更新后的问题,我认为您需要了解内部工作原理,特别是IRQLs的概念(不要与DOS时代的IRQs混淆)和调度程序。问题在于每秒钟可能会有数百个上下文切换。然而,您的观察进程(观察上下文切换的进程)将像任何用户模式进程一样可以被抢占。这意味着您无法实现实时信号或接近它的任何方式,这对方法提出了一个大问题。
您实际上想要实现什么?上下文切换的数量并没有给您带来任何东西。每个单独的SEH异常都会导致上下文切换。你感兴趣的是什么?也许性能计数器更适合您的需求?
更新2:即使对于单个线程,每秒钟的上下文切换次数也会让人难以置信。因此,假设您安装了自己的陷阱处理程序,您仍将(不利地)影响系统上的所有其他线程(毕竟,您将捕获每个上下文切换,然后查看它是否是您关心的进程/线程,然后执行您的操作或将其传递)。
如果您能告诉我们您最终想要实现的内容,而不是使用已经预定义的方法,我们可能会建议替代方案。
更新3:因此,我在这里有一个错误。Windows内置了一些可以信号化上下文切换的东西。ETW可以被利用来挖掘这些内容。感谢Simon指出。

我只想关注一个特定进程的上下文切换,并且我不想计算它们 - 我想在它们发生时执行某些操作。这也会达到每秒数百次的数量级吗? - John Roberts
1
@JohnRoberts:是的,很可能仍然会有那个数量级。许多常见操作最终都会进入内核,无论是各种类型的注册表访问、文件访问还是对各种内核对象(如事件、互斥体和信号量)的访问。如果没有某种方式(自旋锁?)阻止其他所有操作,你不太可能在此类事件“之后”立即执行任何有意义的操作。 - 0xC0000022L
1
“int 2Eh”和相关内容并没有帮助,也不相关。它们仅用于系统调用,并且在抢占时不会被调用。这只是上下文切换的一个原因,而不是唯一的原因。正如Alexey Frunze所正确回答的那样,ETW才是解决问题的方法。 - Simon
1
@Simon:请告诉我在哪里我写到了抢占与int 2Eh有任何关系,我没有也不会这样做。然而,你是否能够及时地对通过自定义陷阱处理程序“感知”到的上下文切换做出反应,这与你的代码是否可以被抢占有关。请重新阅读我的回答。顺便说一句:我不知道ETW如何帮助。因为ETW始终需要一个提供你想要监听的事件的活动部分。虽然我不知道有没有用于上下文切换的活动部分。没有详细信息的情况下指向ETW是没有帮助的。 - 0xC0000022L
1
这里是ETW与上下文切换的关系:http://randomascii.wordpress.com/2012/05/11/the-lost-xperf-documentationcpu-scheduling/ - Simon
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接