cpu使用率-在/proc/stat中报告的Android cpu内核



我正在开发一个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的内存使用情况

,下面是我如何找到一个新的计算方法,使我更准确地表示核心读数:如何获得Linux (c++)中的总cpu使用情况

首先,这是我的一些CPU函数,它在这些循环之后向用户显示一个字符串。我发布这篇文章是为了让你更好地理解我,以及我的代码意味着什么

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可以在这里找到,我不会张贴,因为我觉得这样做的人应该得到它的信用:你怎么能从代码检测Android设备上的双核cpu ?

最后,这是我的代码,我希望它是有意义的,我提供了很多注释。

//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处于活动状态时,可以在线或离线,改变时钟速度和相关电压(可能也会影响内存总线速度和其他系统核心电源状态),并且可以在内核空闲循环中进入低功耗空闲状态。"在测量其他参数时,不仅需要测量这些不同的CPU功率状态,还可能需要避免功耗差异。"

链接:https://source.android.com/devices/tech/power.html

@Torch2424和@Andre的回答还可以,但对我来说,他们缺少了一些东西:

  • 我不想在两个民意调查之间放一个睡眠。我更喜欢从上次函数调用后得到CPU使用情况,并决定何时调用cpuusage函数。
  • 我认为有一个bug在如何计算核心的使用:当一个核心离线时,它并不总是分配核心结果到前一个核心数组的正确位置。
  • 我需要一个返回全局CPU使用情况的函数。

这里是代码,希望正确地修复这一点:可用作为一个类或作为一个简单的应用程序。

即使接受的答案是在问题几个月后给出的,它对我来说非常有用。希望我的建议对将来读到这个问题的人有用。@Torch2424的回答非常好,但缺少一个检查:正如你所说,有时Android不会使用所有的cpu;我在4核平板电脑上尝试了你的代码,确实我看到大多数时候2个cpu根本不使用或不经常改变,因此/proc/stat文件的相对行是完全相同的。这意味着(total2 - total1)等于0,然后尝试除以0,其结果是NaN。
这实际上是我的readCore()函数的工作代码:

// 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;
    }
}

最新更新