一、获取内存信息的方法
linux内核提供了一种通过/proc文件系统来在运行时访问内核内部数据结构,改变内核设置的机制,各种硬件平台上的linux系统的/proc文件系统的基本概念都是相同的。
/proc文件系统是一种内核和内核模块用来向进程发送信息的机制。这个伪文件系统可以和内核内部的数据结构进行交互,获取实时的进程信息。注意,/proc文件系统是存储与内存而不是硬盘,/proc虚拟文件系统实质是以文件系统的形式访问内核数据的接口。
/proc/meminfo
linux系统中/proc/meminfo这个文件用来记录了系统内存使用的详细情况。其中top,free命令中的数据是通过这个文件中的信息计算并按照特定的格式进行显示。
命令解析
MemTotal: 所有内存(RAM)大小,减去一些预留空间和内核的大小。MemFree: 完全没有用到的物理内存,lowFree+highFreeMemAvailable: 在不使用交换空间的情况下,启动一个新的应用最大可用内存的大小,计算方式:MemFree+Active(file)+Inactive(file)-(watermark+min(watermark,Active(file)+Inactive(file)/2))Buffers: 块设备所占用的缓存页,包括:直接读写块设备以及文件系统元数据(metadata),比如superblock使用的缓存页。Cached: 表示普通文件数据所占用的缓存页。SwapCached: swap cache中包含的是被确定要swapping换页,但是尚未写入物理交换区的匿名内存页。那些匿名内存页,比如用户进程malloc申请的内存页是没有关联任何文件的,如果发生swapping换页,这类内存会被写入到交换区。Active: active包含active anon和active fileInactive: inactive包含inactive anon和inactive fileActive(anon): anonymous pages(匿名页),用户进程的内存页分为两种:与文件关联的内存页(比如程序文件,数据文件对应的内存页)和与内存无关的内存页(比如进程的堆栈,用malloc申请的内存),前者称为file pages或mapped pages,后者称为匿名页。Inactive(anon): 见上Active(file): 见上Inactive(file): 见上SwapTotal: 可用的swap空间的总的大小(swap分区在物理内存不够的情况下,把硬盘空间的一部分释放出来,以供当前程序使用)SwapFree: 当前剩余的swap的大小Dirty: 需要写入磁盘的内存去的大小Writeback: 正在被写回的内存区的大小AnonPages: 未映射页的内存的大小Mapped: 设备和文件等映射的大小Slab: 内核数据结构slab的大小SReclaimable: 可回收的slab的大小SUnreclaim: 不可回收的slab的大小PageTables: 管理内存页页面的大小NFS_Unstable: 不稳定页表的大小VmallocTotal: Vmalloc内存区的大小VmallocUsed: 已用Vmalloc内存区的大小VmallocChunk: vmalloc区可用的连续最大快的大小
内存的使用率的计算方法
二. proc/stat
proc/stat节点记录的是系统进程整体的统计信息
wyy$cat /proc/stat//CPU指标:user,nice, system, idle, iowait, irq, softirqcpu130216 19944 162525 1491240 3784 24749 17773 0 0 0cpu0 40321 11452 49784 403099 2615 6076 6748 0 0 0cpu1 26585 2425 36639 151166 404 2533 3541 0 0 0cpu2 22555 2957 31482 152460 330 2236 2473 0 0 0cpu3 15232 1243 20945 153740 303 1985 3432 0 0 0cpu4 5903 595 6017 157410 30 10959 605 0 0 0cpu5 4716 380 3794 157909 23 118 181 0 0 0cpu6 8001 515 8995 157571 48 571 180 0 0 0cpu7 6903 377 4869 157885 31 271 613 0 0 0 intr ...ctxt 22523049btime 1500827856processes 23231procs_running 1procs_blocked 0softirq 3552900 843593 733695 19691 93143 468832 12783 257382 610426 0 513355
有以上信息能够得出 cpu是4核的,cpu这项相应信息例如以下
cpu user nice system idle iowait irq softirq steal guest guest_nice
user:用户态的CPU时间
nice:低优先级程序所占用的用户态的cpu时间。
system:系统态的CPU时间
idle:CPU空暇的时间(不包括IO等待)
iowait:等待IO响应的时间
irq:处理硬件中断的时间
softirq:处理软中断的时间
steal:其它系统所花的时间(个人理解是针对虚拟机)
guest:执行时间为客户操作系统下的虚拟CPU控制(个人理解是访客控制CPU的时间)
guest_nice:低优先级程序所占用的用户态的cpu时间。
三、c语言程序测试内存与CPU使用率
#include#include#includetypedef struct PACKED //定义一个cpu occupy的结构体{char name[20];//定义一个char类型的数组名name有20个元素unsigned int user; //定义一个无符号的int类型的userunsigned int nice; //定义一个无符号的int类型的niceunsigned int system;//定义一个无符号的int类型的systemunsigned int idle; //定义一个无符号的int类型的idle}CPU_OCCUPY;typedef struct PACKED1 //定义一个mem occupy的结构体{char name[20]; //定义一个char类型的数组名name有20个元素unsigned long total;char name2[20];unsigned long free;}MEM_OCCUPY;/*获取内存使用率*/ int get_memoccupy (MEM_OCCUPY *mem) //对无类型get函数含有一个形参结构体类弄的指针O{FILE *fd;int n;char buff[256];char buff1[256];char buff2[256];char buff3[256];char buff4[256];MEM_OCCUPY *m;m=mem;float mem_use;fd = fopen ("/proc/meminfo", "r");fgets (buff1, sizeof(buff1), fd);printf("%s\n",buff1);int num1 = atoi(buff1+15);printf("%d\n",num1);fgets (buff2, sizeof(buff2), fd);printf("%s\n",buff2);int num2 = atoi(buff2+15);fgets (buff3, sizeof(buff3), fd);printf("%s\n",buff3);int num3 = atoi(buff3+15);fgets (buff4, sizeof(buff4), fd);// sscanf (buff, "%s %u %s", m->name, &m->total, m->name2);printf("%s\n",buff4);int num4 = atoi(buff4+15);fgets (buff, sizeof(buff), fd); //从fd文件中读取长度为buff的字符串再存到起始地址为buff这个空间里printf("%s\n",buff);int num5 = atoi(buff+15);// 内存使用率(MEMUsedPerc)=100*(MemTotal-MemFree-Buffers-Cached)/MemTotalmem_use = (float)100*(num1-num2-num5-num4)/num1;printf("内存使用率为:%.2f%%\n",mem_use);fclose(fd); //关闭文件fd}/*获取cpu使用率*/ float cal_cpuoccupy (CPU_OCCUPY *o, CPU_OCCUPY *n){unsigned long od, nd; unsigned long id, sd; float cpu_use = 0; od = (unsigned long) (o->user + o->nice + o->system +o->idle);//第一次(用户+优先级+系统+空闲)的时间再赋给odnd = (unsigned long) (n->user + n->nice + n->system +n->idle);//第二次(用户+优先级+系统+空闲)的时间再赋给ndid = (unsigned long) (n->user - o->user);//用户第一次和第二次的时间之差再赋给idsd = (unsigned long) (n->system - o->system);//系统第一次和第二次的时间之差再赋给sdif((nd-od) != 0){ cpu_use = (float)((sd+id)*100)/(nd-od); //((用户+系统)乖100)除(第一次和第二次的时间差)再赋给g_cpu_used } else{ cpu_use = 0; } printf("cpu使用率为:%1.2f%%\n",cpu_use); return cpu_use; }void get_cpuoccupy (CPU_OCCUPY *cpust) //对无类型get函数含有一个形参结构体类弄的指针O{ FILE *fd;int n;char buff[256];CPU_OCCUPY *cpu_occupy; cpu_occupy=cpust; fd = fopen ("/proc/stat", "r");fgets (buff, sizeof(buff), fd);sscanf (buff, "%s %u %u %u %u", cpu_occupy->name, &cpu_occupy->user, &cpu_occupy->nice,&cpu_occupy->system, &cpu_occupy->idle); fclose(fd);}int main(){ CPU_OCCUPY cpu_stat1;CPU_OCCUPY cpu_stat2;MEM_OCCUPY mem_stat; float cpu; //获取内存 get_memoccupy ((MEM_OCCUPY *)&mem_stat); //第一次获取cpu使用情况 get_cpuoccupy((CPU_OCCUPY *)&cpu_stat1); sleep(10); //第二次获取cpu使用情况get_cpuoccupy((CPU_OCCUPY *)&cpu_stat2); //计算cpu使用率 cpu = cal_cpuoccupy ((CPU_OCCUPY *)&cpu_stat1, (CPU_OCCUPY *)&cpu_stat2); return 0;}
测试结果:
四、shell脚本
#!/bin/bash###############################################Filename: hellome.sh#Description: 监控cpu、磁盘、内存使用率##############################################logFile=/tmp/jiankong.log#获取报警时间now_time=`date '+%F %T'`#获取cpu使用率#cpuUsage=`top -b -n5 | fgrep "Cpu(s)" | tail -1 | awk -F'id,' '{split($1, vs, ","); v=vs[length(vs)]; sub(/\s+/, "", v);sub(/\s+/, "", v); printf "%d", 100-v;}'`cpuUsage=`top -b -n1 | fgrep "Cpu" | awk '{print 100-$8,"%"}'`#统计内存使用率#mem_used_persent=`free -m | awk -F '[ :]+' 'NR==2{printf "%d", ($3)/$2*100}'`mem_used_persent=`free -m | fgrep "Mem" | awk '{printf "%d", ($3)/$2*100}'`#获取磁盘使用率#data_name="/dev/vda1"#diskUsage=`df -h | grep $data_name | awk -F '[ %]+' '{print $5}'`diskUsage=`df -h | fgrep "/dev/vda1" | awk '{print $5}'`function check(){echo "当前时间:"${now_time}echo -e "CPU使用率:${cpuUsage}%\n磁盘使用率:${diskUsage}%\n内存使用率:${mem_used_persent}%"#if [[ "$cpuUsage" > 80 ]] || [[ "$diskUsage" > 80 ]] || [[ "$mem_used_persent" > 80 ]];then#echo "报警时间:${now_time}" > $logFile#echo -e "CPU使用率:${cpuUsage}% --> 磁盘使用率:${diskUsage}% --> 内存使用率:${mem_used_persent}%" >> $logFile#fi}function main(){check}main
脚本结果如下:
脚本是利用top:
top命令:
根据上图所显示的结果可以看出,CPU占用数据在第三行,所以我现在只需要第三行的数据。第三行的数据里有关键字“Cpu(s)”,使用fgrep命令可以根据关键字按行查找信息。所以此时我的命令变成了“top -n1 | fgrep “Cpu(s)””,运行结果如下图所示:
上图显示的是CPU的各类占用率:
us:用户空间占用CPU百分比
sy:内核空间占用CPU百分比
ni:用户进程空间内改变过优先级的进程占用CPU百分比
id:空闲CPU百分比
wa:等待输入输出的CPU时间百分比
hi:硬件中断
si:软件中断
st:虚拟机占用物理机的百分比
我想要获得CPU当前占用率,只需要使用100减去空闲CPU即可。
使用awk命令获取空闲CPU。awk默认按空格切割字符串,根据下图显示可以确认id的数值在第8个,使用100减去该值即可获取当前CPU占用率,所以使用命令“top -n1 | fgrep “Cpu(s)” | awk ‘{print 100-$8}’”,显示如下图所示:
注意:命令使用英文,中文报错