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 }

感觉就像自己手动实现top命令一样。

Linux下用程序实现统计cpu和内存的利用率的更多相关文章

  1. linux下c程序调用reboot函数实现直接重启【转】

    转自:http://www.blog.chinaunix.net/uid-20564848-id-73878.html linux下c程序调用reboot函数实现直接重启 当然你也可以直接调用syst ...

  2. Linux下C程序的编辑,编译和运行以及调试

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...

  3. 位图文件(BMP)格式以及Linux下C程序实现(转)

    源:位图文件(BMP)格式以及Linux下C程序实现 说到图片,位图(Bitmap)当然是最简单的,它是Windows显示图片的基本格式,其文件扩展名为*.BMP.由于没有经过任何的压缩,故BMP图 ...

  4. Linux下C程序内存泄露检测

    在linux下些C语言程序,最大的问题就是没有一个好的编程IDE,当然想kdevelop等工具都相当的强大,但我还是习惯使用kdevelop工具,由于没有一个习惯的编程IDE,内存检测也就成了在lin ...

  5. Linux下C程序的内存映像

    2.Linux下C程序的内存映像 2.1. 代码段.只读数据段(1)对应着程序中的代码(函数),代码段在Linux中又叫文本段(.text)(2)只读数据段就是在程序运行期间只能读不能写的数据,con ...

  6. linux ps命令,查看某进程cpu和内存占用率情况, linux ps命令,查看进程cpu和内存占用率排序。 不指定

    背景:有时需要单看某个进程的CPU及占用情况,有时需要看整体进程的一个占用情况.一. linux ps命令,查看某进程cpu和内存占用率情况[root@test vhost]# ps auxUSER  ...

  7. 【转】Linux下进程/程序网络带宽占用情况查看工具 -- NetHogs

    http://www.cnblogs.com/carbon3/p/5930803.html 之前VPS侦探曾经介绍过流量带宽相关的工具如:iftop.vnstat,这几个都是统计和监控网卡流量的.但是 ...

  8. linux下c程序的链接、装载和库(1)

    读完<程序员的自我修养--链接.装载和库>相关章节,想来总结一下,若有错误,请指正,多谢. 1. 什么叫目标文件? 你的工程里有很多xxx.c这样的源文件,这些文件是文本文件,只有人能够认 ...

  9. Linux下进程/程序网络带宽占用情况查看工具 -- NetHogs

    http://www.vpser.net/manage/nethogs.html   来自.  最后略有修改 之前VPS侦探曾经介绍过流量带宽相关的工具如:iftop.vnstat,这几个都是统计和监 ...

随机推荐

  1. ThreadLocal源码分析:(三)remove()方法

    在ThreadLocal的get(),set()的时候都会清除线程ThreadLocalMap里所有key为null的value. 而ThreadLocal的remove()方法会先将Entry中对k ...

  2. LeetCode & Q119-Pascal's Triangle II-Easy

    Description: Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3 ...

  3. 自动化服务部署(二):Linux下安装jenkins

    jenkins是一个Java开发的开源持续集成工具,广泛用于项目开发,具有自动化构建.测试和部署等功能,它的运行需要Java环境. 上篇博客介绍了Linux下安装JDK的步骤,这篇博客,介绍下Linu ...

  4. 以太坊挖矿源码:clique算法

    上文我们总结了以太坊最主要的共识算法:ethash算法,本文将重点分析以太坊的另一个共识算法:clique. 关键字:clique,共识算法,puppeth,以太坊地址原理,区块校验,认证结点,POA ...

  5. SpringBoot的RestController vs @ResponseBody + @Controller

    @Controller和@RestController的区别?官方文档:@RestController is a stereotype annotation that combines @Respon ...

  6. Angular 学习笔记 ( PWA + App Shell )

    PWA (Progressive Web Apps) 是未来网页设计的方向. 渐进式网站. Angular v5 开始支持 pwa 网站 (所谓支持意思是说有一些 build in 的方法和规范去实现 ...

  7. gradle入门(1-2)gradle的依赖管理

    Gradle支持以下仓库格式: Ivy仓库 Maven仓库 Flat directory仓库 一.添加仓库 1.添加Ivy仓库 1.1.通过URL地址添加一个Ivy仓库 我们可以将以下代码片段加入到b ...

  8. centos6.5时间相关

    时间同步 service ntpdate start 开启网络时间同步

  9. 百度echarts使用--y轴label数字太长难以全部显示

    问题: 今天遇到个小问题,我们系统前端呈现使用了百度echarts.在绘制折线图的时候,因为数字过大,导致显示出现了问题. 解决方案: 左边y轴的值默认是根据我们填充进去的值来默认分割的,因为原始值就 ...

  10. [Kaggle] dogs-vs-cats之模型训练

    上一步建立好模型之后,现在就可以训练模型了. 主要代码如下: import sys #将当期路径加入系统path中 sys.path.append("E:\\CODE\\Anaconda\\ ...