在 UNIX 意义上(如果我没记错的话),系统负载是能够运行但实际上并未在 CPU 上运行的进程数(一段时间内的平均值)。top
例如,在过去的 1、5 和 15 分钟内显示此负载的实用程序。
我不相信这对于标准的 Win32 WMI进程类是可能的。(ExecutionState)
WMIWin32_Process
对象中的进程状态字段记录为未使用。
但是,线程类确实提供了该信息(并且它可能是一个更好的指标,因为现代操作系统倾向于调度线程而不是进程)。该类Win32_Thread
有一个ExecutionState
字段,该字段设置为以下之一:
- 0 未知
- 1 其他
- 2 准备就绪
- 3 跑步
- 4 被封锁
- 5 暂停封锁
- 6 暂停就绪
如果您要对该类进行查询并计算类型 2 的数量(可能还有类型 6;我认为在这种情况下挂起意味着换出),那应该会给您提供负载快照。然后,如果您想要平均值,则必须自己对它们进行平均。
或者,ThreadState
该类中也有一个:
- 0 已初始化(由微内核识别)。
- 1 就绪(准备在下一个可用处理器上运行)。
- 2 运行(执行)。
- 3 Standby(即将运行,一次可能只有一个线程处于此状态)。
- 4 终止(完成执行)。
- 5 等待(处理器没有准备好,准备好后会重新调度)。
- 6 过渡(等待处理器以外的资源)。
- 7 未知(状态未知)。所以你可以考虑计算状态 1 或 3 中的那些。
不要问我为什么有两个字段显示相似的信息或有什么区别。我早就不再用他们的 WMI 信息来猜测微软了,我只需要说服当权者我的选择是可行的 :-)
刚刚为我们自己的监控应用程序开发完一个 Windows 客户端后,我只建议进行 1 秒的快照,并在您需要报告的任何时间范围内对这些快照进行平均。即使每秒一个查询,VBScript 和 WMI 似乎也非常有弹性——它似乎不会占用太多的 CPU,而且只要你释放你使用的所有东西,你就可以运行更长的时间。
所以,每一秒,你都会做类似的事情(在 VBScript 中,并且从内存中,因为我没有准备好从这里访问代码):
set objWmi = GetObject("winmgmts:\\.\root\cimv2")
set threadList = objWmi.ExecQuery("select * from Win32_Thread",,48)
sysLoad = 0
for each objThread in threadList
if objThread.ThreadState = 1 or objThread.ThreadState = 3 then
sysLoad = sysLoad + 1
end if
next
' sysLoad now contains number of threads waiting for a CPU. '