1. 程式人生 > >android系統之獲取CPU的使用率

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資料問題