如何在Windows上限制进程的CPU使用率? (需要代码,而不是应用程序)

有一些程序能够限制Windows中进程的CPU使用率。 例如BES和ThreadMaster 。 我需要编写自己的程序来完成与这些程序相同的function,但具有不同的configurationfunction。 有谁知道一个进程的CPU节stream是如何完成的(代码)? 我不是在谈论设置进程的优先级,而是如何将CPU使用率限制在例如15%,即使没有其他进程争夺CPU时间。

更新:我需要能够扼杀已经运行的任何进程,并且我没有源代码访问权限。

非常简化,它可以像这样工作:

  1. 用一些合理的等待时间(可能是100ms)创建一个定期的等待定时器。 通过调用一次GetProcessTimes获取每个相关进程的“最后”值。
  2. 永远循环,阻塞定时器。
  3. 每当你醒来:
    • 如果 GetProcessAffinityMask返回0,则调用SetProcessAffinityMask(old_value) 。 这意味着我们在上一次迭代中暂停了这个过程,现在让它有机会再次运行。
    • 否则调用GetProcessTimes来获取“当前”值
    • 调用GetSystemTimeAsFileTime
    • 通过从电流中减去最后一个来计算增量
    • cpu_usage = (deltacoreelTime + deltaUserTime) / (deltaTime)
    • 如果这比你想调用old_value = GetProcessAffinityMask其次是SetProcessAffinityMask(0) ,这将使进程脱机。

这基本上是在内核中运行的调度程序的一个非常原始的版本,在用户空间中实现。 如果使用的CPU时间超过了你认为正确的时间,那么它会让一个进程“休眠”一小段时间。 一个更复杂的测量可能会超过一秒或5秒是可能的(可能是可取的)。

您可能会试图暂停进程中的所有线程。 但是,重要的是不要摆脱优先级, 不要使用SuspendThread除非你确切地知道程序在做什么,因为这很容易导致死锁和其他令人讨厌的副作用。 想想举个例子,当另一个线程仍在运行时试图获取同一个对象,暂停一个保留临界区的线程。 或者想象一下,在暂停十几个线程的过程中,你的进程会被换掉,其中一半运行,另一半运行。

另一方面,将亲和性掩码设置为零意味着从现在起,进程中没有任何单个线程在任何处理器上获得更多的时间片。 重置亲和力在同一时间给出原子性 – 所有线程都有可能再次运行。

不幸的是,至少根据文档, SetProcessAffinityMask并不像SetThreadAffinityMask那样返回旧的掩码。 因此,额外的Get...调用是必要的。

您可能想要在作业对象中运行进程,并使用SetInformationJobObject设置作业对象的最大CPU使用率(使用JOBOBJECT_CPU_RATE_CONTROL_INFORMATION

使用QueryProcessCycleTime来估计CPU的使用相当简单。 机器的处理器速度可以从HKLM \ HARDWARE \ DESCRIPTION \ System \ CentralProcessor \\〜MHz(其中是处理器编号,每个处理器存在一个条目)获得。 使用这些值,您可以使用Sleep()来估计进程的CPU使用情况,并根据需要生成CPU,以保持使用范围。