android系統之獲取CPU的使用率
/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 = s2 - s1 ;
3、計算空閒時間idle
idle對應第四列的資料,用第二次的idle - 第一次的idle即可
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資料問題