Linux下沒有直接可以調用系統函數知道CPU占用和內存占用。那么如何知道CPU和內存信息呢。只有通過proc偽文件系統來實現。
proc偽文件就不介紹了,只說其中4個文件。一個是/proc/stat,/proc/meminfo,/proc/<pid>/status,/proc/<pid>/stat
摘自:http://www.blogjava.net/fjzag/articles/317773.html
/proc/stat:存放系統的CPU時間信息
該文件包含了所有CPU活動的信息,該文件中的所有值都是從系統啟動開始累計到當前時刻。不同內核版本中該文件的格式可能不大一致,以下通過實例來說明數據該文件中各字段的含義。
實例數據:2.6.24-24版本上的
fjzag@fjzag-desktop:~$ cat /proc/stat
cpu 38082 627 27594 893908 12256 581 895 0 0
cpu0 22880 472 16855 430287 10617 576 661 0 0
cpu1 15202 154 10739 463620 1639 4 234 0 0
intr 120053 222 2686 0 1 1 0 5 0 3 0 0 0 47302 0 0 34194 29775 0 5019 845 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 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 1434984
btime 1252028243
processes 8113
procs_running 1
procs_blocked 0
第一行的數值表示的是CPU總的使用情況,所以我們只要用第一行的數字計算就可以了。下表解析第一行各數值的含義:
參數 解析(單位:jiffies)
(jiffies是內核中的一個全局變量,用來記錄自系統啟動一來產生的節拍數,在linux中,一個節拍大致可理解為操作系統進程調度的最小時間片,不同linux內核可能值有不同,通常在1ms到10ms之間)
user (38082) 從系統啟動開始累計到當前時刻,處於用戶態的運行時間,不包含 nice值為負進程。
nice (627) 從系統啟動開始累計到當前時刻,nice值為負的進程所占用的CPU時間
system (27594) 從系統啟動開始累計到當前時刻,處於核心態的運行時間
idle (893908) 從系統啟動開始累計到當前時刻,除IO等待時間以外的其它等待時間iowait (12256) 從系統啟動開始累計到當前時刻,IO等待時間(since 2.5.41)
irq (581) 從系統啟動開始累計到當前時刻,硬中斷時間(since 2.6.0-test4)
softirq (895) 從系統啟動開始累計到當前時刻,軟中斷時間(since 2.6.0-test4)stealstolen(0) which is the time spent in other operating systems when running in a virtualized environment(since 2.6.11)
guest(0) which is the time spent running a virtual CPU for guest operating systems under the control of the Linux kernel(since 2.6.24)
結論2:總的cpu時間totalCpuTime = user + nice + system + idle + iowait + irq + softirq + stealstolen + guest
可以利用scanf,sscanf,fscanf讀取這些信息,具體可以查man proc.我的程序中只取了前4個。
/proc/meminfo:存放系統的內存信息
[ubuntu@root ~]#cat /proc/meminfo
MemTotal: 2061616 kB
MemFree: 1093608 kB
Buffers: 151140 kB
Cached: 479372 kB
SwapCached: 0 kB
Active: 516964 kB
Inactive: 374672 kB
Active(anon): 261412 kB
Inactive(anon): 5604 kB
Active(file): 255552 kB
Inactive(file): 369068 kB
……
別的就不說了,主要看第一個MemTotal,系統總的物理內存,它比真實的物理內存要小一點
/proc/<pid>/status:存放進程的CPU時間信息以及一些綜合信息
[ubuntu@root ~]#cat /proc/889/status
Name: Xorg
State: S (sleeping)
Tgid: 889
Pid: 889
PPid: 881
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 256
Groups:
VmPeak: 99036 kB
VmSize: 52424 kB
VmLck: 0 kB
VmHWM: 57004 kB
VmRSS: 45508 kB
VmData: 35668 kB
VmStk: 136 kB
VmExe: 1660 kB
VmLib: 6848 kB
VmPTE: 120 kB
VmPeak是占用虛擬內存的峰值,也就是最高的一個值,而且是虛擬內存,所以有時候會比物理內存要大。PS和TOP指令都是利用VmPeak計算內存占用的。
VmRSS是進程所占用的實際物理內存。
/proc/<pid>/stat:保存着進程的CPU信息。
[ubuntu@root ~]#cat /proc/889/stat
889 (Xorg) S 881 889 889 1031 889 4202752 5307477 0 0 0 34943 12605 0 0 20 0 1 0 8146 89399296 11377 4294967295 134512640 136211844 3221201472 3221200460 5456930 0 0 3149824 1367369423 3223423286 0 0 17 0 0 0 0 0 0
pid=889 進程號
utime=34943 該任務在用戶態運行的時間,單位為jiffies
stime=12605 該任務在核心態運行的時間,單位為jiffies
cutime=0 所有已死線程在用戶態運行的時間,單位為jiffies
cstime=0 所有已死在核心態運行的時間,單位為jiffies
可以利用scanf,sscanf,fscanf讀取這些信息,具體可以查man proc.
結論3:進程的總Cpu時間processCpuTime = utime + stime + cutime + cstime,該值包括其所有線程的cpu時間。
以上這些數據都可以通過文件讀取的方式,可以按照一行一行的讀取,然后采用scanf,sscanf,fscanf獲取信息。
占用內存的計算方法:
pmem = VmRSS / MemTotal * 100;
計算CPU占用的方法:
取一次processCpuTime1和totalCpuTime1;
間隔一段時間;
再取一次processCpuTime2和totalCpuTime2;
pcpu = 100 * (processCpuTime2 – processCpuTime1)/(totalCpuTime2 - totalCpuTime1);
代碼
1 get_cpu.h 2 3 #ifdef __cplusplus 4 extern "C"{ 5 #endif 6 7 #define VMRSS_LINE 15//VMRSS所在行 8 #define PROCESS_ITEM 14//進程CPU時間開始的項數 9 10 typedef struct //聲明一個occupy的結構體 11 { 12 unsigned int user; //從系統啟動開始累計到當前時刻,處於用戶態的運行時間,不包含 nice值為負進程。 13 unsigned int nice; //從系統啟動開始累計到當前時刻,nice值為負的進程所占用的CPU時間 14 unsigned int system;//從系統啟動開始累計到當前時刻,處於核心態的運行時間 15 unsigned int idle; //從系統啟動開始累計到當前時刻,除IO等待時間以外的其它等待時間iowait (12256) 從系統啟動開始累計到當前時刻,IO等待時間(since 2.5.41) 16 }total_cpu_occupy_t; 17 18 typedef struct 19 { 20 pid_t pid;//pid號 21 unsigned int utime; //該任務在用戶態運行的時間,單位為jiffies 22 unsigned int stime; //該任務在核心態運行的時間,單位為jiffies 23 unsigned int cutime;//所有已死線程在用戶態運行的時間,單位為jiffies 24 unsigned int cstime; //所有已死在核心態運行的時間,單位為jiffies 25 }process_cpu_occupy_t; 26 27 int get_phy_mem(const pid_t p);//獲取占用物理內存 28 int get_total_mem();//獲取系統總內存 29 unsigned int get_cpu_total_occupy();//獲取總的CPU時間 30 unsigned int get_cpu_process_occupy(const pid_t p);//獲取進程的CPU時間 31 const char* get_items(const char* buffer,int ie);//取得緩沖區指定項的起始地址 32 33 extern float get_pcpu(pid_t p);//獲取進程CPU占用 34 extern float get_pmem(pid_t p);//獲取進程內存占用 35 extern int get_rmem(pid_t p);//獲取真實物理內存 36 37 38 #ifdef __cplusplus
1 get_cpu.c 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <unistd.h> //頭文件 6 #include <assert.h> 7 #include "get_cpu.h" 8 9 int get_phy_mem(const pid_t p) 10 { 11 char file[64] = {0};//文件名 12 13 FILE *fd; //定義文件指針fd 14 char line_buff[256] = {0}; //讀取行的緩沖區 15 sprintf(file,"/proc/%d/status",p);//文件中第11行包含着 16 17 fprintf (stderr, "current pid:%d\n", p); 18 fd = fopen (file, "r"); //以R讀的方式打開文件再賦給指針fd 19 20 //獲取vmrss:實際物理內存占用 21 int i; 22 char name[32];//存放項目名稱 23 int vmrss;//存放內存峰值大小 24 for (i=0;i<VMRSS_LINE-1;i++) 25 { 26 fgets (line_buff, sizeof(line_buff), fd); 27 }//讀到第15行 28 fgets (line_buff, sizeof(line_buff), fd);//讀取VmRSS這一行的數據,VmRSS在第15行 29 sscanf (line_buff, "%s %d", name,&vmrss); 30 fprintf (stderr, "====%s:%d====\n", name,vmrss); 31 fclose(fd); //關閉文件fd 32 return vmrss; 33 } 34 35 int get_rmem(pid_t p) 36 { 37 return get_phy_mem(p); 38 } 39 40 41 int get_total_mem() 42 { 43 char* file = "/proc/meminfo";//文件名 44 45 FILE *fd; //定義文件指針fd 46 char line_buff[256] = {0}; //讀取行的緩沖區 47 fd = fopen (file, "r"); //以R讀的方式打開文件再賦給指針fd 48 49 //獲取memtotal:總內存占用大小 50 int i; 51 char name[32];//存放項目名稱 52 int memtotal;//存放內存峰值大小 53 fgets (line_buff, sizeof(line_buff), fd);//讀取memtotal這一行的數據,memtotal在第1行 54 sscanf (line_buff, "%s %d", name,&memtotal); 55 fprintf (stderr, "====%s:%d====\n", name,memtotal); 56 fclose(fd); //關閉文件fd 57 return memtotal; 58 } 59 60 float get_pmem(pid_t p) 61 { 62 int phy = get_phy_mem(p); 63 int total = get_total_mem(); 64 float occupy = (phy*1.0)/(total*1.0); 65 fprintf(stderr,"====process mem occupy:%.6f\n====",occupy); 66 return occupy; 67 } 68 69 unsigned int get_cpu_process_occupy(const pid_t p) 70 { 71 char file[64] = {0};//文件名 72 process_cpu_occupy_t t; 73 74 FILE *fd; //定義文件指針fd 75 char line_buff[1024] = {0}; //讀取行的緩沖區 76 sprintf(file,"/proc/%d/stat",p);//文件中第11行包含着 77 78 fprintf (stderr, "current pid:%d\n", p); 79 fd = fopen (file, "r"); //以R讀的方式打開文件再賦給指針fd 80 fgets (line_buff, sizeof(line_buff), fd); //從fd文件中讀取長度為buff的字符串再存到起始地址為buff這個空間里 81 82 sscanf(line_buff,"%u",&t.pid);//取得第一項 83 char* q = get_items(line_buff,PROCESS_ITEM);//取得從第14項開始的起始指針 84 sscanf(q,"%u %u %u %u",&t.utime,&t.stime,&t.cutime,&t.cstime);//格式化第14,15,16,17項 85 86 fprintf (stderr, "====pid%u:%u %u %u %u====\n", t.pid, t.utime,t.stime,t.cutime,t.cstime); 87 fclose(fd); //關閉文件fd 88 return (t.utime + t.stime + t.cutime + t.cstime); 89 } 90 91 92 unsigned int get_cpu_total_occupy() 93 { 94 FILE *fd; //定義文件指針fd 95 char buff[1024] = {0}; //定義局部變量buff數組為char類型大小為1024 96 total_cpu_occupy_t t; 97 98 fd = fopen ("/proc/stat", "r"); //以R讀的方式打開stat文件再賦給指針fd 99 fgets (buff, sizeof(buff), fd); //從fd文件中讀取長度為buff的字符串再存到起始地址為buff這個空間里 100 /*下面是將buff的字符串根據參數format后轉換為數據的結果存入相應的結構體參數 */ 101 char name[16];//暫時用來存放字符串 102 sscanf (buff, "%s %u %u %u %u", name, &t.user, &t.nice,&t.system, &t.idle); 103 104 105 fprintf (stderr, "====%s:%u %u %u %u====\n", name, t.user, t.nice,t.system, t.idle); 106 fclose(fd); //關閉文件fd 107 return (t.user + t.nice + t.system + t.idle); 108 } 109 110 111 float get_pcpu(pid_t p) 112 { 113 unsigned int totalcputime1,totalcputime2; 114 unsigned int procputime1,procputime2; 115 totalcputime1 = get_cpu_total_occupy(); 116 procputime1 = get_cpu_process_occupy(p); 117 usleep(500000);//延遲500毫秒 118 totalcputime2 = get_cpu_total_occupy(); 119 procputime2 = get_cpu_process_occupy(p); 120 float pcpu = 100.0*(procputime2 - procputime1)/(totalcputime2 - totalcputime1); 121 fprintf(stderr,"====pcpu:%.6f\n====",pcpu); 122 return pcpu; 123 } 124 125 const char* get_items(const char* buffer,int ie) 126 { 127 assert(buffer); 128 char* p = buffer;//指向緩沖區 129 int len = strlen(buffer); 130 int count = 0;//統計空格數 131 if (1 == ie || ie < 1) 132 { 133 return p; 134 } 135 int i; 136 137 for (i=0; i<len; i++) 138 { 139 if (' ' == *p) 140 { 141 count++; 142 if (count == ie-1) 143 { 144 p++; 145 break; 146 } 147 } 148 p++; 149 } 150 151 return p; 152 }