如何使用C++在Linux中获取CPU总使用率

51

我正在尝试获取CPU总使用率的百分比。首先,我应该说明的是“top”命令不可行,因为它在CPU快照之间存在延迟,并且需要2个快照和几秒钟的时间,这会使我的程序停顿(我不想为此单独开启线程)。

接下来我尝试使用"ps"命令,虽然延迟很小,但总使用率始终非常高(20+),而当我实际让CPU执行任务时,它保持在大约20左右...

是否有其他方法可以获取总CPU使用率?无论是一秒钟还是更长的时间都没有关系... 不过更长的时间段会更有用。


忘了提一下:对我来说,top的延迟参数也是无用的... - David Polák
7个回答

107

cat /proc/stat

http://www.linuxhowtos.org/System/procstat.htm

我同意上面的答案。在这个文件中,cpu行给出了您的系统在不同类型的处理过程中花费的总“节拍数”。

您需要做的是对此文件进行2次读取,时间间隔可以根据您的需求确定。这些数字是增加的值(受整数回绕限制),因此要获取%cpu,您需要计算经过的节拍数与执行工作所花费的节拍数之比。

例如。假设在14:00:00时您有:

cpu 4698 591 262 8953 916 449 531

total_jiffies_1 = (所有值的总和)= 16400

work_jiffies_1 = (用户,好看,系统的前3个值的总和)= 5551

而在14:00:05时您有:

cpu 4739 591 289 9961 936 449 541

total_jiffies_2 = 17506

work_jiffies_2 = 5619

因此,在此期间的%cpu使用情况为:

work_over_period = work_jiffies_2 - work_jiffies_1 = 68

total_over_period = total_jiffies_2 - total_jiffies_1 = 1106

%cpu = work_over_period / total_over_period * 100 = 6.1%


