/proc/stat文件包含了所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。
k39tv1_bsp_1g:/ # cat /proc/stat
user nice system idle iowait irq softirq stealstolen guest
cpu 49158 1305 81855 141655 452 0 32 0 0 0
cpu0 13887 331 23478 30721 103 0 8 0 0 0
cpu1 14521 392 24319 29547 134 0 7 0 0 0
cpu2 11073 318 18701 38340 96 0 8 0 0 0
cpu3 9675 262 15355 43044 117 0 7 0 0 0
CPU的使用率的计算方法:
1、 采样两个足够短的时间间隔的Cpu快照,分别记作t1,t2,其中t1、t2的结构均为:
(user、nice、system、idle、iowait、irq、softirq、stealstolen、guest)的9元组;
2、 计算cpu时间片total
a) 把第一次的cpu使用情况求和,得到s1;
b) 把第二次的cpu使用情况求和,得到s2;
c) s2 - s1得到这个时间间隔内的所有时间片,即total = j2 - j1 ;
3、计算空闲时间idle
idle对应第四列的数据,用第二次的第四列 - 第一次的第四列即可
idle=第二次的第四列 - 第一次的第四列
6、计算cpu使用率
pcpu =100* (total-idle)/total
计算单个cpu的使用率
private static long cpu0_totalJiffies[] = new long[2];
public static long cpu1_totalJiffies[] = new long[2];
private static long cpu2_totalJiffies[] = new long[2];
private static long cpu3_totalJiffies[] = new long[2];
private static long cpu0_totalIdle[] = new long[2];
private static long cpu1_totalIdle[] = new long[2];
private static long cpu2_totalIdle[] = new long[2];
private static long cpu3_totalIdle[] = new long[2];
private static double cpu0_rate;
private static double cpu1_rate;
private static double cpu2_rate;
private static double cpu3_rate;
public static void getCPURateDesc(){
String path = "/proc/stat";// 系统CPU信息文件
//int firstCPUNum=0;//设置这个参数,这要是防止两次读取文件获知的CPU数量不同,导致不能计算。这里统一以第一次的CPU数量为基准
FileReader fileReader = null;
BufferedReader bufferedReader = null;
Pattern pattern= Pattern.compile(" [0-9]+");
for(int i=0;i<2;i++) {
cpu0_totalJiffies[i]=0;
cpu1_totalJiffies[i]=0;
cpu2_totalJiffies[i]=0;
cpu3_totalJiffies[i]=0;
cpu0_totalIdle[i]=0;
cpu1_totalIdle[i]=0;
cpu2_totalIdle[i]=0;
cpu3_totalIdle[i]=0;
try {
fileReader = new FileReader(path);
bufferedReader = new BufferedReader(fileReader, 8192);
String str;
while ((str = bufferedReader.readLine()) != null) {
if (str.toLowerCase().startsWith("cpu0")) {
int index = 0;
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
try {
long tempJiffies = Long.parseLong(matcher.group(0).trim());
cpu0_totalJiffies[i] += tempJiffies;
if (index == 3) {//空闲时间为该行第4条栏目
cpu0_totalIdle[i] += tempJiffies;
}
index++;
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
if (str.toLowerCase().startsWith("cpu1")) {
int index = 0;
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
try {
long tempJiffies = Long.parseLong(matcher.group(0).trim());
cpu1_totalJiffies[i] += tempJiffies;
if (index == 3) {//空闲时间为该行第4条栏目
cpu1_totalIdle[i] += tempJiffies;
}
index++;
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
if (str.toLowerCase().startsWith("cpu2")) {
int index = 0;
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
try {
long tempJiffies = Long.parseLong(matcher.group(0).trim());
cpu2_totalJiffies[i] += tempJiffies;
if (index == 3) {//空闲时间为该行第4条栏目
cpu2_totalIdle[i] += tempJiffies;
}
index++;
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
if (str.toLowerCase().startsWith("cpu3")) {
int index = 0;
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
try {
long tempJiffies = Long.parseLong(matcher.group(0).trim());
cpu3_totalJiffies[i] += tempJiffies;
if (index == 3) {//空闲时间为该行第4条栏目
cpu3_totalIdle[i] += tempJiffies;
}
index++;
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
if(i==0){
try {//暂停50毫秒,等待系统更新信息。
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
if (cpu0_totalJiffies[0]>0&&cpu0_totalJiffies[1]>0&&cpu0_totalJiffies[0]!=cpu0_totalJiffies[1]){
cpu0_rate=1.0*((cpu0_totalJiffies[1]-cpu0_totalIdle[1])-(cpu0_totalJiffies[0]-cpu0_totalIdle[0]))/(cpu0_totalJiffies[1]-cpu0_totalJiffies[0]);
}
if (cpu1_totalJiffies[0]>0&&cpu1_totalJiffies[1]>0&&cpu1_totalJiffies[0]!=cpu1_totalJiffies[1]){
cpu1_rate=1.0*((cpu1_totalJiffies[1]-cpu1_totalIdle[1])-(cpu1_totalJiffies[0]-cpu1_totalIdle[0]))/(cpu1_totalJiffies[1]-cpu1_totalJiffies[0]);
}
if (cpu2_totalJiffies[0]>0&&cpu2_totalJiffies[1]>0&&cpu2_totalJiffies[0]!=cpu2_totalJiffies[1]){
cpu2_rate=1.0*((cpu2_totalJiffies[1]-cpu2_totalIdle[1])-(cpu2_totalJiffies[0]-cpu2_totalIdle[0]))/(cpu2_totalJiffies[1]-cpu2_totalJiffies[0]);
}
if (cpu3_totalJiffies[0]>0&&cpu3_totalJiffies[1]>0&&cpu3_totalJiffies[0]!=cpu3_totalJiffies[1]){
cpu3_rate=1.0*((cpu3_totalJiffies[1]-cpu3_totalIdle[1])-(cpu3_totalJiffies[0]-cpu3_totalIdle[0]))/(cpu3_totalJiffies[1]-cpu3_totalJiffies[0]);
}
// return String.format("cpu:%.2f",rate);
Log.d("CpuUtils","zrx---- cpu0_rate:"+cpu0_rate+", cpu1_rate:"+cpu1_rate+", cpu2_rate:"+cpu2_rate+", cpu3_rate:"+cpu3_rate);
}
计算总的cpu使用率
public static String getCPURateDesc_All(){
String path = "/proc/stat";// 系统CPU信息文件
long totalJiffies[]=new long[2];
long totalIdle[]=new long[2];
int firstCPUNum=0;//设置这个参数,这要是防止两次读取文件获知的CPU数量不同,导致不能计算。这里统一以第一次的CPU数量为基准
FileReader fileReader = null;
BufferedReader bufferedReader = null;
Pattern pattern=Pattern.compile(" [0-9]+");
for(int i=0;i<2;i++) {
totalJiffies[i]=0;
totalIdle[i]=0;
try {
fileReader = new FileReader(path);
bufferedReader = new BufferedReader(fileReader, 8192);
int currentCPUNum=0;
String str;
while ((str = bufferedReader.readLine()) != null&&(i==0||currentCPUNum<firstCPUNum)) {
if (str.toLowerCase().startsWith("cpu")) {
currentCPUNum++;
int index = 0;
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
try {
long tempJiffies = Long.parseLong(matcher.group(0).trim());
totalJiffies[i] += tempJiffies;
if (index == 3) {//空闲时间为该行第4条栏目
totalIdle[i] += tempJiffies;
}
index++;
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
if(i==0){
firstCPUNum=currentCPUNum;
try {//暂停50毫秒,等待系统更新信息。
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
double rate=-1;
if (totalJiffies[0]>0&&totalJiffies[1]>0&&totalJiffies[0]!=totalJiffies[1]){
rate=1.0*((totalJiffies[1]-totalIdle[1])-(totalJiffies[0]-totalIdle[0]))/(totalJiffies[1]-totalJiffies[0]);
}
Log.d("CpuUtils","zrx---- cpu_rate:"+rate);
return String.format("cpu:%.2f",rate);
}
读取/proc/stat会报permission denied,查看avc log日志,获取如下log:
a.myapplication: type=1400 audit(0.0:1326): avc: denied { read } for name=”stat” dev=”proc” ino=4026532069 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:proc_stat:s0 tclass=file permissive=0
a.myapplication: type=1400 audit(0.0:2164): avc: denied { open } for path=”/proc/stat” dev=”proc” ino=4026532069 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:proc_stat:s0 tclass=file permissive=0
a.myapplication: type=1400 audit(0.0:22): avc: denied { getattr } for path=”/proc/stat” dev=”proc” ino=4026532069 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:proc_stat:s0 tclass=file permissive=0
根据上面log,需要添加sepolicy权限才能读/proc/stat数据,在untrusted_app.te文件中添加allow untrusted_app proc_stat:file { read open getattr };解决不能读取/proc/stat数据问题