linux获取内存与cpu使用率(附有C语言源码与shell脚本)

文章介绍了在Linux系统中通过/proc文件系统获取内存信息和CPU使用率的细节,包括/proc/meminfo文件的内容及其各个字段的含义,以及如何通过C语言程序和shell脚本来监测内存和CPU的使用情况。此外,文章还解释了CPU使用率的计算方法。
摘要由CSDN通过智能技术生成

一、获取内存信息的方法

linux内核提供了一种通过/proc文件系统来在运行时访问内核内部数据结构,改变内核设置的机制,各种硬件平台上的linux系统的/proc文件系统的基本概念都是相同的。
/proc文件系统是一种内核和内核模块用来向进程发送信息的机制。这个伪文件系统可以和内核内部的数据结构进行交互,获取实时的进程信息。注意,/proc文件系统是存储与内存而不是硬盘,/proc虚拟文件系统实质是以文件系统的形式访问内核数据的接口。

/proc/meminfo
linux系统中/proc/meminfo这个文件用来记录了系统内存使用的详细情况。其中top,free命令中的数据是通过这个文件中的信息计算并按照特定的格式进行显示。

在这里插入图片描述

命令解析

MemTotal: 所有内存(RAM)大小,减去一些预留空间和内核的大小。
MemFree: 完全没有用到的物理内存,lowFree+highFree
MemAvailable: 在不使用交换空间的情况下,启动一个新的应用最大可用内存的大小,计算方式: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 file
Inactive: inactive包含inactive anon和inactive file
Active(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, softirq
cpu  130216 19944 162525 1491240 3784 24749 17773 0 0 0
cpu0 40321 11452 49784 403099 2615 6076 6748 0 0 0
cpu1 26585 2425 36639 151166 404 2533 3541 0 0 0
cpu2 22555 2957 31482 152460 330 2236 2473 0 0 0
cpu3 15232 1243 20945 153740 303 1985 3432 0 0 0
cpu4 5903 595 6017 157410 30 10959 605 0 0 0
cpu5 4716 380 3794 157909 23 118 181 0 0 0
cpu6 8001 515 8995 157571 48 571 180 0 0 0
cpu7 6903 377 4869 157885 31 271 613 0 0 0
 
intr ...
ctxt 22523049
btime 1500827856
processes 23231
procs_running 1
procs_blocked 0
softirq 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<unistd.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct PACKED         //定义一个cpu occupy的结构体
{

char name[20];      //定义一个char类型的数组名name有20个元素

unsigned int user; //定义一个无符号的int类型的user

unsigned int nice; //定义一个无符号的int类型的nice

unsigned int system;//定义一个无符号的int类型的system

unsigned 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)/MemTotal

    mem_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);//第一次(用户+优先级+系统+空闲)的时间再赋给od    
    nd = (unsigned long) (n->user + n->nice + n->system +n->idle);//第二次(用户+优先级+系统+空闲)的时间再赋给nd      
    id = (unsigned long) (n->user - o->user);    //用户第一次和第二次的时间之差再赋给id    
    sd = (unsigned long) (n->system - o->system);//系统第一次和第二次的时间之差再赋给sd  
    if((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}’”,显示如下图所示:
在这里插入图片描述
注意:命令使用英文,中文报错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值