1
这项技术类似但并非完全相同。 您可以从/proc/<pid>/stat文件中获取特定进程的数据(有关详细信息,请参见http://www.linuxhowtos.org/manpages/5/proc.htm)。CPU使用数据包含在utime和stime字段中,表示为时钟滴答数(而不是jiffies)。因此,您需要计算出在两次读取之间可用的时钟滴答数,通常可以通过使用sysconf找到时钟频率来近似计算。 - Hitobat
1
这个答案怎么样:https://dev59.com/n2ox5IYBdhLWcg3waziQ#9229580 它也使用了proc/stat,但不需要间隔。 - CMCDragonkai
@Hitobat 时钟滴答声和jiffy不是同一回事吗?所以我们应该可以像在/proc/stat中处理数据一样处理/proc/pid/stat中的数据,对吧?如果不行,我们该如何将时钟滴答声转换为jiffy或反之亦然呢? - pranavk
1
这段代码并不能给出正确的答案,输出结果与 top 命令的不同。你应该使用“空闲时间”(第四列)而不是前三个值,然后计算:(总时间差 - 空闲时间差)/ 总时间差。 - fa7eme
1
work_jiffies 不应该累加更多的值吗,比如 work_jiffies = user + nice + system + iowait + irq + softirq - scai
显示剩余2条评论

7

cpu-stat 是一个 C++ 项目,允许从 /proc/stat 读取 Linux CPU 计数器。

从 cpu-stat 的 src 目录获取 CPUData.* 和 CPUSnaphot.* 文件。

快速实现获取整体 CPU 使用率:

#include "CPUSnapshot.h"

#include <chrono>
#include <thread>
#include <iostream>

int main()
{
  CPUSnapshot previousSnap;
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  CPUSnapshot curSnap;
  
  const float ACTIVE_TIME = curSnap.GetActiveTimeTotal() - previousSnap.GetActiveTimeTotal();
  const float IDLE_TIME   = curSnap.GetIdleTimeTotal() - previousSnap.GetIdleTimeTotal();
  const float TOTAL_TIME  = ACTIVE_TIME + IDLE_TIME;
  int usage = 100.f * ACTIVE_TIME / TOTAL_TIME;
  std::cout << "total cpu usage: " << usage << " %" << std::endl;
}

进行编译:

g++ -std=c++11 -o CPUUsage main.cpp CPUSnapshot.cpp CPUData.cpp

1
嗨,我在我的程序中尝试了这一部分,它给出了66。你能解释一下这是什么意思吗?我的程序需要2秒钟才能完成执行,之后它给出了66,但我不知道那代表什么。所以请帮帮我。 - Aparajit Garg
这意味着你的 CPU 使用率在一秒钟内达到了 66%。 - souch
为什么不使用GetTotalTimeTotal()来获取总时间? - memory of a dream

6

那样不行...我需要一个实际的百分比。我不知道如何从那个计算出来。 - David Polák
2
这个答案是不对的,/proc/loadavg 中的数字也受到 I/O 的影响。 - scai

6
阅读/proc/cpuinfo以查找系统可用的CPU /核心数量。调用getloadavg()(或者可以阅读/proc/loadavg),取第一个值,将其乘以100(转换为百分比),再除以CPU /核心数。如果该值大于100,则将其截断为100。完成。
相关文档:man getloadavgman 5 proc 注意:负载平均值通常适用于*NIX系统,可能会超过100%(每个CPU /核心)。因为它实际上是测量准备由调度程序运行的进程数。使用类似Windows的CPU指标时,当负载达到100%时,您无法确定它是CPU资源的最佳使用还是系统超载了。在*NIX下,CPU loadavg的最佳使用将为您提供约1.0的值(双系统为2.0)。如果该值远大于CPU /核心数,则可能需要将额外的CPU插入到盒子中。
否则,请查看/proc文件系统。

有趣的是,我刚刚让计算机空闲了一分钟,使用 top 命令并设置 70 秒延迟。在那一分钟内,top 显示 95% 的空闲率。当我读取 loadavg 时,它显示了 0.20,这相当于使用率的 10%。但是,这种方法对我来说太不精确了。我最多只能容忍 1% 的误差... - David Polák
我有一个系统,其中平均负载值非常高。拿一个用例来看,上面建议的公式非常不准确:/proc/loadavg中的第一个负载数字为159.47->乘以->15900->除以8(核心,如/proc/stat中所报告的)给我一个负载为1987.5。你觉得将其简单截断为100合理吗?对我来说不是... :-)。这个问题更加复杂。/proc/loadavg中的负载数字取决于系统上的进程数量,并且似乎不堪重负的系统可以非常响应。看一下'collectl'命令行工具。 - Boaz Rymland
2
这个方法实际上可以为您提供每个CPU的处理器队列长度。尽管它是衡量整个系统负载的好方法,但它并不代表实际的CPU负载。例如,如果您的CPU执行大量的“iowait”,则当实际CPU使用率下降时,队列长度会增加。 - dtoux

1

这看起来更像是可行的...但每秒钟CPU的总容量是多少?我应该用CPU的时钟来计算吗?或者我怎么知道,比如说125的总增量转化为使用率是多少? - David Polák
@dav 计算经过的 CPU 时间,计算在用户/系统/任何模式下花费的时间,获取比率,例如 cpu_user/cpu_ticks。 - Anycorn

0

-2

看一下这个 C++ Lib

这些信息是从 /proc/stat 解析出来的。它还从 /proc/meminfo 解析内存使用情况,从 /proc/net/dev 解析以太网负载。

----------------------------------------------
current CPULoad:5.09119
average CPULoad 10.0671
Max     CPULoad 10.0822
Min     CPULoad 1.74111
CPU: : Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
----------------------------------------------
network load: wlp0s20f3 : 1.9kBit/s : 920Bit/s : 1.0kBit/s :  RX Bytes Startup: 15.8mByte TX Bytes Startup: 833.5mByte
----------------------------------------------
memory load: 28.4% maxmemory: 16133792 Kb used: 4581564 Kb  Memload of this Process 170408 KB
----------------------------------------------

2
无效链接。不是一个有效的答案。 - e-info128

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