我正在开发一个 Android 应用程序,显示每个核心的 CPU 负载和内存消耗。对于 CPU 负载,我正在读取 /proc/stat,对于内存 -> /proc/meminfo。 但是我看到 /proc/stat 中的 CPU 核心数在后续读取文件期间发生了变化。
cpu 230599 10622 84595 1892023 8236 16 285 0 0 0
cpu0 138005 7992 58080 1738918 6407 16 278 0 0 0
intr 9136791 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9601 0 0 0 0 0 0 .......
ctxt 16904510
btime 1394641996
processes 16919
procs_running 2
procs_blocked 0
softirq 1688530 407 706934 422 1558 407 407 92978 324500 1267 559650
5秒后变成:
cpu 230772 10623 84671 1890801 8236 16 286 0 0 0
cpu0 138104 7993 58126 1739267 6407 16 279 0 0 0
cpu1 92668 2630 26545 151534 1829 0 7 0 0 0
intr 9144729 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9601 0 0 0 0 0 0 ........
ctxt 16923744
btime 1394641996
processes 16946
procs_running 2
procs_blocked 0
softirq 1690205 407 707396 422 1558 407 407 93311 324790 1267 560240
这是否意味着CPU核心在某些情况下正在休眠?
我知道这很旧,但似乎没有答案,我也一直在寻找解决方案。
我想的是,如果我记录每个名为“cpu”的核心,后面跟着一个数字。 cpu从0到3。如果我按顺序阅读核心。然后,如果 /proc/stat 的 .readline() 返回一个不包含 cpu 的字符串,则该核心一定没有工作,并且处于离线状态。因此,从理论上讲,其使用率为零。所以,返回 0。
*** 已完成答案并附有代码,请参阅下文 ***
这是一些代码,以防我说的没有意义,我的代码是基于此的: 获取 Android 中的内存使用情况
以下是我如何找到一种新的计算方法,可以更准确地表示核心读数:如何使用 C++ 获取 Linux 中的总 cpu 使用率
首先,这是我的一些 CPU 函数,它在这些循环之后向用户显示一个字符串和内容。我发布此内容是为了让您更好地理解 i 以及我的代码的含义
float[] coreValues = new float[10];
//get how many cores there are from function
int numCores = getNumCores();
for(byte i = 0; i < numCores; i++)
{
coreValues[i] = readCore(i);
}
getNumCores
可以在这里找到,我不会发帖,因为我觉得发帖的人应该得到它的荣誉:How can you detector a Dual-core cpu on an Android device from code?
最后,这是我的代码,我希望它有意义,并且我提供了很多评论。
//for multi core value
private float readCore(int i)
{
/*
* how to calculate multicore
* this function reads the bytes from a logging file in the android system (/proc/stat for cpu values)
* then puts the line into a string
* then spilts up each individual part into an array
* then(since he know which part represents what) we are able to determine each cpu total and work
* then combine it together to get a single float for overall cpu usage
*/
try {
RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
//skip to the line we need
for(int ii = 0; ii < i + 1; ++ii)
{
reader.readLine();
}
String load = reader.readLine();
//cores will eventually go offline, and if it does, then it is at 0% because it is not being
//used. so we need to do check if the line we got contains cpu, if not, then this core = 0
if(load.contains("cpu"))
{
String[] toks = load.split(" ");
//we are recording the work being used by the user and system(work) and the total info
//of cpu stuff (total)
//https://stackoverflow.com/questions/3017162/how-to-get-total-cpu-usage-in-linux-c/3017438#3017438
long work1 = Long.parseLong(toks[1])+ Long.parseLong(toks[2]) + Long.parseLong(toks[3]);
long total1 = Long.parseLong(toks[1])+ Long.parseLong(toks[2]) + Long.parseLong(toks[3]) +
Long.parseLong(toks[4]) + Long.parseLong(toks[5])
+ Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
try
{
//short sleep time = less accurate. But android devices typically don't have more than
//4 cores, and I'n my app, I run this all in a second. So, I need it a bit shorter
Thread.sleep(200);
}
catch (Exception e) {}
reader.seek(0);
//skip to the line we need
for(int ii = 0; ii < i + 1; ++ii)
{
reader.readLine();
}
load = reader.readLine();
//cores will eventually go offline, and if it does, then it is at 0% because it is not being
//used. so we need to do check if the line we got contains cpu, if not, then this core = 0%
if(load.contains("cpu"))
{
reader.close();
toks = load.split(" ");
long work2 = Long.parseLong(toks[1])+ Long.parseLong(toks[2]) + Long.parseLong(toks[3]);
long total2 = Long.parseLong(toks[1])+ Long.parseLong(toks[2]) + Long.parseLong(toks[3]) +
Long.parseLong(toks[4]) + Long.parseLong(toks[5])
+ Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
//here we find the change in user work and total info, and divide by one another to get our total
//seems to be accurate need to test on quad core
//https://stackoverflow.com/questions/3017162/how-to-get-total-cpu-usage-in-linux-c/3017438#3017438
return (float)(work2 - work1) / ((total2 - total1));
}
else
{
reader.close();
return 0;
}
}
else
{
reader.close();
return 0;
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
return 0;
}
最后一点,我的
readCore
函数将返回 0.0 - 1.0 的值,您需要乘以 100 才能得到百分比。
编辑 正如下面评论中所要求的,Android 文档:“当处于活动状态时,CPU 可以联机或脱机,更改时钟速度和相关电压(可能还会影响内存总线速度和其他系统核心电源状态),并且可以进入较低功耗空闲状态在内核空闲循环中的状态不仅是为了电源配置文件而测量的,而且在测量其他参数时可能有必要避免功耗变化。”
即使接受的答案是在问题提出几个月后才给出的,这对我来说也非常有用。
希望我的建议对将来阅读这个问题的其他人有用。
@Torch2424 的答案非常好,但缺少检查:正如您所说,有时 Android 不会使用所有 CPU;我在 4 核平板电脑上尝试了您的代码,实际上我发现大多数时候 2 个 CPU 根本不使用或不经常更改,因此 /proc/stat 文件的相对行是完全相同的。这意味着
(total2 - total1)
等于 0,然后你尝试除以 0,结果为 NaN。// for multi core value
private float readCore(int i) {
/*
* how to calculate multicore this function reads the bytes from a
* logging file in the android system (/proc/stat for cpu values) then
* puts the line into a string then spilts up each individual part into
* an array then(since he know which part represents what) we are able
* to determine each cpu total and work then combine it together to get
* a single float for overall cpu usage
*/
try {
RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
// skip to the line we need
for (int ii = 0; ii < i + 1; ++ii) {
String line = reader.readLine();
}
String load = reader.readLine();
// cores will eventually go offline, and if it does, then it is at
// 0% because it is not being
// used. so we need to do check if the line we got contains cpu, if
// not, then this core = 0
if (load.contains("cpu")) {
String[] toks = load.split(" ");
// we are recording the work being used by the user and
// system(work) and the total info
// of cpu stuff (total)
// http://stackoverflow.com/questions/3017162/how-to-get-total-cpu-usage-in-linux-c/3017438#3017438
long work1 = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
+ Long.parseLong(toks[3]);
long total1 = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
+ Long.parseLong(toks[3]) + Long.parseLong(toks[4])
+ Long.parseLong(toks[5]) + Long.parseLong(toks[6])
+ Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
try {
// short sleep time = less accurate. But android devices
// typically don't have more than
// 4 cores, and I'n my app, I run this all in a second. So,
// I need it a bit shorter
Thread.sleep(300);
} catch (Exception e) {
}
reader.seek(0);
// skip to the line we need
for (int ii = 0; ii < i + 1; ++ii) {
reader.readLine();
}
load = reader.readLine();
// cores will eventually go offline, and if it does, then it is
// at 0% because it is not being
// used. so we need to do check if the line we got contains cpu,
// if not, then this core = 0%
if (load.contains("cpu")) {
reader.close();
toks = load.split(" ");
long work2 = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
+ Long.parseLong(toks[3]);
long total2 = Long.parseLong(toks[1]) + Long.parseLong(toks[2])
+ Long.parseLong(toks[3]) + Long.parseLong(toks[4])
+ Long.parseLong(toks[5]) + Long.parseLong(toks[6])
+ Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
// here we find the change in user work and total info, and
// divide by one another to get our total
// seems to be accurate need to test on quad core
// http://stackoverflow.com/questions/3017162/how-to-get-total-cpu-usage-in-linux-c/3017438#3017438
if ((total2 - total1) == 0)
return 0;
else
return (float) (work2 - work1) / ((total2 - total1));
} else {
reader.close();
return 0;
}
} else {
reader.close();
return 0;
}
} catch (IOException ex) {
ex.printStackTrace();
}
return 0;
}
希望有帮助!
我日日夜夜都在寻找如何从 android 获取
CPU
的使用,有时我会遇到这个问题。
好吧,如果我没记错的话,我认为当你没有获得
CPU
核心时,意味着未显示的核心处于离线状态(Android 这样做是为了防止大量电池消耗)。
如果你想知道 Android 有多少个核心,可以找到另一种方法,那里有太多的方法,然后做你喜欢做的事。
我希望它对你有用......
public static float cpuTemperature() {
Process process;
try {
process = Runtime.getRuntime().exec("cat sys/class/thermal/thermal_zone0/temp");
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = reader.readLine();
if (line != null) {
float temp = Float.parseFloat(line);
return temp / 1000.0f;
} else {
return 45.0f;
}
} catch (Exception e) {
e.printStackTrace();
return 0.0f;
}
}