博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android中获取CPU负载和进程cpu时间
阅读量:6903 次
发布时间:2019-06-27

本文共 9214 字,大约阅读时间需要 30 分钟。

hot3.png

        android系统中有一个ProcessStats类,我们可以使用它来获取系统的负载情况及进程时间。

        实现原理是读取/proc目录下的文件。linux系统运行时,内核会去更新 /proc目录下的文件,将PID的运行情况写入相应的文件中。我们主要关注以下文件

1. /proc/stat

该文件包含了从系统启动开始累积到当前时刻的CPU活动信息。

看下我手机的情况,如下

cat /proc/stat

cpu  14869 5121 19794 156065 3114 0 26 0 0 0 

cpu0 10268 4823 15912 84682 2800 0 23 0 0 0

intr 8830975 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5926 0 0 0 0 0 0 0 0 0 0 0 0 0 0 84406

0 0 0 0 0 0 0 0 0 0 13205 0 2195 0 0 0 0 2 2 0 4304 0 1 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 1570 0 321 0 7132798 0 3638 21 0 0 1 0 0 0 134 0 0 0 0 0 0 0

 0 0 0 0 715 835 0 0 168670 0 0 0 0 0 0 0 0 0 0 0 0 0 2124 28527 0 0 200 0 0 0 0

 4823 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

ctxt 15331839

btime 1423869515

processes 2813

procs_running 3

procs_blocked 1

softirq 135522 11 57942 11 3386 11 11 8212 5725 54 60159

cpu的每一列的意思如下

user (14869 ) 从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies) ,不包含 nice值为负进程。1jiffies=0.01秒

nice (5121 ) 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
system (19794 ) 从系统启动开始累计到当前时刻,核心时间(单位:jiffies)
idle (156065 ) 从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)
iowait (3114 ) 从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies) ,
irq (0) 从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies)
softirq (26) 从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)

后三个android没有读取,估计没用。

手机是单核从,所以只有cup0,含义和上面一样

其他的如下:

“intr”这行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。

“ctxt”给出了自系统启动以来CPU发生的上下文交换的次数。
“btime”给出了从系统启动到现在为止的时间,单位为秒。
“processes (total_forks) 自系统启动以来所创建的任务的个数目。
“procs_running”:当前运行队列的任务的数目。
“procs_blocked”:当前被阻塞的任务的数目。

2./proc/loadavg

系统平均负载.该文件中的所有值都是从系统启动开始累计到当前时刻。该文件只给出了所有CPU的集合信息,不能该出每个CPU的信息。

我手机中如下:

cat /proc/loadavg

10.78 9.55 7.20 5/818 3719

每个值的含义为:

参数 解释
lavg_1 (10.78) 1-分钟平均负载
lavg_5 (9.55) 5-分钟平均负载
lavg_15(7.20) 15-分钟平均负载
nr_running (5) 在采样时刻,运行队列的任务的数目,与/proc/stat的procs_running表示相同意思
nr_threads (818) 在采样时刻,系统中活跃的任务的个数(不包括运行已经结束的任务)
last_pid(3719) 最大的pid值,包括轻量级进程,即线程。

3.进程信息

以PID作为文件夹名。

例如进程2411的stat如下

cat /proc/2411/stat

2411 (loop43) S 2 0 0 0 -1 2129984 0 0 0 0 0 150 0 0 0 -20 1 0 7794 0 0 42949672

95 0 0 0 0 0 0 0 2147483647 0 4294967295 0 0 17 2 0 0 0 0 0 0 0 0

每一项的含义可以看

有了以上的基础,我们就可以看ProcessStats这个类了。

