最近需要做一个小功能获取Android设备的各种参数,包括内存、SD卡容量、CPU使用率等问题。发现其他几种都很好获得,有问题的是CPU的使用率。
android本质还是linux,因此可以用linux的方式获取某个进程的cpu使用率。
1.执行命令。
/** get CPU rate
* @return
*/
private int getProcessCpuRate() {
StringBuilder tv = new StringBuilder();
int rate = 0;
try {
String Result;
Process p;
p = Runtime.getRuntime().exec("top -n 1");
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((Result = br.readLine()) != null) {
if (Result.trim().length() < 1) {
continue;
} else {
String[] CPUusr = Result.split("%");
tv.append("USER:" + CPUusr[0] + "\n");
String[] CPUusage = CPUusr[0].split("User");
String[] SYSusage = CPUusr[1].split("System");
tv.append("CPU:" + CPUusage[1].trim() + " length:" + CPUusage[1].trim().length() + "\n");
tv.append("SYS:" + SYSusage[1].trim() + " length:" + SYSusage[1].trim().length() + "\n");
rate = Integer.parseInt(CPUusage[1].trim()) + Integer.parseInt(SYSusage[1].trim());
break;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(rate + "");
return rate;
}
2.读取文件。
在Linux/Unix下,CPU利用率分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。平时所说的CPU利用率是指:CPU执行非系统空闲进程的时间 / CPU总的执行时间。
在Linux的内核中,有一个全局变量:Jiffies。 Jiffies代表时间。它的单位随硬件平台的不同而不同。系统里定义了一个常数HZ,代表每秒种最小时间间隔的数目。这样jiffies的单位就是 1/HZ。Intel平台jiffies的单位是1/100秒,这就是系统所能分辨的最小时间间隔了。每个CPU时间片,Jiffies都要加1。 CPU的利用率就是用执行用户态+系统态的Jiffies除以总的Jifffies来表示。
proc文件系统
/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取/proc目录中的文件时,proc文件系统是动态从系统内核读出所需信息并提交的。
/proc目录中有一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程在/proc下都对应一个以进程号为目录名的目录/proc/pid,它们是读取进程信息的接口。此外,在Linux 2.6.0-test6以上的版本中/proc/pid目录中有一个task目录,/proc/pid/task目录中也有一些以该进程所拥有的线程的线程号命名的目录/proc/pid/task/tid,它们是读取线程信息的接口。
因此可以根据/proc/stat和/proc/pid/stat中的信息计算进程的cpu使用率。
/proc/stat文件
该文件包含了所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。不同内核版本中该文件的格式可能不大一致,以下通过实例来说明数据该文件中各字段的含义。
实例数据:
proc/stat结果
第一行的数值表示的是CPU总的使用情况,所以我们只要用第一行的数字计算就可以了。下表解析第一行各数值的含义:
参数
解析(单位:jiffies)
user (14624) 从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负进程。
nice (771) 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间
system (8484) 从系统启动开始累计到当前时刻,处于核心态的运行时间
idle (283052) 从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间
iowait (0) 从系统启动开始累计到当前时刻,IO等待时间(since 2.5.41)
irq (0) 从系统启动开始累计到当前时刻,硬中断时间(since 2.6.0-test4)
softirq (62) 从系统启动开始累计到当前时刻,软中断时间(since 2.6.0-test4)
结论1:总的cpu时间totalCpuTime = user + nice + system + idle + iowait + irq + softirq
/proc/pid/stat文件
该文件包含了某一进程所有的活动的信息,该文件中的所有值都是从系统启动开始累计
到当前时刻。以下通过实例数据来说明该文件中各字段的含义:
procpidstat
说明:以下只解释对我们计算Cpu使用率有用相关参数
参数
解析(单位:jiffies)
Pid(1327) 进程号
Utime(39) 该任务在用户态运行的时间,单位为jiffies
Stime(25) 该任务在核心态运行的时间,单位为jiffies
Cutime(0) 所有已死线程在用户态运行的时间,单位为jiffies
Cstime(0) 所有已死在核心态运行的时间,单位为jiffies
结论2:进程的总Cpu时间processCpuTime = utime + stime + cutime + cstime,该值包括其所有线程的cpu时间。
某一线程Cpu使用率的计算
计算方法:
1. 采样两个足够短的时间隔的cpu快照与线程快照,
a) 每一个cpu快照均为(user、nice、system、idle、iowait、irq、softirq、stealstealon、guest)的9元组;
b) 每一个线程快照均为 (utime、stime)的2元组;
2. 分别根据结论1、结论2计算出两个时刻的总的cpu时间与线程的cpu时间,分别记作:totalCpuTime1、totalCpuTime2、threadCpuTime1、threadCpuTime2
3. 计算该线程的cpu使用率pcpu = 100*( threadCpuTime2 – threadCpuTime1) / (totalCpuTime2 – totalCpuTime1) (按100%计算,如果是多核情况下还需乘以cpu的个数);
计算某个时间段内AppCpuTime与TotalCpuTime的变化,然后按照比例换算成该应用的Cpu使用率。
Android系统本省也有一个类是用来显示Cpu使用率的:
android/system/frameworks/base/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
阅读源码发现也是读取/proc目录下的文件来计算Cpu使用率。