计算进程消费cpu和内存
Linux下没有直接可以调用系统函数知道CPU占用和内存占用。那么如何知道CPU和内存信息呢。只有通过proc伪文件系统来实现。
proc伪文件就不介绍了,只说其中4个文件。一个是/proc/stat,/proc/meminfo,/proc/<pid>/status,/proc/<pid>/stat
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时间。
下面粘贴一下本人写的调用接口
//get_cpu.h #ifndef __GET_CPU__ #define __GET_CPU__ #include <stdio.h> #include <stdlib.h> #include <iostream> #include <unistd.h> #include <assert.h> #include <algorithm> #include <vector> #define PROCESS_ITEM 14 typedef struct { pid_t pid; unsigned int utime; //live thread at user status (jiffies) unsigned int stime; //live thread at kernel status unsigned int cutime; //killed thread at user status unsigned int cstime; //killed thread at kernel status }process_cpu_occupy; vector<unsigned int>total_cpu_time; unsigned int get_cpu_process_occupy(const pid_t p); const char* get_items(const char* buffer,int ie); extern float get_cpu(pid_t p); extern unsigned int get_total_cpu(); #endif
//get_cpu.cc #include "get_cpu.h" const char* get_items(const char* buffer,int ie) { assert(buffer); char* p = buffer; int len = strlen(buffer); int count = 0; int i; if (1 == ie || ie < 1) { return p; } for (i=0; i<len; i++) { if (' ' == *p) { count++; if (count == ie-1) { p++; break; } } p++; } return p; } unsigned int get_cpu_process_occupy(const pid_t p) { char file[64] = {0}; process_cpu_occupy t; FILE *fd; char line_buff[1024] = {0}; sprintf(file,"/proc/%d/stat",p); fd = fopen (file, "r"); fgets (line_buff, sizeof(line_buff), fd); sscanf(line_buff,"%u",&t.pid); char* q = get_items(line_buff,PROCESS_ITEM); sscanf(q,"%u %u %u %u",&t.utime,&t.stime,&t.cutime,&t.cstime); fclose(fd); return (t.utime + t.stime + t.cutime + t.cstime); } unsigned int get_cpu(pid_t p,int index) { unsigned int procputime; procputime = get_cpu_process_occupy(p); std::cout<<"procputime :"<<procputime<<endl; switch(index){ case 1: total_cpu_time.clear(); total_cpu_time.push_back(procputime); break; case 2: total_cpu_time.push_back(procputime); break; case 3: total_cpu_time.push_back(procputime); break; default: DSTREAM_WARN("index is errno"); break; } return procputime; } unsigned int get_total_cpu(){ int length=total_cpu_time.size(); unsigned int total_time=0; if(length != 3){ DSTREAM_WARN("get total cpu failed"); return -1; } for(int i=0;i<length;i++){ total_time+=total_cpu_time[i]; } return total_time; }
#ifndef __GET_MEM__ #define __GET_MEM__ #include <stdio.h> #include <stdlib.h> #include <iostream> #include <unistd.h> #include <assert.h> #include <algorithm> #include <vector> #define VMRSS_LINE 15 //VMRSS line vector<int>total_memory; int get_phy_mem(const pid_t p); extern int get_mem(pid_t p); extern int get_total_memory(); extern int get_total_mem(); #endif
//get_mem.cc #include "get_mem.h" int get_phy_mem(const pid_t p) { char file[64] = {0}; FILE *fd; char line_buff[256] = {0}; sprintf(file,"/proc/%d/status",p); fd = fopen (file, "r"); int i; char name[32]; int vmrss; for (i=0;i<VMRSS_LINE-1;i++) { fgets (line_buff, sizeof(line_buff), fd); } fgets (line_buff, sizeof(line_buff), fd); sscanf (line_buff, "%s %d", name,&vmrss); fclose(fd); return vmrss; } int get_mem(pid_t p,int index) { int procmemory; promemory=get_phy_mem(p); switch(index){ case 1: total_memory.clear(); total_memory.push_back(promemory); break; case 2: total_memory.push_back(promemory); break; case 3: total_memory.push_back(promemory); break; default: DSTREAM_WARN("index is errno"); break; } return promemory; } //importer+aggregater+exporter int get_total_memory(){ int length=total_memory.size(); int total_mem=0; if(length != 3){ DSTREAM_WARN("get total cpu failed"); return -1; } for(int i=0;i<length;i++){ total_mem+=total_memory[i]; } return total_mem; } //total memory int get_all_mem() { char* file = "/proc/meminfo"; FILE *fd; char line_buff[256] = {0}; fd = fopen (file, "r"); int i; char name[32]; int memtotal; fgets (line_buff, sizeof(line_buff), fd); sscanf (line_buff, "%s %d", name,&memtotal); fclose(fd); return memtotal; }