update()函数读取上面所提的信息。

    public void update() {        ......        // 读取/proc/stat中的cpu时间        if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT,                null, sysCpu, null)) {            // Total user time is user + nice time.            final long usertime = sysCpu[0]+sysCpu[1];            // Total system time is simply system time.            final long systemtime = sysCpu[2];            // Total idle time is simply idle time.            final long idletime = sysCpu[3];            // Total irq time is iowait + irq + softirq time.            final long iowaittime = sysCpu[4];            final long irqtime = sysCpu[5];            final long softirqtime = sysCpu[6];             mRelUserTime = (int)(usertime - mBaseUserTime);            mRelSystemTime = (int)(systemtime - mBaseSystemTime);            mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);            mRelIrqTime = (int)(irqtime - mBaseIrqTime);            mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);            mRelIdleTime = (int)(idletime - mBaseIdleTime);             if (DEBUG) {                Slog.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]                      + " S:" + sysCpu[2] + " I:" + sysCpu[3]                      + " W:" + sysCpu[4] + " Q:" + sysCpu[5]                      + " O:" + sysCpu[6]);                Slog.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime                      + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);            }             mBaseUserTime = usertime;            mBaseSystemTime = systemtime;            mBaseIoWaitTime = iowaittime;            mBaseIrqTime = irqtime;            mBaseSoftIrqTime = softirqtime;            mBaseIdleTime = idletime;        }         // 读取所有/proc/[pid]/文件夹中的进行信息        mCurPids = collectStats("/proc", -1, mFirst, mCurPids, mProcStats);         // 读取/proc/loadavg中的平均负载        final float[] loadAverages = mLoadAverageData;        if (Process.readProcFile("/proc/loadavg", LOAD_AVERAGE_FORMAT,                null, null, loadAverages)) {            float load1 = loadAverages[0];            float load5 = loadAverages[1];            float load15 = loadAverages[2];            if (load1 != mLoad1 || load5 != mLoad5 || load15 != mLoad15) {                mLoad1 = load1;                mLoad5 = load5;                mLoad15 = load15;                onLoadChanged(load1, load5, load15);            }        }         if (DEBUG) Slog.i(TAG, "*** TIME TO COLLECT STATS: "                + (SystemClock.uptimeMillis()-mCurrentSampleTime));         mWorkingProcsSorted = false;        mFirst = false;    }

再来看下读取进行信息的函数

    private int[] collectStats(String statsFile, int parentPid, boolean first,            int[] curPids, ArrayList
 allProcs) {        //获取全部PID        int[] pids = Process.getPids(statsFile, curPids);        int NP = (pids == null) ? 0 : pids.length;        int NS = allProcs.size();        int curStatsIndex = 0;        //迭代PID,创建或更新PID对应的Stats对象        for (int i=0; i
< 0) {                NP = pid;                break;            }            Stats st = curStatsIndex < NS ? allProcs.get(curStatsIndex) : null;             // Stats对象已经存在,更新            if (st != null && st.pid == pid) {                // Update an existing process...                st.added = false;                st.working = false;                curStatsIndex++;                if (DEBUG) Slog.v(TAG, "Existing "                        + (parentPid < 0 ? "process" : "thread")                        + " pid " + pid + ": " + st);                 if (st.interesting) {                    final long uptime = SystemClock.uptimeMillis();                     final long[] procStats = mProcessStatsData;                    // 读取/proc/[pid]/stat文件中的信息至procStats                    if (!Process.readProcFile(st.statFile.toString(),                            PROCESS_STATS_FORMAT, null, procStats, null)) {                        continue;                    }                                         final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS];                    final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS];                    final long utime = procStats[PROCESS_STAT_UTIME];                    final long stime = procStats[PROCESS_STAT_STIME];                     // cpu用户时间系统时间没变化,设置Stats的active为false                    if (utime == st.base_utime && stime == st.base_stime) {                        st.rel_utime = 0;                        st.rel_stime = 0;                        st.rel_minfaults = 0;                        st.rel_majfaults = 0;                        if (st.active) {                            st.active = false;                        }                        continue;                    }                     if (!st.active) {                        st.active = true;                    }                     if (parentPid < 0) {                        // 从/proc/[pid]/cmdline中读取进程名                        getName(st, st.cmdlineFile);                        if (st.threadStats != null) {                            // 如果需要读取线程信息,怎从/proc/[pid]/task/中读取全部线程的信息                            mCurThreadPids = collectStats(st.threadsDir, pid, false,                                    mCurThreadPids, st.threadStats);                        }                    }                     if (DEBUG) Slog.v("Load", "Stats changed " + st.name + " pid=" + st.pid                            + " utime=" + utime + "-" + st.base_utime                            + " stime=" + stime + "-" + st.base_stime                            + " minfaults=" + minfaults + "-" + st.base_minfaults                            + " majfaults=" + majfaults + "-" + st.base_majfaults);                     // 设置Stats的值                    st.rel_uptime = uptime - st.base_uptime;                    st.base_uptime = uptime;                    st.rel_utime = (int)(utime - st.base_utime);                    st.rel_stime = (int)(stime - st.base_stime);                    st.base_utime = utime;                    st.base_stime = stime;                    st.rel_minfaults = (int)(minfaults - st.base_minfaults);                    st.rel_majfaults = (int)(majfaults - st.base_majfaults);                    st.base_minfaults = minfaults;                    st.base_majfaults = majfaults;                    st.working = true;                }                 continue;            }             // Stats对象不存在,创建            if (st == null || st.pid > pid) {                ......                // 创建的流程和更新差不多                continue;            }                             ......            continue;        }         ......                 return pids;    }

我们可以很方便的使用这个类,来进行cpu负荷和进程时间的监控。Android系统在SystemUI中有一个服务,就使用了这个类。

我们看SystemUI的Manifest文件,可以找到一个叫LoadAverageService的服务,它就是使用了ProcessStats获取cpu和进程信息,并把他们显示出来。

最后,在看下如何使用LoadAverageService这个服务

可以在adb shell中直接运行am startservice -n com.android.systemui/.LoadAverageService

或者用【设置】->【开发者选项】->【显示cpu使用情况】打开服务

我们在开发应用的时候,可以开启这个选项,时时跟踪系统的cpu占用情况,真的是很方便啊!!!

转载于:https://my.oschina.net/u/262208/blog/378660

你可能感兴趣的文章
【转载】Cookie/Session机制详解
查看>>
ASCII码、Unicode码 转中文
查看>>
java 不通过第三个字符串,实现一个字符串倒序
查看>>
map/reduce
查看>>
矩阵的相似对角化
查看>>
weixinJSDDK
查看>>
eclipse手动安装svn和maven
查看>>
权限管理 (二) 实现中几个问题
查看>>
安家博客园-准备迁移过往博客-发帖提醒自己-别偷懒别偷懒别偷懒!
查看>>
密码学经典之生日悖论与生日攻击【详解】
查看>>
算法题丨3Sum
查看>>
Android学习笔记33:Intent介绍及Intent在Activity中的使用方法
查看>>
java常用类--与用户互动
查看>>
day40-python多进程多线程-多线程实例和锁
查看>>
关于使用pip安装软件的存储库的问题-python
查看>>
Android Material Design-Getting Started(入门)-(一)
查看>>
CHIL-ORACLE-truncate 语法 清空表数据
查看>>
IE和FireFox下的JS调试工具
查看>>
2018全球最强物联网公司榜单揭晓
查看>>
docker的安装和docket拉取Oracle
查看>>